renamed .h and libs clicon->clixon

This commit is contained in:
Olof Hagsand 2016-02-28 15:27:36 +01:00
parent baa5611616
commit 79b77943f9
132 changed files with 1240 additions and 1268 deletions

663
lib/src/clixon_options.c Normal file
View file

@ -0,0 +1,663 @@
/*
*
Copyright (C) 2009-2016 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
CLIXON 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 3 of the License, or
(at your option) any later version.
CLIXON 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 CLIXON; see the file LICENSE. If not, see
<http://www.gnu.org/licenses/>.
*
* CLICON options
* See clicon_tutorial appendix and clicon.conf.cpp.cpp on documentation of
* options
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/socket.h>
/* cligen */
#include <cligen/cligen.h>
/* clicon */
#include "clixon_err.h"
#include "clixon_queue.h"
#include "clixon_hash.h"
#include "clixon_handle.h"
#include "clixon_chunk.h"
#include "clixon_log.h"
#include "clixon_yang.h"
#include "clixon_options.h"
/*
* clicon_option_dump
* Print registry on file. For debugging.
*/
void
clicon_option_dump(clicon_handle h, int dbglevel)
{
clicon_hash_t *hash = clicon_options(h);
int i;
char **keys;
void *val;
size_t klen;
size_t vlen;
if (hash == NULL)
return;
keys = hash_keys(hash, &klen);
if (keys == NULL)
return;
for(i = 0; i < klen; i++) {
val = hash_value(hash, keys[i], &vlen);
if (vlen){
if (((char*)val)[vlen-1]=='\0') /* assume string */
clicon_debug(dbglevel, "%s =\t \"%s\"", keys[i], (char*)val);
else
clicon_debug(dbglevel, "%s =\t 0x%p , length %zu", keys[i], val, vlen);
}
else
clicon_debug(dbglevel, "%s = NULL", keys[i]);
}
free(keys);
}
/*! Read filename and set values to global options registry
*/
static int
clicon_option_readfile(clicon_hash_t *copt, const char *filename)
{
struct stat st;
char opt[1024], val[1024];
char line[1024], *cp;
FILE *f;
int retval = -1;
if (filename == NULL || !strlen(filename)){
clicon_err(OE_UNIX, 0, "Not specified");
return -1;
}
if (stat(filename, &st) < 0){
clicon_err(OE_UNIX, errno, "%s", filename);
return -1;
}
if (!S_ISREG(st.st_mode)){
clicon_err(OE_UNIX, 0, "%s is not a regular file", filename);
return -1;
}
if ((f = fopen(filename, "r")) == NULL) {
clicon_err(OE_UNIX, errno, "configure file: %s", filename);
return -1;
}
clicon_debug(2, "Reading config file %s", __FUNCTION__, filename);
while (fgets(line, sizeof(line), f)) {
if ((cp = strchr(line, '\n')) != NULL) /* strip last \n */
*cp = '\0';
/* Trim out comments, strip whitespace, and remove CR */
if ((cp = strchr(line, '#')) != NULL)
memcpy(cp, "\n", 2);
if (sscanf(line, "%s %s", opt, val) < 2)
continue;
if ((hash_add(copt,
opt,
val,
strlen(val)+1)) == NULL)
goto catch;
}
retval = 0;
catch:
fclose(f);
return retval;
}
/*! Set default values of some options that may not appear in config-file
*/
static int
clicon_option_default(clicon_hash_t *copt)
{
char *val;
int retval = 0;
if (!hash_lookup(copt, "CLICON_YANG_MODULE_MAIN")){
if (hash_add(copt, "CLICON_YANG_MODULE_MAIN", "clicon", strlen("clicon")+1) < 0)
goto catch;
}
if (!hash_lookup(copt, "CLICON_SOCK_GROUP")){
val = CLICON_SOCK_GROUP;
if (hash_add(copt, "CLICON_SOCK_GROUP", val, strlen(val)+1) < 0)
goto catch;
}
if (!hash_lookup(copt, "CLICON_CLI_MODE")){
if (hash_add(copt, "CLICON_CLI_MODE", "base", strlen("base")+1) < 0)
goto catch;
}
if (!hash_lookup(copt, "CLICON_MASTER_PLUGIN")){
val = CLICON_MASTER_PLUGIN;
if (hash_add(copt, "CLICON_MASTER_PLUGIN", val, strlen(val)+1) < 0)
goto catch;
}
if (!hash_lookup(copt, "CLICON_CLI_GENMODEL")){
if (hash_add(copt, "CLICON_CLI_GENMODEL", "1", strlen("1")+1) < 0)
goto catch;
}
if (!hash_lookup(copt, "CLICON_CLI_GENMODEL_TYPE")){
if (hash_add(copt, "CLICON_CLI_GENMODEL_TYPE", "VARS", strlen("VARS")+1) < 0)
goto catch;
}
if (!hash_lookup(copt, "CLICON_AUTOCOMMIT")){
if (hash_add(copt, "CLICON_AUTOCOMMIT", "0", strlen("0")+1) < 0)
goto catch;
}
/* Legacy is 1 but default should really be 0. New apps should use 0 */
if (!hash_lookup(copt, "CLICON_CLI_VARONLY")){
if (hash_add(copt, "CLICON_CLI_VARONLY", "1", strlen("1")+1) < 0)
goto catch;
}
if (!hash_lookup(copt, "CLICON_CLI_GENMODEL_COMPLETION")){
if (hash_add(copt, "CLICON_CLI_GENMODEL_COMPLETION", "0", strlen("0")+1) < 0)
goto catch;
}
retval = 0;
catch:
unchunk_group(__FUNCTION__);
return retval;
}
/*! Check that options are set
*/
static int
clicon_option_sanity(clicon_hash_t *copt)
{
int retval = -1;
if (!hash_lookup(copt, "CLICON_CLI_DIR")){
clicon_err(OE_UNIX, 0, "CLICON_CLI_DIR not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_CLISPEC_DIR")){
clicon_err(OE_UNIX, 0, "CLICON_CLISPEC_DIR not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_BACKEND_DIR")){
clicon_err(OE_UNIX, 0, "CLICON_BACKEND_PIDFILE not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_NETCONF_DIR")){
clicon_err(OE_UNIX, 0, "CLICON_NETCONF_DIR not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_RUNNING_DB")){
clicon_err(OE_UNIX, 0, "CLICON_RUNNING_DB not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_CANDIDATE_DB")){
clicon_err(OE_UNIX, 0, "CLICON_CANDIDATE_DB not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_YANG_DIR")){
clicon_err(OE_UNIX, 0, "CLICON_YANG_DIR not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_ARCHIVE_DIR")){
clicon_err(OE_UNIX, 0, "CLICON_ARCHIVE_DIR not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_STARTUP_CONFIG")){
clicon_err(OE_UNIX, 0, "CLICON_STARTUP_CONFIG not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_SOCK")){
clicon_err(OE_UNIX, 0, "CLICON_SOCK not defined in config file");
goto done;
}
if (!hash_lookup(copt, "CLICON_BACKEND_PIDFILE")){
clicon_err(OE_UNIX, 0, "CLICON_BACKEND_PIDFILE not defined in config file");
goto done;
}
retval = 0;
done:
return retval;
}
/*! Initialize option values
*
* Set default options, Read config-file, Check that all values are set.
* @param[in] h clicon handle
*/
int
clicon_options_main(clicon_handle h)
{
int retval = -1;
char *configfile;
clicon_hash_t *copt = clicon_options(h);
/*
* Set configure file if not set by command-line above
*/
if (!hash_lookup(copt, "CLICON_CONFIGFILE")){
clicon_err(OE_CFG, 0, "CLICON_CONFIGFILE (-f) not set");
goto done;
}
configfile = hash_value(copt, "CLICON_CONFIGFILE", NULL);
clicon_debug(1, "CLICON_CONFIGFILE=%s", configfile);
/* Set default options */
if (clicon_option_default(copt) < 0) /* init registry from file */
goto done;
/* Read configfile */
if (clicon_option_readfile(copt, configfile) < 0)
goto done;
if (clicon_option_sanity(copt) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Check if a clicon option has a value
*/
int
clicon_option_exists(clicon_handle h, const char *name)
{
clicon_hash_t *copt = clicon_options(h);
return (hash_lookup(copt, (char*)name) != NULL);
}
/*! Get a single string option string via handle
*
* @param[in] h clicon_handle
* @param[in] name option name
* @retval NULL If option not found, or value of option is NULL
* @retval string value of option if found
* clicon options should be strings.
* To differentiate the two reasons why NULL may be returned, use function
* clicon_option_exists() before the call
*/
char *
clicon_option_str(clicon_handle h, const char *name)
{
clicon_hash_t *copt = clicon_options(h);
if (hash_lookup(copt, (char*)name) == NULL)
return NULL;
return hash_value(copt, (char*)name, NULL);
}
/*! Set a single string option via handle
*/
int
clicon_option_str_set(clicon_handle h, const char *name, char *val)
{
clicon_hash_t *copt = clicon_options(h);
return hash_add(copt, (char*)name, val, strlen(val)+1)==NULL?-1:0;
}
/*! Get options as integer but stored as string
* @param h clicon handle
* @param name name of option
* @retval int An integer as aresult of atoi
* @retval -1 If option does not exist
* @code
* if (clicon_option_exists(h, "X")
* return clicon_option_int(h, "X");
* else
* return 0;
* @endcode
* Note that -1 can be both error and value.
* This means that it should be used together with clicon_option_exists() and
* supply a defualt value as shown in the example.
*/
int
clicon_option_int(clicon_handle h, const char *name)
{
char *s;
if ((s = clicon_option_str(h, name)) == NULL)
return -1;
return atoi(s);
}
/*! set option given as int.
*/
int
clicon_option_int_set(clicon_handle h, const char *name, int val)
{
char s[64];
if (snprintf(s, sizeof(s)-1, "%u", val) < 0)
return -1;
return clicon_option_str_set(h, name, s);
}
/*! delete option
*/
int
clicon_option_del(clicon_handle h, const char *name)
{
clicon_hash_t *copt = clicon_options(h);
return hash_del(copt, (char*)name);
}
/*-----------------------------------------------------------------
* Specific option access functions.
* These should be commonly accessible for all users of clicon lib
*-----------------------------------------------------------------*/
char *
clicon_configfile(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CONFIGFILE");
}
/*! YANG database specification directory */
char *
clicon_yang_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_YANG_DIR");
}
/*! YANG main module */
char *
clicon_yang_module_main(clicon_handle h)
{
return clicon_option_str(h, "CLICON_YANG_MODULE_MAIN");
}
/*! YANG revision */
char *
clicon_yang_module_revision(clicon_handle h)
{
return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION");
}
/* candidate database: get name */
char *
clicon_candidate_db(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CANDIDATE_DB");
}
/* running database: get name */
char *
clicon_running_db(clicon_handle h)
{
return clicon_option_str(h, "CLICON_RUNNING_DB");
}
char *
clicon_backend_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_BACKEND_DIR");
}
/* contains .so files CLICON_CLI_DIR */
char *
clicon_cli_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CLI_DIR");
}
/* contains .cli files - CLICON_CLISPEC_DIR */
char *
clicon_clispec_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CLISPEC_DIR");
}
char *
clicon_netconf_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_NETCONF_DIR");
}
char *
clicon_archive_dir(clicon_handle h)
{
return clicon_option_str(h, "CLICON_ARCHIVE_DIR");
}
char *
clicon_startup_config(clicon_handle h)
{
return clicon_option_str(h, "CLICON_STARTUP_CONFIG");
}
/* get family of backend socket: AF_UNIX, AF_INET or AF_INET6 */
int
clicon_sock_family(clicon_handle h)
{
char *s;
if ((s = clicon_option_str(h, "CLICON_SOCK_FAMILY")) == NULL)
return AF_UNIX;
else if (strcmp(s, "IPv4")==0)
return AF_INET;
else if (strcmp(s, "IPv6")==0)
return AF_INET6;
else
return AF_UNIX; /* default */
}
/* get information about socket: unix domain filepath, or addr:path */
char *
clicon_sock(clicon_handle h)
{
return clicon_option_str(h, "CLICON_SOCK");
}
/* get port for backend socket in case of AF_INET or AF_INET6 */
int
clicon_sock_port(clicon_handle h)
{
char *s;
if ((s = clicon_option_str(h, "CLICON_SOCK_PORT")) == NULL)
return -1;
return atoi(s);
}
char *
clicon_backend_pidfile(clicon_handle h)
{
return clicon_option_str(h, "CLICON_BACKEND_PIDFILE");
}
char *
clicon_sock_group(clicon_handle h)
{
return clicon_option_str(h, "CLICON_SOCK_GROUP");
}
char *
clicon_master_plugin(clicon_handle h)
{
return clicon_option_str(h, "CLICON_MASTER_PLUGIN");
}
/* return initial clicon cli mode */
char *
clicon_cli_mode(clicon_handle h)
{
return clicon_option_str(h, "CLICON_CLI_MODE");
}
/*! Whether to generate CLIgen syntax from datamodel or not (0 or 1)
* Must be used with a previous clicon_option_exists().
*/
int
clicon_cli_genmodel(clicon_handle h)
{
char const *opt = "CLICON_CLI_GENMODEL";
if (clicon_option_exists(h, opt))
return clicon_option_int(h, opt);
else
return 0;
}
/* How to generate and show CLI syntax: VARS|ALL */
enum genmodel_type
clicon_cli_genmodel_type(clicon_handle h)
{
char *s;
enum genmodel_type gt = GT_ERR;
if (!clicon_option_exists(h, "CLICON_CLI_GENMODEL_TYPE")){
gt = GT_VARS;
goto done;
}
s = clicon_option_str(h, "CLICON_CLI_GENMODEL_TYPE");
if (strcmp(s, "NONE")==0)
gt = GT_NONE;
else
if (strcmp(s, "VARS")==0)
gt = GT_VARS;
else
if (strcmp(s, "ALL")==0)
gt = GT_ALL;
done:
return gt;
}
/* eg -q option, dont print notifications on stdout */
char *
clicon_quiet_mode(clicon_handle h)
{
return clicon_option_str(h, "CLICON_QUIET");
}
int
clicon_autocommit(clicon_handle h)
{
char const *opt = "CLICON_AUTOCOMMIT";
if (clicon_option_exists(h, opt))
return clicon_option_int(h, opt);
else
return 0;
}
int
clicon_autocommit_set(clicon_handle h, int val)
{
return clicon_option_int_set(h, "CLICON_AUTOCOMMIT", val);
}
/*! Dont include keys in cvec in cli vars callbacks
*/
int
clicon_cli_varonly(clicon_handle h)
{
char const *opt = "CLICON_CLI_VARONLY";
if (clicon_option_exists(h, opt))
return clicon_option_int(h, opt);
else
return 0;
}
int
clicon_cli_varonly_set(clicon_handle h, int val)
{
return clicon_option_int_set(h, "CLICON_CLI_VARONLY", val);
}
int
clicon_cli_genmodel_completion(clicon_handle h)
{
char const *opt = "CLICON_CLI_GENMODEL_COMPLETION";
if (clicon_option_exists(h, opt))
return clicon_option_int(h, opt);
else
return 0;
}
/*
* Get dbspec (YANG variant)
* Must use hash functions directly since they are not strings.
*/
yang_spec *
clicon_dbspec_yang(clicon_handle h)
{
clicon_hash_t *cdat = clicon_data(h);
size_t len;
void *p;
if ((p = hash_value(cdat, "dbspec_yang", &len)) != NULL)
return *(yang_spec **)p;
return NULL;
}
/*
* Set dbspec (YANG variant)
* ys must be a malloced pointer
*/
int
clicon_dbspec_yang_set(clicon_handle h, struct yang_spec *ys)
{
clicon_hash_t *cdat = clicon_data(h);
/* It is the pointer to ys that should be copied by hash,
so we send a ptr to the ptr to indicate what to copy.
*/
if (hash_add(cdat, "dbspec_yang", &ys, sizeof(ys)) == NULL)
return -1;
return 0;
}
/*
* Get dbspec name as read from spec. Can be used in CLI '@' syntax.
* XXX: this we muśt change,...
*/
char *
clicon_dbspec_name(clicon_handle h)
{
if (!clicon_option_exists(h, "dbspec_name"))
return NULL;
return clicon_option_str(h, "dbspec_name");
}
/*
* Set dbspec name as read from spec. Can be used in CLI '@' syntax.
*/
int
clicon_dbspec_name_set(clicon_handle h, char *name)
{
return clicon_option_str_set(h, "dbspec_name", name);
}