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

dummy-ups.c

/* dummy-ups.c - new testing driver

   Copyright (C) 2005  Arnaud Quette <http://arnaud.quette.free.fr/contact.html>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include "main.h"
#include "parseconf.h"
#include "dummy-ups.h"

static int setvar(const char *varname, const char *val);
static int parse_data_file(int upsfd);
static dummy_info_t *find_info(const char *varname);
static int is_valid_data(const char* varname);
static int is_valid_value(const char* varname, const char *value);

void upsdrv_initinfo(void)
{
      dummy_info_t *item;

      /* Initialise basic essential variables */
      for ( item = nut_data ; item->info_type != NULL ; item++ ) {
            if (item->drv_flags & DU_FLAG_INIT) {
                  dstate_setinfo(item->info_type, "%s", item->default_value);
                  dstate_setflags(item->info_type, item->info_flags);

                  /* Set max length for strings, if needed */
                  if (item->info_flags & ST_FLAG_STRING)
                        dstate_setaux(item->info_type, item->info_len);
            }
      }

      /* Now get user's defined variables */
      if (parse_data_file(upsfd) < 0)
            upslogx(LOG_NOTICE, "Unable to parse the definition file %s", device_path);

      /* Initialize handler */
      upsh.setvar = setvar;

      dstate_dataok();
}

void upsdrv_updateinfo(void)
{
      upsdebugx(1, "upsdrv_updateinfo...");

      sleep(1);

      /* simply avoid driver staleness */
      status_init();
      status_set(dstate_getinfo("ups.status"));
      status_commit();

      dstate_dataok();
}

void upsdrv_shutdown(void)
{
      fatalx(EXIT_FAILURE, "shutdown not supported");
}

/*
static int instcmd(const char *cmdname, const char *extra)
{
      if (!strcasecmp(cmdname, "test.battery.stop")) {
            ser_send_buf(upsfd, ...);
            return STAT_INSTCMD_HANDLED;
      }

      upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
      return STAT_INSTCMD_UNKNOWN;
}
*/

void upsdrv_help(void)
{
}

/* list flags and values that you want to receive via -x */
void upsdrv_makevartable(void)
{
      /* allow '-x xyzzy' */
      /* addvar(VAR_FLAG, "xyzzy", "Enable xyzzy mode"); */

      /* allow '-x foo=<some value>' */
      /* addvar(VAR_VALUE, "foo", "Override foo setting"); */
}

void upsdrv_banner(void)
{
      printf("Network UPS Tools - Dummy UPS driver %s (%s)\n\n", 
            DRV_VERSION, UPS_VERSION);
}

void upsdrv_initups(void)
{
      /* Nothing to do here... */
}

void upsdrv_cleanup(void)
{
      /* Nothing to do here... */
}


static int setvar(const char *varname, const char *val)
{
      dummy_info_t *item;

      upsdebugx(2, "entering setvar(%s, %s)", varname, val);

      if (!strncmp(varname, "ups.status", 10)) {
            status_init();
             /* FIXME: split and check values (support multiple values) */
            status_set(val);
            status_commit();

            return STAT_SET_HANDLED;
      }

      /* Check variable validity */
      if (!is_valid_data(varname)) {
            upsdebugx(2, "setvar: invalid variable name (%s)", varname);

            return STAT_SET_UNKNOWN;
      }

      /* Check value validity */
      if (!is_valid_value(varname, val)) {
            upsdebugx(2, "setvar: invalid value (%s) for variable (%s)", val, varname);

            return STAT_SET_UNKNOWN;
      }

      dstate_setinfo(varname, "%s", val);

      if ( (item = find_info(varname)) != NULL) {
            dstate_setflags(item->info_type, item->info_flags);

            /* Set max length for strings, if needed */
            if (item->info_flags & ST_FLAG_STRING)
                  dstate_setaux(item->info_type, item->info_len);
      }

      return STAT_SET_HANDLED;
}

/*************************************************/
/*               Support functions               */
/*************************************************/

/* find info element definition in info array */
static dummy_info_t *find_info(const char *varname)
{
      dummy_info_t *item;

      for ( item = nut_data ; item->info_type != NULL ; item++ )  {
            if (!strcasecmp(item->info_type, varname))
                  return item;
      }

      upsdebugx(2, "find_info: unknown variable: %s\n", varname);

      return NULL;
}

/* check if data exists */
static int is_valid_data(const char* varname)
{
      dummy_info_t *item;

      if ( (item = find_info(varname)) != NULL) {
                  return 1;
      }

      return 0;
}

/* check if data's value validity */
static int is_valid_value(const char* varname, const char *value)
{
      dummy_info_t *item;

      if ( (item = find_info(varname)) != NULL) {
            /* FIXME: test enum or bound against value */
            return 1;
      }

      return 0;
}

/* called for fatal errors in parseconf like malloc failures */
static void upsconf_err(const char *errmsg)
{
      upslogx(LOG_ERR, "Fatal error in parseconf(ups.conf): %s", errmsg);
}

static int parse_data_file(int upsfd)
{
      char  fn[SMALLBUF];
      char  *ptr;
      PCONF_CTX_t ctx;

      if (device_path[0] == '/')
            snprintf(fn, sizeof(fn), "%s", device_path);
      else
            snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path);

      pconf_init(&ctx, upsconf_err);

      if (!pconf_file_begin(&ctx, fn))
            fatalx(EXIT_FAILURE, "Can't open dummy-ups definition file %s: %s",
                  fn, ctx.errmsg);

      while (pconf_file_next(&ctx)) {
            if (pconf_parse_error(&ctx)) {
                  upsdebugx(2, "Parse error: %s:%d: %s",
                        fn, ctx.linenum, ctx.errmsg);
                  continue;
            }

            /* Check if we have something to process */
            if (ctx.numargs < 1)
                  continue;

            /* Remove the ":" after the variable name */
            if ((ptr = strchr(ctx.arglist[0], ':')) != NULL)
                  *ptr = '\0';

            upsdebugx(2, "parse_data_file: variable \"%s\" with %d args", ctx.arglist[0], ctx.numargs);

            /* skip the driver.* collection data */
            if (!strncmp(ctx.arglist[0], "driver.", 7)) {
                  upsdebugx(2, "parse_data_file: skipping %s", ctx.arglist[0]);
                  continue;
            }
            else
                  upsdebugx(2, "parse_data_file: %s is not a driver. var", ctx.arglist[0]);

            /* From there, we get varname in arg[0], and values in other arg[1...x] */
            /* FIXME: iteration on arg[2, 3, ...]
                  if ST_FLAG_STRING => all args are the value
                  if ups.status, each arg is a value to be set (ie OB LB) + check against enum
                  else int/float values need to be check against bound/enum
            */
            if (setvar(ctx.arglist[0], ctx.arglist[1]) == STAT_SET_UNKNOWN)
                  upsdebugx(2, "parse_data_file: can't add \"%s\" with value \"%s\"",
                        ctx.arglist[0], ctx.arglist[1]);
            else
                  upsdebugx(2, "parse_data_file: added \"%s\" with value \"%s\"",
                        ctx.arglist[0], ctx.arglist[1]);
      }

      return 1;
}

Generated by  Doxygen 1.6.0   Back to index