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

confp.c

Go to the documentation of this file.
/*
   Name: $RCSfile: confp.c,v $
   Author: Alan Moran
   $Date: 2005/11/26 15:21:09 $
   $Revision: 1.26 $
   $Id: confp.c,v 1.26 2005/11/26 15:21:09 a_j_moran Exp $

   Legal Notice:

   This program is free software; you can redistribute it and/or
   modify it under the terms of the license contained in the
   COPYING file that comes with this distribution.

*/

/**
   @file

   @brief XML parser that reads configuration file.

   The purpose of the configuration parser is to parse the rapple configuration
   file in order to populate variables to be made available to other modules.
   In the process the well-formedness of the configuration file is verified and
   some minor processing of configuration parameters takes place.

*/

#include <expat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "globals.h"
#include "config.h"
#include "memory.h"

static rpl_str_t cfg_log_file = NULL;
static rpl_str_t cfg_RPL_LOG_LEVEL = NULL;
static rpl_str_t cfg_conf_filename = NULL;
static rpl_str_t cfg_ds_basedir = NULL;
static rpl_str_t cfg_srcdir = NULL;
static rpl_str_t cfg_webdir = NULL;
static rpl_str_t cfg_tidy_conf = NULL;
static rpl_str_t cfg_trf_tpl_domain = NULL;
static rpl_str_t cfg_trf_tpl_xslt = NULL;
static rpl_str_t cfg_trf_catalog = NULL;
static rpl_str_t cfg_linkchecker_xslt = NULL;
static rpl_str_t cfg_linkchecker_html_report= NULL;
static rpl_str_t cfg_linkchecker_xml_report= NULL;
static rpl_str_t cfg_dg_dir = NULL;
static rpl_list cfg_dg_dir_names;
static rpl_list cfg_dg_dir_titles;
static rpl_str_t cfg_db_name = NULL;
static rpl_str_t cfg_db_host = NULL;
static rpl_str_t cfg_db_port = NULL;
static rpl_str_t cfg_db_user = NULL;
static rpl_str_t cfg_db_pwd = NULL;


rpl_str_t    cfg_str_buf = RPL_STR_NUL;
int         str_capture, log_flag, ds_flag, src_flag, web_flag, tidy_flag, tpl_flag, dg_flag, lc_flag, db_flag;

static void config_copy_buf(rpl_str_t *dest);
static void config_missing_file_error(rpl_str_t info, rpl_str_t filename);

/**
   Displays an error message when a required file or directory does not exist.

   @param info very brief leader explaining the reason for the error.
   @param filename name of file or directory that is absent.
 */
static
00073 void config_missing_file_error(rpl_str_t info, rpl_str_t filename)
{
      rpl_str_t err_msg;

      assert((info != NULL) && (filename != NULL));

      err_msg = rpl_message_get("CONFIG_STAT_FAILED", info, ": ", filename, RPL_EOM);
      fprintf(stderr, "%s\n", err_msg);
      rpl_log_fatal(err_msg);
}

/**
   Copy the contents of cfg_str_buf into dest. Convenience function used throughout this file.

   @param dest Pointer to return buffer contents.
 */
static
00090 void config_copy_buf(rpl_str_t *dest) {
    size_t length;

    assert(cfg_str_buf != NULL);

    length = strlen(cfg_str_buf) + 1;
    *dest = (rpl_str_t)rpl_me_malloc(length);
    snprintf(*dest, length, "%s", cfg_str_buf);
    str_capture = 0;
    //  rpl_me_free(cfg_str_buf);
}

/**
   Handles start of element event. Passed to XML_SetElementHandler.

   @param data
   @param el
   @param attr
 */
static void
00110 config_start(void *data, const char *el, const char **attr) {
    int i;
    rpl_str_t dir_title = RPL_STR_NUL;
    rpl_str_list_node *lnp;

    if(log_flag && (strcmp(el, "logfile") == 0))
        str_capture = 1;
    if(log_flag && (strcmp(el, "loglevel") == 0))
        str_capture = 1;

    if(ds_flag && (strcmp(el, "basedir") == 0))
        str_capture = 1;
    if(strcmp(el, "srcdir") == 0)
        str_capture = 1;
    if(strcmp(el, "webdir") == 0)
        str_capture = 1;

    if(tidy_flag && (strcmp(el, "config") == 0))
        str_capture = 1;

    if(dg_flag && (strcmp(el, "dir") == 0)) {
        str_capture = 1;
        /* capture title attribute */
        for(i=0; attr[i]; i+=2) {
            if(strcmp(attr[i], "title") == 0) {
                dir_title = (rpl_str_t)rpl_me_malloc(strlen(attr[i+1]) + 1);
                strcpy(dir_title, attr[i+1]);
                lnp = rpl_str_list_create_node(dir_title);
                rpl_list_prepend(&cfg_dg_dir_titles, &lnp->node, lnp);
            }
        }
    }

    if(tpl_flag && (strcmp(el, "domain") == 0))
        str_capture = 1;
    if(tpl_flag && (strcmp(el, "tplXSLT") == 0))
        str_capture = 1;
    if(tpl_flag && (strcmp(el, "catalog") == 0))
        str_capture = 1;

      if(lc_flag && (strcmp(el, "xslt") == 0))
            str_capture = 1;
      if(lc_flag && (strcmp(el, "htmlReport") == 0))
            str_capture = 1;
      if(lc_flag && (strcmp(el, "xmlReport") == 0))
            str_capture = 1;

    if(db_flag && (strcmp(el, "dbname") == 0))
        str_capture = 1;
    if(db_flag && (strcmp(el, "host") == 0))
        str_capture = 1;
    if(db_flag && (strcmp(el, "port") == 0))
        str_capture = 1;
    if(db_flag && (strcmp(el, "username") == 0))
        str_capture = 1;
    if(db_flag && (strcmp(el, "password") == 0))
        str_capture = 1;

    /* if the appropriate flag has already been set */
    if(str_capture) {
        *cfg_str_buf = 0;
    }

    /* acknowledge container element for next pass */
    if(strcmp(el, "logger") == 0)
        log_flag = 1;
    if(strcmp(el, "datastore") == 0)
        ds_flag = 1;
    if(strcmp(el, "tidy") == 0)
        tidy_flag = 1;
    if(strcmp(el, "template") == 0)
        tpl_flag = 1;
    if((strcmp(el, "digest") == 0))
        dg_flag = 1;
    if((strcmp(el, "linkchecker") == 0))
        lc_flag = 1;
    if((strcmp(el, "database") == 0))
        db_flag = 1;
}

/**
   Handles occurence of character text event. Passed to XML_SetCharacterDataHandler.

   @param data
   @param txt
   @param txtlen
c */
static void
00198 config_characters(void *data, const char *txt, int txtlen) {
    if(str_capture)
        strncat(cfg_str_buf, txt, txtlen);
}

/**
   Handles end of element event. Passed to XML_SetElementHandler.

   @param data
   @param el
 */
static void
00210 config_end(void *data, const char *el) {
    int     log_int;
    rpl_str_list_node *lnp;
      rpl_str_t abs_dg_dir = NULL, log_dir = NULL, log_fp = NULL;

    /* capture value data */
    if(log_flag && (strcmp(el,"logfile") == 0))
      {
        config_copy_buf(&cfg_log_file);
            log_dir = strdup(cfg_log_file);
            if((log_fp = strrchr(log_dir, '/')) != NULL)
            {
                  *log_fp = '\0';
                  if(rpl_fs_file_exists(log_dir) < 0)
                        config_missing_file_error("log dir does not exist", log_dir);
                  *log_fp = '/'; /* ensures release of full chunk */
            }
            rpl_me_free(log_dir);
      }

    if(strcmp(el,"srcdir") == 0)
      {
        config_copy_buf(&cfg_srcdir);
            if(rpl_fs_file_exists(cfg_srcdir) < 0)
                  config_missing_file_error("srcdir does not exist", cfg_srcdir);
      }

    if(strcmp(el,"webdir") == 0)
      {
        config_copy_buf(&cfg_webdir);
            if(rpl_fs_file_exists(cfg_webdir) < 0)
                  config_missing_file_error("webdir does not exist", cfg_webdir);
      }

    if(log_flag && (strcmp(el,"loglevel") == 0)) {
        log_int = atoi((rpl_c_str_t)cfg_str_buf);
        /* if outside permissible range then pick a sensible default */
        if((log_int < 1) || (log_int > 5)) {
            cfg_RPL_LOG_LEVEL = "3";
        } else {
            config_copy_buf(&cfg_RPL_LOG_LEVEL);
        }
        rpl_log_set_level(atoi((rpl_c_str_t)cfg_RPL_LOG_LEVEL));
    }

    if(ds_flag && (strcmp(el,"basedir") == 0))
      {
        config_copy_buf(&cfg_ds_basedir);
            if(rpl_fs_file_exists(cfg_ds_basedir) < 0)
                  config_missing_file_error("datastore does not exist", cfg_ds_basedir);
      }

    if(tidy_flag && (strcmp(el,"config") == 0))
        config_copy_buf(&cfg_tidy_conf);

    if(tpl_flag && (strcmp(el,"domain") == 0))
        config_copy_buf(&cfg_trf_tpl_domain);

    if(tpl_flag && (strcmp(el,"tplXSLT") == 0))
      {
        config_copy_buf(&cfg_trf_tpl_xslt);
            if(rpl_fs_file_exists(cfg_trf_tpl_xslt) < 0)
                  config_missing_file_error("XSLT does not exist", cfg_trf_tpl_xslt);
      }

    if(tpl_flag && (strcmp(el,"catalog") == 0))
        config_copy_buf(&cfg_trf_catalog);

      if(lc_flag && (strcmp(el, "xslt") == 0))
            config_copy_buf(&cfg_linkchecker_xslt);
      if(lc_flag && (strcmp(el, "htmlReport") == 0))
            config_copy_buf(&cfg_linkchecker_html_report);
      if(lc_flag && (strcmp(el, "xmlReport") == 0))
            config_copy_buf(&cfg_linkchecker_xml_report);

    if(dg_flag && (strcmp(el, "dir") == 0)) {
            abs_dg_dir = rpl_str_concat(cfg_srcdir, "/", cfg_dg_dir, RPL_STR_EOC);
            if(rpl_fs_file_exists(abs_dg_dir) < 0)
                  config_missing_file_error("digest dir does not exist", abs_dg_dir);
            rpl_me_free(abs_dg_dir);
        config_copy_buf(&cfg_dg_dir);
        lnp = rpl_str_list_create_node(cfg_dg_dir);
        rpl_list_prepend(&cfg_dg_dir_names, &lnp->node, lnp);
    }

    if(db_flag && (strcmp(el,"dbname") == 0))
      {
            if(cfg_str_buf == NULL) 
                  cfg_str_buf =  RPL_DB_NAME;
        config_copy_buf(&cfg_db_name);
      }
    if(db_flag && (strcmp(el,"host") == 0))
      {
            if(cfg_str_buf == NULL) 
                  cfg_str_buf =  RPL_DB_HOST;
        config_copy_buf(&cfg_db_host);
      }
    if(db_flag && (strcmp(el,"port") == 0))
      {
            if(cfg_str_buf == NULL) 
                  cfg_str_buf =  RPL_DB_PORT;
        config_copy_buf(&cfg_db_port);
      }
    if(db_flag && (strcmp(el,"username") == 0))
      {
            if(cfg_str_buf == NULL) 
                  cfg_str_buf =  RPL_DB_USER;
        config_copy_buf(&cfg_db_user);
      }
    if(db_flag && (strcmp(el,"password") == 0))
      {
            if(cfg_str_buf == NULL) 
                  cfg_str_buf =  RPL_DB_PWD;
        config_copy_buf(&cfg_db_pwd);
      }

    /* remove container flag out of scope */
    if(strcmp(el, "logger") == 0)
        log_flag = 0;
    if(strcmp(el, "datastore") == 0)
        ds_flag = 0;
    if(strcmp(el, "tidy") == 0)
        tidy_flag = 0;
    if(strcmp(el, "template") == 0)
        tpl_flag = 0;
      if(strcmp(el, "linkchecker") == 0)
            lc_flag = 0;
    if((strcmp(el, "digest") == 0))
        dg_flag = 0;
    if((strcmp(el, "database") == 0))
        db_flag = 0;
}

/**
   @brief Performs configuration parsing.

   Uses the EXPAT library to parse the XML formatted configuration file.

   @param cfg_filename Configuration file to parse.

   @return -1 if config file cannot be found, -2 if parsing error occurs, otherwise 0.
 */
int
00353 rpl_cfg_parse(rpl_str_t cfg_filename) {
    XML_Parser parser;
    char *xml_buf;
    int flag;
    size_t length;
    FILE *fp;
    rpl_str_t msg;

    if(cfg_filename == NULL)
        cfg_filename = (getenv(RPL_CFG_ENV_VAR) == NULL) ? RPL_CFG_DEFAULT_FILE_NAME :
                       getenv(RPL_CFG_ENV_VAR);
      cfg_conf_filename = strdup(cfg_filename);

    /* open the file (and acquire a descriptor for it) */
    /* binary "b" is req'd for ANSI C portability but has no effect on POSIX platforms */
    errno = 0;
    if((fp=fopen(cfg_filename, "rb")) == NULL) {
        msg = rpl_message_get("RPL_CFG_FILE_NOT_FOUND", RPL_EOM);
        fprintf(stderr, "[FATAL] %s: %s\n", msg, cfg_filename);
        return RPL_CFG_FILE_NOT_FOUND;
    }
    /* log_fatal(get_message("FS_OPEN_FAILED", strerror(errno), EOM)); */

    rpl_list_init (&cfg_dg_dir_names);
    rpl_list_init (&cfg_dg_dir_titles);

    if((parser = XML_ParserCreate(NULL)) == NULL) {
        fprintf(stderr, rpl_message_get("OUT_OF_MEMORY", "config XML parser", RPL_EOM));
        return RPL_CFG_PARSE_ERROR;
    }

    XML_SetElementHandler(parser, config_start, config_end);
    XML_SetCharacterDataHandler(parser, config_characters);

    cfg_str_buf = (rpl_str_t)rpl_me_malloc(RPL_XML_MAX_VALUE_LEN + 1);

    xml_buf = (rpl_str_t)rpl_me_malloc(RPL_XML_BUFFER_BLK + 1);
    do {
        length = fread(xml_buf, 1, RPL_XML_BUFFER_BLK, fp);
        flag = length < strlen(xml_buf);
        if (XML_Parse(parser, xml_buf, length, flag) == XML_STATUS_ERROR) {
            /* XML_WELLFORMEDNESS_ERROR */
            fprintf(stderr,"Error:  configuration file is not well formed!\n");
            fprintf(stderr,"%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)),
                    XML_GetCurrentLineNumber(parser));
            return RPL_CFG_PARSE_ERROR;
        }
    } while(!flag);

    XML_ParserFree(parser);
    fclose (fp);
    rpl_me_free (cfg_str_buf);
    rpl_me_free (xml_buf);

    return 0;
}

/**
  Returns the config filename as determined by CLI -f option,
  the environment or default name (rapple.conf).

  @return config filename 
 */
rpl_str_t
00417 rpl_cfg_get_config_filename()
{
      return rpl_fs_normalize_path(cfg_conf_filename);
}

/**
   Returns the logfile as specified in the XML config file.

   @return logfile as specified in the XML config file.
 */
rpl_str_t
00428 rpl_cfg_get_logfile() {
    return rpl_fs_normalize_path(cfg_log_file);
}

/**
   Returns the log level as specified in the XML config file.

   @return the log level as specified in the XML config file.
 */
int
00438 rpl_cfg_get_loglevel() {
    return atoi(cfg_RPL_LOG_LEVEL);
}

/**
   Returns the base directory of (filesystem) datastore as specified in the XML config file.

   @return the base directory of (filesystem) datastore as specified in the XML config file.
 */
rpl_str_t
00448 rpl_cfg_get_ds_basedir() {
    return rpl_fs_normalize_path(cfg_ds_basedir);
}

/**
   Returns the src directory of (filesystem) datastore as specified in the XML config file.

   @return the src directory of (filesystem) datastore as specified in the XML config file.
 */
rpl_str_t
00458 rpl_cfg_get_srcdir() {
    return rpl_fs_normalize_path(cfg_srcdir);
}

/**
   Returns the web directory of (filesystem) datastore as specified in the XML config file.

   @return the web directory of (filesystem) datastore as specified in the XML config file.
 */
rpl_str_t
00468 rpl_cfg_get_webdir() {
    return rpl_fs_normalize_path(cfg_webdir);
}

/**
   Returns the tidy configuration file.

   @return the tidy configuration file.
 */
rpl_str_t
00478 rpl_cfg_get_trf_tidy_config() {
      return (cfg_tidy_conf != NULL) ? rpl_fs_normalize_path(cfg_tidy_conf) : NULL;
}

/**
   Returns the XML catalog root filename.

   @return the XML catalog root filename.
 */
rpl_str_t
00488 rpl_cfg_get_trf_catalog() {
    return (cfg_trf_catalog != NULL) ? rpl_fs_normalize_path(cfg_trf_catalog) : NULL;
}

/**
   Returns the template host name parameter as specified in the XML config file.

   @return the template host name parameter as specified in the XML config file.
 */
rpl_str_t
00498 rpl_cfg_get_trf_tpl_domain() {
    return cfg_trf_tpl_domain;
}

/**
   Returns the template XSLT as specified in the XML config file.

   @return the template XSLT as specified in the XML config file.
 */
rpl_str_t
00508 rpl_cfg_get_trf_tpl_xslt() {
    return rpl_fs_normalize_path(cfg_trf_tpl_xslt);
}

/**
   Returns the link checker XSLT as specified in the XML config file.

   @return the link checker XSLT as specified in the XML config file.
 */
rpl_str_t
00518 rpl_cfg_get_linkchecker_xslt() {
    return (cfg_linkchecker_xslt != NULL) ? rpl_fs_normalize_path(cfg_linkchecker_xslt) : NULL;
}

/**
   Returns the link checker XML report file location as specified in the XML config file.

   @return the link checker XML report file location as specified in the XML config file.
 */
rpl_str_t
00528 rpl_cfg_get_linkchecker_xml_report() {
      return (cfg_linkchecker_xml_report != NULL) ?  rpl_fs_normalize_path(cfg_linkchecker_xml_report) : NULL;
}

/**
   Returns the link checker HTML report file location as specified in the XML config file.

   @return the link checker HTML report file location as specified in the XML config file.
 */
rpl_str_t
00538 rpl_cfg_get_linkchecker_html_report() {
    return rpl_fs_normalize_path(cfg_linkchecker_html_report);
}

/**
   Returns the (linked) list of directories to be cataloged.

   @return the (linked) list of directories to be cataloged.
 */
rpl_list *
00548 rpl_cfg_get_dg_dir_names() {
    return &cfg_dg_dir_names;
}

/**
   Returns the (linked) list of display titles for directories to be cataloged.

   @return  the (linked) list of display titles for directories to be cataloged.
 */
rpl_list *
00558 rpl_cfg_get_dg_dir_titles() {
    return &cfg_dg_dir_titles;
}

/**
   Returns the database instance name as specified in the XML config file.

   @return the template XSLT as specified in the XML config file.
 */
rpl_str_t
00568 rpl_cfg_get_db_name() {
    return (cfg_db_name == NULL) ? RPL_DB_NAME : cfg_db_name;
}

/**
   Returns the database host as specified in the XML config file.

   @return the template XSLT as specified in the XML config file.
 */
rpl_str_t
00578 rpl_cfg_get_db_host() {
    return (cfg_db_host == NULL) ? RPL_DB_HOST : cfg_db_host;
}

/**
   Returns the database port as specified in the XML config file.

   @return the template XSLT as specified in the XML config file.
 */
int
00588 rpl_cfg_get_db_port() {
    return (cfg_db_port == NULL) ? atoi(RPL_DB_PORT) : atoi(cfg_db_port);
}

/**
   Returns the database port as specified in the XML config file.

   @return the template XSLT as specified in the XML config file.
 */
rpl_str_t
00598 rpl_cfg_get_db_user() {
    return (cfg_db_user == NULL) ? RPL_DB_USER : cfg_db_user;
}

/**
   Returns the database port as specified in the XML config file.

   @return the template XSLT as specified in the XML config file.
 */
rpl_str_t
00608 rpl_cfg_get_db_pwd() {
    return (cfg_db_pwd == NULL) ? RPL_DB_PWD : cfg_db_pwd;
}

/**
   Cleans up resources used by the configuration module.
*/
00615 void rpl_cfg_cleanup()
{
    rpl_me_free (cfg_log_file);
    rpl_me_free (cfg_RPL_LOG_LEVEL);
    rpl_me_free (cfg_ds_basedir);
      /* do not need to release cfg_trf_tpl_domain as mod_xslt indirectly does this */
    rpl_me_free (cfg_trf_tpl_xslt);
    rpl_me_free (cfg_trf_catalog);
    rpl_str_list_destroy (&cfg_dg_dir_names);
    rpl_str_list_destroy (&cfg_dg_dir_titles);
}

Generated by  Doxygen 1.6.0   Back to index