summaryrefslogtreecommitdiff
path: root/src/cli_new.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli_new.c')
-rw-r--r--src/cli_new.c1938
1 files changed, 1938 insertions, 0 deletions
diff --git a/src/cli_new.c b/src/cli_new.c
new file mode 100644
index 0000000..2f2801d
--- /dev/null
+++ b/src/cli_new.c
@@ -0,0 +1,1938 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <limits.h>
+#include <stdarg.h>
+#include "cli_val.h"
+#include "cli_parse.h"
+#include <regex.h>
+
+#include "cli_objects.h"
+#include "cli_val_engine.h"
+
+/* Defines: */
+
+#define EXE_STRING_DELTA 512
+#define PATH_DELTA 1000
+#define ENDS_ALLOC 20
+#define PATH_CM_LOCATION 25 /* mcd vs. ccd location
+ change when m_root changed */
+
+/* Global vars: */
+vtw_path m_path, t_path;
+
+/* Loval vars: */
+static vtw_node *vtw_free_nodes; /* linked via left */
+static char val_name[] = VAL_NAME;
+static int cond1[TOP_COND] ={5, 0,-1,-1, 0, 1, 0, 0};
+static int cond2[TOP_COND] ={5, 0, 1,-1,-1, 1, 1, 0};
+static char const *cond_formats[DOMAIN_TYPE] =
+ {
+ 0,
+ "%u", /* INT_TYPE */
+ "%u.%u.%u.%u", /*IPV4_TYPE*/
+ "%u.%u.%u.%u/%u", /*IPV4NET_TYPE*/
+ 0,
+ 0,
+ "%x:%x:%x:%x:%x:%x" /* MACADDR_TYPE */
+ };
+
+static int cond_format_lens[DOMAIN_TYPE] =
+ {
+ 0,
+ 1, /* INT_TYPE */
+ 4, /*IPV4_TYPE*/
+ 5, /*IPV4NET_TYPE*/
+ 0,
+ 0,
+ 6 /* MACADDR_TYPE */
+ };
+
+static int cli_val_len;
+static char *cli_val_alloc;
+static char *cli_val_ptr;
+
+static char *exe_string;
+static int exe_string_len;
+static int node_cnt;
+static int free_node_cnt;
+static boolean in_validate_val;
+static valstruct validate_value_val; /* value being validated
+ to be used as $(@) */
+
+/* Local function declarations: */
+
+static int check_comp(vtw_node *cur);
+static boolean check_syn_func(vtw_node *cur,const char* func,int line);
+#define check_syn(cur) check_syn_func((cur),__FUNCTION__,__LINE__)
+static void copy_path(vtw_path *to, vtw_path *from);
+static int eval_va(valstruct *res, vtw_node *node);
+static int expand_string(char *p);
+static void free_node(vtw_node *node);
+static void free_node_tree(vtw_node *node);
+static void free_reuse_list(void);
+static void free_path(vtw_path *path);
+static void free_string(char *str);
+static vtw_node * get_node(void);
+
+static void scan_ipv6(char *val, unsigned int *parts);
+
+static int set_reference_environment(const char* var_reference,
+ clind_path_ref *n_cfg_path,
+ clind_path_ref *n_tmpl_path,
+ clind_path_ref *n_cmd_path,
+ int active);
+
+/*************************************************
+ GLOBAL FUNCTIONS
+***************************************************/
+/* it is executed as "eval `my_set` in order to be able to
+ modify BASH env
+ therefore, all error will be reported as
+ printf("echo \"bla-bla-bla%s\";", sptr)
+ note very important ';' as the end of the format
+*/
+void bye(char *msg, ...)
+{
+ va_list ap;
+
+ if (is_silent_msg())
+ exit(0);
+ va_start(ap, msg);
+ if (is_echo())
+ printf("echo \"");
+ vprintf(msg, ap);
+ printf(is_echo()? "\";":"\n");
+ va_end(ap);
+
+ exit(0);
+}
+
+/* msg:
+ print message, preceeded by "echo " if global
+ flag echo set. This flag is used by program
+ which are executed as eval `command` in order to
+ modify BASH env
+*/
+void print_msg(char *msg, ...)
+{
+ va_list ap;
+
+ if (is_silent_msg())
+ return;
+ va_start(ap, msg);
+ if (is_echo())
+ printf("echo \"");
+ vprintf(msg, ap);
+ printf(is_echo()? "\";":"\n");
+ va_end(ap);
+}
+
+void touch_dir(const char *dp)
+{
+ struct stat statbuf;
+ if (lstat(dp, &statbuf) < 0) {
+ char *command;
+ command = my_malloc(strlen(dp) + 10, "set");
+ sprintf(command, "mkdir -p %s", dp);
+ system(command);
+ free(command);
+ return;
+ }
+ if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
+ bye("directory %s expected, found regular file", dp);
+ }
+ return;
+}
+
+/*****************************************************
+ add_val:
+ verify that the types are the same;
+ if first valstruct is single value, convert it
+ into multivalue;
+ add the value of second to the list of first;
+*****************************************************/
+void add_val(valstruct *first, valstruct *second)
+{
+ assert (first->free_me && second->free_me);
+ assert(second->cnt == 0);
+ if (first->val_type != second->val_type) {
+ printf("Different types\n\n");
+ } else {
+ if (first->cnt%MULTI_ALLOC == 0) {
+ /* convert into multivalue */
+ first->vals = my_realloc(first->vals, (first->cnt + MULTI_ALLOC) *
+ sizeof(char *), "add_value");
+ if (first->cnt == 0) { /* single value - convert */
+ first->vals[0] = first->val;
+ first->cnt = 1;
+ first->val = NULL;
+ }
+ }
+ second->free_me = FALSE; /* we took its string */
+ first->vals[first->cnt] = second->val;
+ ++first->cnt;
+ }
+}
+/*****************************************************
+ append - append node to the tail of list
+*****************************************************/
+void append(vtw_list *l, vtw_node *n, int aux)
+{
+ vtw_node *lnode;
+ lnode = make_node(LIST_OP, n, NULL);
+ lnode->vtw_node_aux = aux;
+ if(l->vtw_list_tail) {
+ assert(l->vtw_list_tail->vtw_node_right == NULL);
+ l->vtw_list_tail->vtw_node_right = lnode;
+ } else {
+ assert(l->vtw_list_head == NULL);
+ l->vtw_list_head = lnode;
+ }
+ l->vtw_list_tail = lnode;
+}
+
+void dt(vtw_sorted *srtp)
+{
+ int i;
+ for (i=0; i<srtp->num; ++i)
+ printf("%d %s\n", i, (char *)(srtp->ptrs[i]));
+}
+
+
+void di(vtw_sorted *srtp)
+{
+ int i;
+ for (i=0; i<srtp->num; ++i)
+ printf("%u %u\n", i, *(unsigned int *)(srtp->ptrs[i]));
+}
+
+static char _lock_file_[1025] = {0};
+static int _lock_fd_=-1;
+
+static void clean_lock_file(void) {
+ if(_lock_file_[0]) {
+ unlink(_lock_file_);
+ _lock_file_[0]=0;
+ }
+ if(_lock_fd_!=-1) {
+ close(_lock_fd_);
+ _lock_fd_=-1;
+ }
+}
+
+boolean get_config_lock(const char* adirp, const char* lock_name) {
+
+ boolean ret = TRUE;
+
+ sprintf(_lock_file_, "%s/%s", adirp, lock_name);
+
+ _lock_fd_ = open(_lock_file_, O_WRONLY | O_CREAT | O_EXCL, 0644);
+
+ ret = (_lock_fd_!=-1);
+
+ if(ret) {
+ atexit(clean_lock_file);
+ }
+
+ return ret;
+}
+
+void internal_error(int line, char *file)
+{
+ printf("\n\nInternal Error at line %d in %s\n", line, file);
+ exit (-1);
+}
+
+/*************************************************
+ vtw_sort:
+ create sorted structure for the value,
+ allocates ptrs and parts in this structure
+*/
+void vtw_sort(valstruct *valp, vtw_sorted *sortp)
+{
+ int i, unsorted, left, child, right;
+ void *leftp, *rightp, *childp;
+ const char * format;
+ unsigned int *parts;
+ vtw_type_e type = valp->val_type;
+ char *cp;
+ int cur=0, par=0, partnum=0, res=0;
+ void *curp, *parp;
+
+ sortp->num = valp->cnt?valp->cnt : 1;
+ sortp->ptrs = my_malloc(sortp->num * sizeof(void *), "sort_ptrs");
+ sortp->partnum = cond_format_lens[type];
+ if (sortp->partnum) {
+ sortp->parts = my_malloc(sortp->partnum * sortp->num * sizeof(void *),
+ "sort_parts");
+ }else{
+ sortp->parts = NULL;
+ }
+ switch (type){
+ case IPV6_TYPE:
+ case IPV6NET_TYPE:
+ for (i = 0; i < sortp->num; ++i) {
+ parts = sortp->parts + i * sortp->partnum;
+ scan_ipv6(valp->cnt?valp->vals[i]:valp->val, parts);
+ sortp->ptrs[i] = parts;
+ }
+ break;
+ case IPV4_TYPE:
+ case IPV4NET_TYPE:
+ case MACADDR_TYPE:
+ case INT_TYPE:
+ format = cond_formats[valp->val_type];
+ for (i = 0; i < sortp->num; ++i) {
+ cp = valp->cnt?valp->vals[i]:valp->val;
+ parts = sortp->parts + i * sortp->partnum;
+ switch (sortp->partnum) {
+ case 1:
+ (void) sscanf(cp, format, parts);
+ break;
+ case 2:
+ (void) sscanf(cp, format, parts, parts+1);
+ break;
+ case 3:
+ (void) sscanf(cp, format, parts, parts+1, parts+2);
+ break;
+ case 4:
+ (void) sscanf(cp, format, parts, parts+1, parts+2,
+ parts+3);
+ break;
+ case 5:
+ (void) sscanf(cp, format, parts, parts+1, parts+2,
+ parts+3, parts+4);
+ break;
+ case 6:
+ (void) sscanf(cp, format, parts, parts+1, parts+2,
+ parts+3, parts+4, parts+5);
+ break;
+ }
+ sortp->ptrs[i] = parts;
+ }
+ break;
+ case TEXT_TYPE:
+ case BOOL_TYPE:
+ for (i = 0; i < sortp->num; ++i) {
+ sortp->ptrs[i] = valp->cnt?valp->vals[i]:valp->val;
+ }
+ break;
+ default:
+ printf("Unknown value in switch on line %d\n", __LINE__);
+ exit(-5);
+ }
+ if (sortp->num < 2)
+ return;
+ /* now do a heap sort */
+ /* build heap */
+ /* from left to right, we start with the heap of only one (first) element*/
+ for (i = 2; i <= sortp->num; ++i)
+ {
+ cur = i;
+ do {
+ curp = sortp->ptrs[cur - 1];
+ par = cur >> 1;
+ parp = sortp->ptrs[par - 1];
+ if (sortp->partnum){
+ for(partnum = 0; partnum < sortp->partnum; ++partnum) {
+ if (*((unsigned int *)curp + partnum)>
+ *((unsigned int *)parp + partnum)){
+ res = 1;
+ break;
+ }
+ if (*((unsigned int *)curp + partnum)<
+ *((unsigned int *)parp + partnum)){
+ res = -1;
+ break;
+ }
+ res = 0;
+ }
+ }else{
+ res = strcmp((char *)curp, (char *) parp);
+ }
+ if (res <= 0)
+ break;
+ /* swap them */
+ sortp->ptrs[cur - 1] = parp;
+ sortp->ptrs[par - 1] = curp;
+
+ } while ((cur = par) != 1);
+ }
+ /* convert heap into sorted array */
+ unsorted = sortp->num; /* sortp->num must be >= 2 */
+ while (TRUE) {
+ void *tp;
+ /* root to the sorted part */
+ tp = sortp->ptrs[0];
+ sortp->ptrs[0] = sortp->ptrs[--unsorted];
+ sortp->ptrs[unsorted] = tp;
+ if (unsorted == 1)
+ break;
+ /* push down the new root */
+ par = 1;
+ while(TRUE) {
+ left = par << 1; /* left child */
+ if (left > unsorted)
+ break; /* no children */
+ else {
+ if (left == unsorted) {
+ /* only left child */
+ child = left;
+ } else {
+ /* both children */
+ right = left+1;
+ leftp = sortp->ptrs[left - 1];
+ rightp = sortp->ptrs[right - 1];
+ /* find larger child */
+ if (sortp->partnum){
+ for(partnum = 0; partnum < sortp->partnum; ++partnum) {
+ if (*((unsigned int *)leftp + partnum) >
+ *((unsigned int *)rightp + partnum)) {
+ res = 1;
+ break;
+ }
+ if (*((unsigned int *)leftp + partnum) <
+ *((unsigned int *)rightp + partnum)) {
+ res = -1;
+ break;
+ }
+ res = 0;
+ }
+ }else{
+ res = strcmp((char *)leftp, (char *) rightp);
+ }
+ if (res >= 0) {
+ child = left; /* left is larger or same*/
+ } else {
+ child = right;
+ }
+ }
+ /* compare parent and larger child */
+ parp = sortp->ptrs[par - 1];
+ childp = sortp->ptrs[child - 1];
+ if (sortp->partnum){
+ for(partnum = 0; partnum < sortp->partnum; ++partnum) {
+ if (*((unsigned int *)parp + partnum) >
+ *((unsigned int *)childp + partnum)){
+ res = 1;
+ break;
+ }
+ if (*((unsigned int *)parp + partnum) <
+ *((unsigned int *)childp + partnum)){
+ res = -1;
+ break;
+ }
+ res = 0;
+ }
+ }else{
+ res = strcmp((char *)parp, (char *) childp);
+ }
+ if (res >= 0) {
+ /* done with percolating down, parent larger than child */
+ break;
+ }
+ /* child greater, exchage and continue */
+ sortp->ptrs[par - 1] = childp;
+ sortp->ptrs[child - 1] = parp;
+ par = child;
+ }
+ }
+ }
+}
+
+/* returns FALSE if execution returns non-null,
+ returns TRUE if every excution returns NULL
+*/
+boolean execute_list(vtw_node *cur, vtw_def *def)
+{
+ boolean ret;
+ int status;
+ set_in_exec(TRUE);
+ status = char2val(def, get_at_string(), &validate_value_val);
+ if (status) return FALSE;
+ ret = check_syn(cur);
+ free_val(&validate_value_val);
+ set_in_exec(FALSE);
+ return ret;
+}
+
+
+/*****************************************************
+ make_node - create a node with oper, left, and right
+*****************************************************/
+vtw_node * make_node(vtw_oper_e oper, vtw_node *left,
+ vtw_node *right)
+{
+ vtw_node *ret ;
+ ret = get_node();
+ ret->vtw_node_oper = oper;
+ ret->vtw_node_left = left;
+ ret->vtw_node_right = right;
+ ret->vtw_node_string = NULL;
+ ret->vtw_node_aux = 0;
+ return ret;
+}
+vtw_node *make_str_node0(char *str, vtw_oper_e op)
+{
+ vtw_node *ret;
+ ret = make_node(op, NULL, NULL);
+ ret->vtw_node_string = str;
+ ret->vtw_node_type = TEXT_TYPE;
+ return ret;
+}
+/*****************************************************
+ make_str_node - create a VAL_OP node with str
+*****************************************************/
+vtw_node *make_str_node(char *str)
+{
+ return make_str_node0(str, VAL_OP);
+}
+/*****************************************************
+ make_var_node - create a VAR_OP node with str
+*****************************************************/
+vtw_node *make_var_node(char *str)
+{
+ return make_str_node0(str, VAR_OP);
+}
+/*****************************************************
+ make_val_node - create a VAl_OP node with str
+*****************************************************/
+vtw_node *make_val_node(valstruct *val)
+{
+ vtw_node *ret;
+ assert(val->free_me);
+ ret = make_node(VAL_OP, NULL, NULL);
+ ret->vtw_node_val = *val;
+ val->free_me = FALSE;
+ return ret;
+}
+valstruct str2val(char *cp)
+{
+ valstruct ret;
+ memset(&ret, 0, sizeof(ret));
+ ret.val_type = TEXT_TYPE;
+ ret.val = cp;
+ ret.free_me = TRUE;
+ return ret;
+}
+/****************************************************
+ STATIC FUNCTIONS
+****************************************************/
+
+/**************************************************
+ char2val:
+ convert string into valstruct verifying the type
+ according to def
+****************************************************/
+int char2val(vtw_def *def, char *value, valstruct *valp)
+{
+ int token;
+ char *endp, *cp;
+ int linecnt, cnt;
+ int my_type = def->def_type;
+ boolean first = TRUE;
+
+ memset(valp, 0, sizeof (*valp));
+
+ if (my_type == ERROR_TYPE) {
+ my_type = TEXT_TYPE;
+ }
+
+ if (my_type != TEXT_TYPE && my_type != ERROR_TYPE) {
+ cli_val_len = strlen(value);
+ cli_val_ptr = value;
+ while(1) {
+ token = yy_cli_val_lex();
+ if (token != VALUE) {
+ if (first || token){
+ if (def->def_type_help){
+ set_at_string(value);
+ (void)expand_string(def->def_type_help);
+ printf("%s\n", exe_string);
+ fprintf(stderr, "%s\n", exe_string);
+ } else {
+ print_msg("Wrong type of value in %s, "
+ "need %s\n",
+ m_path.path_buf + m_path.print_offset,
+ type_to_name(my_type));
+ }
+ return -1;
+ }
+ return 0;
+ }
+ if (my_type != get_cli_value_ptr()->val_type) {
+ if (def->def_type_help){
+ set_at_string(value);
+ (void)expand_string(def->def_type_help);
+ printf("%s\n", exe_string);
+ fprintf(stderr, "%s\n", exe_string);
+ } else {
+ print_msg("Wrong type of value in %s, "
+ "need %s\n",
+ m_path.path_buf + m_path.print_offset,
+ type_to_name(my_type));
+ }
+ my_free(get_cli_value_ptr()->val);
+ if (first)
+ return -1;
+ return 0;
+ }
+ if (first) {
+ *valp = *get_cli_value_ptr();
+ get_cli_value_ptr()->free_me = FALSE;
+ first = FALSE;
+ } else {
+ if (def->multi)
+ add_val(valp, get_cli_value_ptr());
+ else {
+ print_msg("Unexpected multivalue in %s\n", m_path.path);
+ free_val(get_cli_value_ptr());
+ }
+ }
+ token = yy_cli_val_lex();
+ if (!token)
+ return 0;
+ if (token != EOL) {
+ print_msg("Badly formed value in %s\n",
+ m_path.path + m_path.print_offset);
+ if (token == VALUE)
+ my_free(get_cli_value_ptr()->val);
+ return 0;
+ }
+ }
+ return 0;
+ }
+ valp->val_type = TEXT_TYPE;
+ valp->free_me = TRUE;
+ /* count lines */
+ linecnt = 0;
+ for (cp = value; *cp; ++cp)
+ if (*cp == '\n')
+ ++linecnt;
+ if (cp != value && cp[-1] != '\n')
+ ++linecnt; /* last non empty non \n terminated string */
+ if (linecnt == 0) /* one empty non terminated string */
+ linecnt = 1;
+ if (linecnt == 1) {
+ valp->val=my_strdup(value, "char2val 1");
+ /*truncate '\n' etc */
+ endp = strchr(valp->val, '\n');
+ if (endp)
+ *endp = 0;
+ } else {
+ valp->cnt = linecnt;
+ cnt = (linecnt + MULTI_ALLOC - 1) / MULTI_ALLOC;
+ cnt *= MULTI_ALLOC;
+ valp->vals = my_malloc(cnt * sizeof(char *), "char2val 2");
+ for(cp = value, cnt = 0; cnt < linecnt; ++cnt) {
+ endp = strchr(cp, '\n');
+ if (endp)
+ *endp = 0;
+ valp->vals[cnt]=my_strdup(cp, "char2val 3");
+ if (endp) {
+ *endp = '\n';
+ cp = endp + 1;
+ } else {
+ /* non '\n' terinated string, must be last line, we are done */
+ ++cnt;
+ assert(cnt == linecnt);
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/****************************************************
+ val_comp:
+ compare two values per cond
+ returns result of comparison
+****************************************************/
+boolean val_cmp(valstruct *left, valstruct *right, vtw_cond_e cond)
+{
+ unsigned int left_parts[9], right_parts[9];
+ vtw_type_e val_type;
+ int parts_num, lstop, rstop, lcur, rcur;
+ char const *format;
+ char *lval, *rval;
+ int ret=0, step=0, res=0;
+
+ val_type = left->val_type;
+ if (left->cnt)
+ lstop = left->cnt;
+ else
+ lstop = 1;
+ if (right->cnt)
+ rstop = right->cnt;
+ else
+ rstop = 1;
+
+ for(lcur = 0; lcur < lstop; ++lcur) {
+ if (!lcur && !left->cnt)
+ lval = left->val;
+ else
+ lval = left->vals[lcur];
+ for(rcur = 0; rcur < rstop; ++rcur) {
+ if (!rcur && !right->cnt)
+ rval = right->val;
+ else
+ rval = right->vals[rcur];
+ switch (val_type) {
+ case IPV6_TYPE:
+ parts_num = 8;
+ goto ipv6_common;
+ case IPV6NET_TYPE:
+ parts_num = 9;
+ ipv6_common:
+ scan_ipv6(lval,left_parts);
+ scan_ipv6(rval,right_parts);
+ break;
+ case IPV4_TYPE:
+ case IPV4NET_TYPE:
+ case MACADDR_TYPE:
+ case INT_TYPE:
+ format = cond_formats[val_type];
+ parts_num = cond_format_lens[val_type];
+ (void) sscanf(lval, format, left_parts, left_parts+1,
+ left_parts+2, left_parts+3, left_parts+4,
+ left_parts+5);
+ (void) sscanf(rval, format, right_parts, right_parts+1,
+ right_parts+2, right_parts+3, right_parts+4,
+ right_parts+5);
+ break;
+ case TEXT_TYPE:
+ case BOOL_TYPE:
+ res = strcmp(lval, rval);
+ goto done_comp;
+ default:
+ printf("Unknown value in switch on line %d\n", __LINE__);
+ exit(-5);
+ }
+ /* here to do a multistep int compare */
+ for (step = 0; step < parts_num; ++ step) {
+ if (left_parts[step] > right_parts[step]) {
+ res = 1;
+ break; /* no reason to continue checking other steps */
+ }
+ if (left_parts[step] < right_parts[step]) {
+ res = -1;
+ break; /* no reason to continue checking other steps */
+ }
+ res = 0;
+ }
+ done_comp:
+ if(res > 0) res = 1;
+ else if(res < 0) res = -1;
+ ret = ((res == cond1[cond]) ||
+ (res == cond2[cond]));
+ if (ret && cond == IN_COND) {
+ set_in_cond_tik(rcur); /* for delete */
+ /* one success is enough for right cycle
+ in case of IN_COND, continue left cycle */
+ break;
+ }
+ if (!ret && cond != IN_COND)
+ /* one failure is enough in cases
+ other than IN_COND - go out */
+ return ret;
+ /* in all other cases:
+ (fail & IN_COND) or (success & !IN_COND)
+ contniue checking; */
+ }
+ }
+ return ret;
+}
+
+
+
+/****************************************************
+ check_comp:
+ evaluate comparison node.
+ returns boolean value of result
+****************************************************/
+static boolean check_comp(vtw_node *cur)
+{
+ int ret;
+ int status;
+ valstruct left, right;
+
+ memset(&left, 0 , sizeof(left));
+ memset(&right, 0 , sizeof(right));
+ ret = FALSE; /* in case of status */
+ status = eval_va(&left, cur->vtw_node_left);
+ if (status)
+ goto free_and_return;
+ status = eval_va(&right, cur->vtw_node_right);
+ if (status)
+ goto free_and_return;
+ if(left.val_type != right.val_type) {
+ printf("Different types in comparison\n");
+ goto free_and_return;
+ }
+ ret = val_cmp(&left, &right,cur->vtw_node_aux);
+ free_and_return:
+ if (left.free_me)
+ free_val(&left);
+ if (right.free_me)
+ free_val(&right);
+ return ret;
+}
+
+/******************
+ Change value of var in the file
+
+*****************/
+
+static int write_value_to_file(const char* var_path,const char* value) {
+
+ if(var_path && value) {
+
+ {
+ /*Build directory, if necessary:*/
+ clind_path_ref var_dir_path=clind_path_construct(var_path);
+
+ if(!var_dir_path) bye("Can not construct path %s", var_path);
+ else {
+
+ char* end = clind_path_pop_string(var_dir_path);
+
+ if(!end || strcmp(end,VAL_NAME)) {
+ bye("Wrong end of path: %s (%s)", end,var_path);
+ }
+
+ free(end);end=NULL;
+
+ touch();
+ touch_dir(clind_path_get_path_string(var_dir_path));
+
+ clind_path_destruct(&var_dir_path);
+ }
+ }
+
+ {
+ /*Write to file*/
+ FILE* fp = fopen(var_path, "w");
+ if(!fp) bye("Can not open value file %s", var_path);
+
+ if (fputs(value, fp) < 0 || fputc('\n',fp) < 0)
+ bye("Error writing file %s", var_path);
+
+ fclose(fp);
+
+ }
+ }
+
+ return 0;
+}
+
+static int change_var_value(const char* var_reference,const char* value, int active_dir) {
+
+ int ret=-1;
+
+ if(var_reference && value) {
+
+ char* var_path=NULL;
+
+ clind_path_ref n_cfg_path=NULL;
+ clind_path_ref n_tmpl_path=NULL;
+ clind_path_ref n_cmd_path=NULL;
+
+ if(set_reference_environment(var_reference,
+ &n_cfg_path,
+ &n_tmpl_path,
+ &n_cmd_path,
+ active_dir)==0) {
+
+ clind_val cv;
+
+ memset(&cv,0,sizeof(cv));
+
+ if(clind_config_engine_apply_command_path(n_cfg_path,
+ n_tmpl_path,
+ n_cmd_path,
+ FALSE,
+ &cv,
+ get_cdirp(),
+ get_tdirp(),
+ TRUE)==0) {
+ var_path=cv.value;
+
+ }
+
+ }
+
+ if(n_cfg_path) clind_path_destruct(&n_cfg_path);
+ if(n_tmpl_path) clind_path_destruct(&n_tmpl_path);
+ if(n_cmd_path) clind_path_destruct(&n_cmd_path);
+
+ if(var_path) {
+ ret=write_value_to_file(var_path,value);
+ free(var_path);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************
+ check_syn:
+ evaluate syntax tree;
+ returns TRUE if all checks are OK,
+ returns FALSE if check fails.
+****************************************************/
+static boolean check_syn_func(vtw_node *cur,const char* func,int line)
+{
+ int status;
+ int ret;
+ int ii;
+
+ switch(cur->vtw_node_oper) {
+ case LIST_OP:
+ ret = check_syn(cur->vtw_node_left);
+ if (!is_in_commit() && cur->vtw_node_aux)
+ ret = TRUE;
+ if (!ret || !cur->vtw_node_right) /* or no right operand */
+ return ret;
+ return check_syn(cur->vtw_node_right);
+ case HELP_OP:
+ ret = check_syn(cur->vtw_node_left);
+ if (ret <= 0){
+ if (expand_string(cur->vtw_node_right->vtw_node_string) == VTWERR_OK) {
+ fprintf(stderr, exe_string);
+ fprintf(stderr, "\n");
+ printf(exe_string);
+ printf("\n");
+ }
+ }
+ return ret;
+
+ case ASSIGN_OP:
+
+ if (is_in_exec()) {
+
+ valstruct right;
+
+ char* var_reference = NULL;
+
+ memset(&right, 0, sizeof(right));
+ status = eval_va(&right, cur->vtw_node_right);
+
+ if (status || right.cnt) { /* bad or multi */
+ if (right.free_me) free_val(&right);
+ return FALSE;
+ }
+
+ var_reference = strdup(cur->vtw_node_left->vtw_node_string+2);
+
+ {
+ int i=0;
+ while(var_reference[i]) {
+ if(var_reference[i]==')') {
+ var_reference[i]=0;
+ break;
+ }
+ i++;
+ }
+ }
+
+ change_var_value(var_reference,right.val,FALSE);
+ change_var_value(var_reference,right.val,TRUE);
+
+ if (right.free_me) free_val(&right);
+
+ if(var_reference) free(var_reference);
+ }
+
+ return TRUE;
+
+ case EXEC_OP:
+ /* for every value */
+ if (in_validate_val) {
+ char *save_at = get_at_string();
+ for(ii = 0; ii < validate_value_val.cnt || ii == 0; ++ii) {
+ set_at_string(validate_value_val.cnt?
+ validate_value_val.vals[ii]:validate_value_val.val);
+ status = expand_string(cur->vtw_node_left->vtw_node_string);
+ if (status != VTWERR_OK) {
+ set_at_string(save_at);
+ return FALSE;
+ }
+ ret = system(exe_string);
+ if (ret) {
+ set_at_string(save_at);
+ return FALSE;
+ }
+ }
+ set_at_string(save_at);
+ return TRUE;
+ }
+ /* else */
+ status = expand_string(cur->vtw_node_left->vtw_node_string);
+ if (status != VTWERR_OK) {
+ return FALSE;
+ }
+ ret = system(exe_string);
+ return !ret;
+
+ case PATTERN_OP: /* left to var, right to pattern */
+ {
+ valstruct left;
+ regex_t myreg;
+ boolean ret;
+ int ii;
+
+ ret = TRUE;
+ status = eval_va(&left, cur->vtw_node_left);
+ if (status) {
+ ret = FALSE;
+ goto free_and_return;
+ }
+ status = regcomp(&myreg, cur->vtw_node_right->vtw_node_string,
+ REG_EXTENDED);
+ if (status)
+ bye("Can not compile regex |%s|, result %d\n",
+ cur->vtw_node_right->vtw_node_string, status);
+ /* for every value */
+ for(ii = 0; ii < left.cnt || ii == 0; ++ii) {
+ status = regexec(&myreg, left.cnt?
+ left.vals[ii]:left.val,
+ 0, 0, 0);
+ if(status) {
+ ret = FALSE;
+ break;
+ }
+ }
+ free_and_return:
+ if (left.free_me)
+ free_val(&left);
+ return ret;
+ }
+
+ case OR_OP:
+ ret = check_syn(cur->vtw_node_left) ||
+ check_syn(cur->vtw_node_right);
+ return ret;
+ case AND_OP:
+ ret = check_syn(cur->vtw_node_left) &&
+ check_syn(cur->vtw_node_right);
+ return ret;
+ case NOT_OP:
+ ret = check_syn(cur->vtw_node_left);
+ return !ret;
+
+ case COND_OP: /* aux field specifies cond type (GT, GE, etc.)*/
+ ret = check_comp(cur);
+ return ret;
+
+ case VAL_OP:
+ printf("VAL op in check_syn\n");
+ exit(-4);
+ case VAR_OP:
+ printf("VAR op in check_syn\n");
+ exit(-4);
+ default:
+ printf("unknown op %d in check_syn\n", cur->vtw_node_oper);
+ exit(-4);
+ }
+}
+
+/*************************************************
+ copy_path:
+ copy path
+ if destination path owns memory, free it
+**************************************************/
+static void copy_path(vtw_path *to, vtw_path *from)
+{
+ if (to->path_buf)
+ my_free(to->path_buf);
+ if (to->path_ends)
+ my_free(to->path_ends);
+ *to = *from;
+ to->path_buf = (char *) my_malloc(from->path_alloc+2, "copy_path1");
+ memcpy(to->path_buf, from->path_buf, to->path_alloc + 1);
+ to->path = to->path_buf + (from->path-from->path_buf);
+ to->path_ends = (int *) my_malloc(to->path_ends_alloc * sizeof(int),
+ "copy_path2");
+ memcpy(to->path_ends, from->path_ends,
+ to->path_ends_alloc * sizeof(int));
+}
+
+/*****************************************************
+ eval_va:
+ converts VAR_OP or VAL_OP node into valstruct
+ in case of VAR_OP we need to find corresponding
+ template node to obtain type.
+
+*****************************************************/
+static int eval_va(valstruct *res, vtw_node *node)
+{
+ char *cp=NULL;
+ char *pathp=NULL;
+ int status=0;
+
+ switch (node->vtw_node_oper) {
+ case VAR_OP:
+
+ {
+ char *endp = 0;
+ clind_path_ref n_cfg_path=NULL;
+ clind_path_ref n_tmpl_path=NULL;
+ clind_path_ref n_cmd_path=NULL;
+
+ pathp = node->vtw_node_string;
+
+ assert(pathp[0]=='$' && pathp[1]=='(');
+ pathp += 2;
+
+ if(pathp[0] == '@' && pathp[1]!='@'){
+ /* this is why we passed at_val all around */
+ *res = validate_value_val;
+ res->free_me = FALSE;
+ return 0;
+ }
+
+ memset(res,0,sizeof(*res));
+
+ if ((endp = strchr(pathp, ')')) == NULL) {
+ printf("invalid VAR_OP [%s]\n", node->vtw_node_string);
+ return VTWERR_BADPATH;
+ }
+
+ *endp = 0;
+
+ if(set_reference_environment(pathp,
+ &n_cfg_path,
+ &n_tmpl_path,
+ &n_cmd_path,
+ is_in_delete_action())==0) {
+
+ clind_val cv;
+
+ memset(&cv,0,sizeof(cv));
+
+ status=clind_config_engine_apply_command_path(n_cfg_path,
+ n_tmpl_path,
+ n_cmd_path,
+ FALSE,
+ &cv,
+ get_cdirp(),
+ get_tdirp(),
+ FALSE);
+
+ if(status==0) {
+ if(cv.value) {
+ res->val_type = cv.val_type;
+ res->free_me = TRUE;
+ res->val = cv.value;
+ }
+ }
+ }
+
+ if(n_cfg_path) clind_path_destruct(&n_cfg_path);
+ if(n_tmpl_path) clind_path_destruct(&n_tmpl_path);
+ if(n_cmd_path) clind_path_destruct(&n_cmd_path);
+
+ *endp = ')';
+
+ return status;
+ }
+
+ case VAL_OP:
+ *res = node->vtw_node_val;
+ res->free_me = FALSE;
+ return 0;
+ case B_QUOTE_OP:
+ {
+ FILE *f;
+ int a_len, len, rd;
+
+ status = expand_string(node->vtw_node_string);
+ if (status != VTWERR_OK) {
+ return FALSE;
+ }
+ f = popen(exe_string, "r");
+ if (!f)
+ return -1;
+#define LEN 24
+ len = 0;
+ cp = my_malloc(LEN,"");
+ a_len = LEN;
+ for(;;){
+ rd = fread(cp + len, 1, a_len - len , f);
+ len += rd;
+ if (len < a_len)
+ break;
+ cp = my_realloc(cp, a_len+LEN, "");
+ a_len += LEN;
+ }
+ cp[len] = 0;
+ pclose(f);
+ memset(res, 0, sizeof (*res));
+ res->val_type = TEXT_TYPE;
+ res->free_me = TRUE;
+ res->val = cp;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+/**********************************************************
+ expand_string:
+ expand string replacing var references with the appropriate
+ values, the formed string is collected in the buffer pointed
+ at by the global exe_string. The buffer dynamically allocated
+ and reallocated.
+***********************************************************/
+static int expand_string(char *stringp)
+{
+ char *scanp;
+ char *resp = exe_string;
+ int left = exe_string_len;
+ int my_len;
+ int len;
+
+ scanp = stringp; /* save stringp for printf */
+
+ do{
+
+ if (left <= 1){
+ my_len = resp - exe_string;
+ exe_string_len += EXE_STRING_DELTA;
+ exe_string = my_realloc(exe_string, exe_string_len, "expand_string 1");
+ left += EXE_STRING_DELTA;
+ resp = exe_string + my_len;
+ /* back in business */
+ }
+ if (*scanp != '$') {
+ if(*scanp == '\\' && scanp[1] == '$') {
+ /* escaped $, treat as regular char */
+ ++scanp;
+ }
+ *resp++ = *scanp++;
+ --left;
+ } else {
+
+ char *cp=NULL;
+ boolean my_cp=FALSE;
+
+ if (scanp[1] != '('){
+
+ printf("Badly formed var reference in %s\n", stringp);
+ exit (VTWERR_BADPATH);
+
+ } else if(scanp[2] == '@' && scanp[3] == ')') {
+
+ cp = get_at_string();
+ my_cp = FALSE;
+ scanp += 4;
+
+ } else {
+
+ clind_path_ref n_cfg_path=NULL;
+ clind_path_ref n_tmpl_path=NULL;
+ clind_path_ref n_cmd_path=NULL;
+
+ char *endp;
+
+ endp = strchr(scanp, ')');
+ if (!endp ){
+ return -1;
+ }
+
+ scanp += 2;
+ /* path reference */
+ *endp = 0;
+ if (endp == scanp)
+ bye("Empty path");
+
+ if(set_reference_environment(scanp,
+ &n_cfg_path,
+ &n_tmpl_path,
+ &n_cmd_path,
+ is_in_delete_action())==0) {
+
+ clind_val cv;
+
+ memset(&cv,0,sizeof(cv));
+
+ if(clind_config_engine_apply_command_path(n_cfg_path,
+ n_tmpl_path,
+ n_cmd_path,
+ FALSE,
+ &cv,
+ get_cdirp(),
+ get_tdirp(),
+ FALSE)==0) {
+ cp=cv.value;
+
+ }
+
+ }
+
+ if(n_cfg_path) clind_path_destruct(&n_cfg_path);
+ if(n_tmpl_path) clind_path_destruct(&n_tmpl_path);
+ if(n_cmd_path) clind_path_destruct(&n_cmd_path);
+
+ if(!cp) {
+ cp="";
+ } else {
+ my_cp=TRUE;
+ }
+
+ *endp = ')';
+
+ scanp = strchr(scanp, ')') + 1;
+ }
+ len = strlen(cp);
+ while(len + 1 > left) { /* 1 for termination */
+ my_len = resp - exe_string;
+ exe_string_len += EXE_STRING_DELTA;
+ exe_string = my_realloc(exe_string, exe_string_len, "expand_string 2");
+ left += EXE_STRING_DELTA;
+ resp = exe_string + my_len;
+ /* back in business */
+ }
+
+ strcpy(resp, cp);
+ if(my_cp && cp) free(cp);
+ resp += len;
+ left -= len;
+ }
+
+ } while(*scanp);
+
+ *resp = 0;
+
+ return VTWERR_OK;
+}
+
+/*****************************************************
+ free_sorted:
+ free all memory allocated to sorted
+*****************************************************/
+void free_sorted(vtw_sorted *sortp)
+{
+ if(sortp->ptrs)
+ my_free(sortp->ptrs);
+ if (sortp->parts)
+ my_free(sortp->parts);
+}
+
+
+/*****************************************************
+ free_def:
+ free all memory allocated to def
+*****************************************************/
+void free_def(vtw_def *defp)
+{
+ vtw_act_type act;
+ for(act=0; act<top_act; ++ act)
+ if (defp->actions[act].vtw_list_head)
+ free_node_tree(defp->actions[act].vtw_list_head);
+ if (defp->def_type_help)
+ my_free(defp->def_type_help);
+ if (defp->def_default)
+ my_free(defp->def_default);
+}
+
+/*****************************************************
+ free_node - add node to free list
+*****************************************************/
+static void free_node(vtw_node *node)
+{
+ --node_cnt;
+ ++free_node_cnt;
+ node->vtw_node_left = vtw_free_nodes;
+ vtw_free_nodes = node;
+}
+
+/*****************************************************
+ free_node_tree - add all nodes of the tree to free list
+*****************************************************/
+static void free_node_tree(vtw_node *node)
+{
+ if (node->vtw_node_left)
+ free_node_tree(node->vtw_node_left);
+ if (node->vtw_node_right)
+ free_node_tree(node->vtw_node_right);
+ if (node->vtw_node_string)
+ free_string(node->vtw_node_string);
+ if (node->vtw_node_val.free_me)
+ free_val(&(node->vtw_node_val));
+ free_node(node);
+}
+
+static void free_path(vtw_path *path)
+{
+ if (path->path_ends)
+ my_free(path->path_ends);
+ if (path->path_buf) {
+ my_free(path->path_buf);
+ }
+}
+
+static void free_reuse_list()
+{
+ vtw_node *next;
+ int cnt = 0;
+
+ while (vtw_free_nodes) {
+ next = vtw_free_nodes->vtw_node_left;
+ my_free(vtw_free_nodes);
+ ++cnt;
+ vtw_free_nodes = next;
+ --free_node_cnt;
+ }
+#if DEBUG
+ printf("%d nodes used\n", cnt);
+#endif
+}
+
+/*****************************************************
+ free_val - dealloc allocated memory of valstruct
+*****************************************************/
+void free_val(valstruct *val)
+{
+ int cnt;
+
+ assert(val->free_me);
+ if (val->val)
+ my_free(val->val);
+ for (cnt = 0; cnt < val->cnt; ++ cnt)
+ my_free(val->vals[cnt]);
+ if(val->vals)
+ my_free(val->vals);
+}
+/*****************************************************
+ free_string - dealloc string
+ just free for now, we might do something else later
+*****************************************************/
+static void free_string(char *str)
+{
+ my_free(str);
+}
+
+
+/*****************************************************
+ get_node - take node from free list or allocate
+*****************************************************/
+static vtw_node * get_node(void)
+{
+ vtw_node *ret;
+ if (vtw_free_nodes){
+ ret = vtw_free_nodes;
+ vtw_free_nodes = vtw_free_nodes->vtw_node_left;
+ --free_node_cnt;
+ } else {
+ ret = my_malloc(sizeof(vtw_node), "New node");
+ }
+ ++node_cnt;
+ memset(ret, 0, sizeof(vtw_node));
+ return ret;
+}
+
+/****************************************************
+ get_value:
+ for a given path (*path) verify that value exists,
+ open it and read it. The pointer to allocated
+ memory is returned in valpp. It is responsibility
+ of a caller to release memory.
+ Returns:
+******************************************************/
+int get_value(char **valpp, vtw_path *pathp)
+{
+ struct stat statbuf;
+ int status = VTWERR_OK;
+ char const *err = NULL;
+ FILE *in = NULL;
+ char *valp;
+ int readcnt;
+
+
+ /* find value */
+ *valpp = 0;
+ push_path(pathp, val_name);
+
+ if (lstat(pathp->path, &statbuf) < 0) {
+ err = "no value file in [%s]\n";
+ goto bad_path;
+ }
+ if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
+ err = "no value file in [%s]\n";
+ goto bad_path;
+ }
+ in = fopen(pathp->path, "r");
+ if (!in) {
+ err = "Can not open value file in [%s]\n";
+ goto bad_path;
+ }
+ valp = my_malloc(statbuf.st_size + 1, "get_value");
+ readcnt = fread(valp, 1, statbuf.st_size, in);
+ if (readcnt != statbuf.st_size) {
+ my_free(valp);
+ cli_val_alloc = 0;
+ err = "Error reading value file in [%s]\n";
+ goto bad_path;
+ }
+ valp[statbuf.st_size] = 0;
+ /* remove \n at the line end */
+ if (valp[statbuf.st_size - 1] == '\n')
+ valp[statbuf.st_size - 1] = 0;
+ *valpp = valp;
+ status = 0;
+pop:
+ if (in)
+ fclose(in);
+ pop_path(pathp);
+ if (err) {
+ fprintf(stderr, err, pathp->path_buf + m_path.print_offset);
+ printf(err, pathp->path_buf + m_path.print_offset);
+ }
+ return status;
+ bad_path:
+ status = VTWERR_BADPATH;
+ goto pop;
+}
+
+int get_value_to_at_string(vtw_path *pathp) {
+
+ char* at=NULL;
+ int status = get_value(&at,pathp);
+
+ if(status==0) {
+ set_at_string(at);
+ } else {
+ set_at_string(NULL);
+ }
+
+ return status;
+}
+
+/*****************************************************
+ out_of_memeory
+ print out of memory message and exit
+*****************************************************/
+void out_of_memory()
+{
+ printf("\n\t!!! OUT OF MEMORY !!!\n");
+ exit(-1);
+}
+
+/*************************************************
+ init_path:
+ init path, exit if not able (out_of_memory)
+**************************************************/
+void init_path(vtw_path *path, const char *root)
+{
+ long path_len;
+ memset(path, 0, sizeof(vtw_path));
+ path_len = pathconf(root, _PC_PATH_MAX);
+ if (path_len < 0)
+ path_len = PATH_DELTA;
+ path->path_alloc = path_len - 2;
+ /* 1 byte for null termination, and 1 byte for '/' */
+ path->path_buf = path->path =
+ (char *)my_malloc(path_len, "init_path 1");
+ strcpy(path->path, root);
+ path->path_len = strlen(root);
+ path->path_ends = (int *)my_malloc(ENDS_ALLOC * sizeof(int *),
+ "init_path 2");
+ path->path_lev = 1;
+ path->path_ends[0] = path->path_len;
+ path->path_ends_alloc = ENDS_ALLOC;
+}
+
+/*****************************************************
+ pop_path - shorten path by one segment
+*****************************************************/
+
+void pop_path(vtw_path *path)
+{
+ if (--path->path_lev < 1) {
+ INTERNAL;
+ }
+ path->path_len = path->path_ends[path->path_lev - 1];
+ path->path_buf[path->path_len] = 0;
+}
+void warrant_path(vtw_path *path, int len)
+{
+ int delta = path->path - path->path_buf;
+
+ while(path->path_alloc - path->path_len < len + 1){
+ path->path_buf = (char *)my_realloc(path->path_buf,
+ path->path_alloc +
+ PATH_DELTA, "push_path 1");
+ path->path_alloc += PATH_DELTA;
+ }
+ path->path = path->path_buf + delta;
+}
+/*****************************************************
+ push_path - extend path by '/' and one new segment
+*****************************************************/
+void push_path(vtw_path *path, char *segm)
+{
+ int len;
+ char *cp;
+ char *pp;
+
+ for(cp=segm, len=0;*cp;++cp, ++len)
+ if(*cp=='%' || *cp=='/')
+ len +=2;
+ warrant_path(path, len + 1);
+ path->path_buf[path->path_len] = '/';
+ path->path_buf[++path->path_len] = 0;
+ for(pp=path->path_buf + path->path_len,cp=segm;
+ *cp;++cp, ++pp)
+ if(*cp=='%') {
+ pp[0] = '%';
+ pp[1] = '2';
+ pp[2] = '5';
+ pp += 2;
+ }else if (*cp == '/') {
+ pp[0] = '%';
+ pp[1] = '2';
+ pp[2] = 'F';
+ pp += 2;
+ }else
+ *pp = *cp;
+ *pp = 0;
+
+ path->path_len += len;
+ if (path->path_lev == path->path_ends_alloc){
+ path->path_ends_alloc += ENDS_ALLOC;
+ path->path_ends = (int *)my_realloc(path->path_ends,
+ sizeof(int *)*path->path_ends_alloc, "puhs_path 2");
+ }
+ path->path_ends[path->path_lev++] = path->path_len;
+}
+
+/****************************************************
+ scan_ipv6:
+ scans ipv6 or ipv6net pointed by val
+ and returns as array of integers pointed
+ by parts
+***************************************************/
+static void scan_ipv6(char *val, unsigned int *parts)
+{
+ int num = 0;
+ int num_cnt = 0;
+ int dot_dot_pos = -1;
+ int dot_cnt = 0;
+ char c;
+ char *p;
+ int base = 16;
+ int total = 8;
+ int gap;
+
+ for (p = val;TRUE; ++p) {
+ switch ((c = *p)) {
+ case '.':
+ if (dot_cnt == 0) {
+ /* turn out it was decimal, convert our wrong
+ hex interpretation;
+ decimal may not have more than 3 digits */
+ num = (num/256)*100 + (num%256)/16*10 + num%16;
+ base = 10;
+ }
+ ++dot_cnt;
+ break;
+ case ':':
+ if (p[1] == ':'){
+ ++p;
+ dot_dot_pos = num_cnt + 1;
+ }
+ break;
+ case '/':
+ base = 10;
+ total = 9;
+ break;
+ case 0:
+ break;
+ default:
+ /* must be a digit */
+ c = tolower(*p);
+ if (isdigit(c))
+ num = num * base + c - '0';
+ else
+ num = num * base + c - 'a' + 10;
+ continue;
+ }
+ /* close the number */
+ /* the case of "::234: etc "
+ handled automatically as 0::234
+ with allowing :: to represent 0 or more
+ groups instead of 1 or more */
+
+ parts[num_cnt] = num;
+ num = 0;
+ ++num_cnt;
+ /* combine two decimal if needed */
+ if (dot_cnt == 2 || (dot_cnt == 3 && (c == 0 || c == '/'))) {
+ --num_cnt;
+ parts[num_cnt - 1] = parts[num_cnt - 1] * 256 + parts[num_cnt];
+ }
+ if (*p == 0)
+ break;
+ }
+ /* replace '::' with 0s */
+ if (dot_dot_pos != -1 && total != num_cnt) {
+ int i;
+ gap = total - num_cnt;
+ if (dot_dot_pos != num_cnt)
+ memmove(parts+dot_dot_pos+gap, parts+dot_dot_pos,
+ (num_cnt-dot_dot_pos)*sizeof(int));
+ for (i = 0; i<gap; ++i)
+ parts[dot_dot_pos+i] = 0;
+ }
+}
+
+/***************************************************
+ switch_path:
+ switch m_path between mcd and ccd directories -
+ modified (UNIONFS) configuration and changed
+ (real) configuration
+****************************************************/
+void switch_path(first_seg *segp)
+{
+ memcpy(m_path.path_buf + segp->f_segoff, segp->f_segp,
+ segp->f_seglen);
+ m_path.path = m_path.path_buf + segp->f_segoff;
+}
+
+/*************************************************
+ validate_value:
+ validates value against type and syntax
+ return TRUE if OK, FALSE otherwise
+**************************************************/
+boolean validate_value(vtw_def *def, char *cp)
+{
+ int status;
+ boolean ret=TRUE;
+
+ /* prepare cur_value */
+ set_at_string(cp);
+ status = char2val(def, cp, &validate_value_val);
+ if (status != VTWERR_OK)
+ return FALSE;
+ if ((def->def_type!=ERROR_TYPE) &&
+ (validate_value_val.val_type != def->def_type)) {
+ if (def->def_type_help){
+ (void)expand_string(def->def_type_help);
+ printf("%s\n", exe_string);
+ fprintf(stderr, "%s\n", exe_string);
+ } else {
+ printf("Incorrect type of %s, need %s\n",
+ cp, type_to_name(def->def_type));
+ }
+ ret = FALSE;
+ goto validate_value_free_and_return;
+ }
+ ret = TRUE;
+ if (def->actions && def->actions[syntax_act].vtw_list_head){
+ in_validate_val = TRUE;
+ ret = check_syn(def->actions[syntax_act].vtw_list_head);
+ in_validate_val = FALSE;
+ }
+ validate_value_free_and_return:
+ free_val(&validate_value_val);
+ return ret;
+}
+
+
+int cli_val_read(char *buf, int max_size)
+{
+ int len;
+
+ if (cli_val_len > max_size)
+ len = max_size;
+ else
+ len = cli_val_len;
+ if (len) {
+ (void)memcpy(buf, cli_val_ptr, len);
+ cli_val_len -= len;
+ cli_val_ptr += len;
+ }
+ return len;
+}
+/*==========================================================*/
+/* MEMORY */
+/*==========================================================*/
+
+void *my_malloc(size_t size, const char *name)
+{
+ return malloc(size);
+}
+void *my_realloc(void *ptr, size_t size, const char *name)
+{
+ return realloc(ptr, size);
+}
+
+void my_free(void *ptr)
+{
+ free(ptr);
+}
+
+/*************************************************
+ my_strdup:
+ do a strdup,
+ exit on no memory
+**************************************************/
+char *my_strdup(const char *s, const char *name)
+{
+ return strdup(s);
+}
+
+void done()
+{
+ free_reuse_list();
+ free_path(&t_path);
+ free_path(&m_path);
+ if (exe_string)
+ my_free(exe_string);
+}
+void mark_paths(vtw_mark *markp)
+{
+ markp->m_lev = m_path.path_lev;
+ markp->t_lev = t_path.path_lev;
+}
+void restore_paths(vtw_mark *markp)
+{
+ while(markp->m_lev < m_path.path_lev)
+ pop_path(&m_path);
+ while(markp->t_lev < t_path.path_lev)
+ pop_path(&t_path);
+}
+
+void touch()
+{
+ char *command;
+ command = my_malloc(strlen(get_mdirp()) + 20, "delete");
+ sprintf(command, "touch %s/%s", get_mdirp(), MOD_NAME);
+ system(command);
+ free(command);
+}
+
+char *type_to_name(vtw_type_e type) {
+ switch(type) {
+ case INT_TYPE: return("u32");
+ case IPV4_TYPE: return("ipv4");
+ case IPV4NET_TYPE: return("ipv4net");
+ case IPV6_TYPE: return("ipv6");
+ case IPV6NET_TYPE: return("ipv6net");
+ case MACADDR_TYPE: return("macaddr");
+ case DOMAIN_TYPE: return("domain");
+ case TEXT_TYPE: return("text");
+ case BOOL_TYPE: return("bool");
+ default: return("unknown");
+ }
+}
+
+#if 1
+void
+dump_log(int argc, char **argv)
+{
+}
+#else
+void dump_log(int argc, char **argv)
+{
+ int i;
+ int len;
+ char *cp;
+
+ len = 0;
+ for (i=0; i<argc;++i)
+ len += strlen(argv[i]);
+ len += argc;
+ cp = my_malloc(len, "dump_log");
+ len = 0;
+ for (i=0; i<argc;++i){
+ strcpy(cp+len, argv[i]);
+ len += strlen(argv[i]);
+ cp[len]= ' ';
+ ++len;
+ }
+ cp[len-1]=0;
+ printf("Command: %s\n",cp);
+ my_free(cp);
+}
+#endif
+
+/********************* New Dir ****************************/
+
+static int set_reference_environment(const char* var_reference,
+ clind_path_ref *n_cfg_path,
+ clind_path_ref *n_tmpl_path,
+ clind_path_ref *n_cmd_path,
+ int active) {
+
+ if(var_reference && n_cfg_path && n_tmpl_path && n_cmd_path) {
+
+ if(*var_reference=='/') {
+
+ if(is_in_delete_action()) {
+ *n_cfg_path=clind_path_construct(get_adirp());
+ } else {
+ *n_cfg_path=clind_path_construct(get_mdirp());
+ }
+ *n_tmpl_path=clind_path_construct(get_tdirp());
+ *n_cmd_path=clind_path_construct(var_reference);
+
+ } else {
+
+ vtw_path n_vt_path;
+
+ memset(&n_vt_path,0,sizeof(n_vt_path));
+
+ copy_path(&n_vt_path, &m_path);
+ /* switch to MPATH */
+ memcpy(n_vt_path.path_buf + get_f_seg_m_ptr()->f_segoff, get_f_seg_m_ptr()->f_segp,
+ get_f_seg_m_ptr()->f_seglen);
+ n_vt_path.path = n_vt_path.path_buf + get_f_seg_m_ptr()->f_segoff;
+
+ if(active) {
+
+ vtw_path active_path;
+
+ memset(&active_path,0,sizeof(active_path));
+
+ copy_path(&active_path, &n_vt_path);
+
+ memcpy(active_path.path_buf + get_f_seg_a_ptr()->f_segoff, get_f_seg_a_ptr()->f_segp,
+ get_f_seg_a_ptr()->f_seglen);
+ active_path.path = active_path.path_buf + get_f_seg_a_ptr()->f_segoff;
+
+ *n_cfg_path=clind_path_construct(active_path.path);
+
+ } else {
+
+ *n_cfg_path=clind_path_construct(n_vt_path.path);
+
+ }
+
+ *n_tmpl_path=clind_path_construct(t_path.path);
+ *n_cmd_path=clind_path_construct(var_reference);
+
+ }
+
+ return 0;
+
+ } else {
+
+ return -1;
+
+ }
+}
+
+/**********************************************************/