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.c343
1 files changed, 230 insertions, 113 deletions
diff --git a/src/cli_new.c b/src/cli_new.c
index b0535d8..9cc9777 100644
--- a/src/cli_new.c
+++ b/src/cli_new.c
@@ -21,6 +21,8 @@
#include "cli_objects.h"
#include "cli_val_engine.h"
+#include "cstore/cstore-c.h"
+
/* Defines: */
#define EXE_STRING_DELTA 512
@@ -32,9 +34,12 @@
#define VAR_REF_MARKER "$VAR("
#define VAR_REF_MARKER_LEN 5
+#define VAR_REF_SELF_MARKER "$VAR(@)"
+#define VAR_REF_SELF_MARKER_LEN 7
/* Global vars: */
vtw_path m_path, t_path;
+void *var_ref_handle = NULL;
/* Local vars: */
static vtw_node *vtw_free_nodes; /* linked via left */
@@ -114,8 +119,8 @@ void bye(const char *msg, ...)
{
va_list ap;
- fprintf(out_stream, "%s failed\n",
- (cli_operation_name) ? cli_operation_name : "Operation");
+ OUTPUT_USER("%s failed\n",
+ (cli_operation_name) ? cli_operation_name : "Operation");
va_start(ap, msg);
if (is_echo())
@@ -239,6 +244,74 @@ void append(vtw_list *l, vtw_node *n, int aux)
l->vtw_list_tail = lnode;
}
+/* this recursive function walks the specified "vtw_node" tree representing
+ * "syntax" actions and looks for the first "in" action on a "self ref"
+ * specified as follows in template:
+ * $VAR(@) in "val1", "val2", ...
+ *
+ * if found, the corresponding valstruct is returned. this is used by the
+ * completion mechanism to get such "allowed" values specified by "syntax".
+ */
+const valstruct *
+get_syntax_self_in_valstruct(vtw_node *vnode)
+{
+ const valstruct *ret = NULL;
+ if (!vnode) {
+ return NULL;
+ }
+ if (vnode->vtw_node_oper == COND_OP && vnode->vtw_node_aux == IN_COND
+ && vnode->vtw_node_left && vnode->vtw_node_right) {
+ vtw_node *ln = vnode->vtw_node_left;
+ vtw_node *rn = vnode->vtw_node_right;
+ if (ln->vtw_node_oper == VAR_OP && ln->vtw_node_string
+ && strncmp(VAR_REF_SELF_MARKER, ln->vtw_node_string,
+ VAR_REF_SELF_MARKER_LEN) == 0
+ && rn->vtw_node_oper == VAL_OP) {
+ // found a matching syntax action. return valstruct.
+ return &(rn->vtw_node_val);
+ }
+ }
+ // this node does not match. walk down.
+ ret = get_syntax_self_in_valstruct(vnode->vtw_node_left);
+ if (!ret) {
+ ret = get_syntax_self_in_valstruct(vnode->vtw_node_right);
+ }
+ return ret;
+}
+
+/* execute specified command and return output in specified buffer as
+ * a null-terminated string. return number of characters in the output
+ * or -1 if failed.
+ *
+ * NOTE: NO attempt is made to ensure the security of the specified command.
+ * in other words, *DO NOT* use a user-supplied string as the command
+ * for this function.
+ */
+int
+get_shell_command_output(const char *cmd, char *buf, unsigned int buf_size)
+{
+ int ret = -1;
+ FILE *cmd_in = NULL;
+ size_t cnt = 0;
+
+ if (!buf || !buf_size) {
+ return -1;
+ }
+ if (!(cmd_in = popen(cmd, "r"))) {
+ return -1;
+ }
+ cnt = fread(buf, 1, buf_size - 1, cmd_in);
+ if (cnt == (buf_size - 1) || feof(cmd_in)) {
+ /* buffer full or got the whole output. null terminate */
+ buf[cnt] = 0;
+ ret = cnt;
+ }
+ if (pclose(cmd_in) == -1) {
+ ret = -1;
+ }
+ return ret;
+}
+
void dt(vtw_sorted *srtp)
{
int i;
@@ -729,7 +802,7 @@ int char2val(vtw_def *def, char *value, valstruct *valp)
//currently fails to handle mixed text + non-text case...
char buf1[2048];
if (char2val_notext(def,my_type,my_type2,value,&valp,buf1) != 0) {
- fprintf(out_stream,"%s",buf1);
+ OUTPUT_USER("%s", buf1);
return -1; //only single definition
}
return 0;
@@ -1106,43 +1179,50 @@ static int change_var_value(const char* var_reference,const char* value, int act
int ret=-1;
if(var_reference && value) {
-
- char* var_path=NULL;
+ if (var_ref_handle) {
+ /* XXX current var ref lib implementation is fs-specific.
+ * for now treat it as a part of the unionfs-specific
+ * cstore implementation.
+ * handle is set => we are in cstore operation.
+ */
+ if (cstore_set_var_ref(var_ref_handle, var_reference, value,
+ active_dir)) {
+ ret = 0;
+ }
+ } else {
+ /* legacy usage */
+ 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;
- 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_tdirp(),
- TRUE)==0) {
- var_path=cv.value;
-
+ 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_tdirp(),
+ TRUE,
+ active_dir)==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);
}
-
- }
-
- 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);
}
}
@@ -1177,7 +1257,7 @@ static boolean check_syn_func(vtw_node *cur,const char **outbuf,const char* func
if (ret <= 0){
if (expand_string(cur->vtw_node_right->vtw_node_string) == VTWERR_OK) {
if (outbuf == NULL) {
- fprintf(out_stream, "%s\n", exe_string);
+ OUTPUT_USER("%s\n", exe_string);
}
else {
strcat((char*)*outbuf, exe_string);
@@ -1362,9 +1442,6 @@ static int eval_va(valstruct *res, vtw_node *node)
{
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;
DPRINT("eval_va var[%s]\n", pathp);
@@ -1388,36 +1465,63 @@ static int eval_va(valstruct *res, vtw_node *node)
*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,
- TRUE,
- &cv,
- get_tdirp(),
- FALSE);
-
- if(status==0) {
- if(cv.value) {
- res->val_type = cv.val_type;
- res->val_types = NULL;
- res->free_me = TRUE;
- res->val = cv.value;
- }
- }
- }
+ if (var_ref_handle) {
+ /* XXX current var ref lib implementation is fs-specific.
+ * for now treat it as a part of the unionfs-specific
+ * cstore implementation.
+ * handle is set => we are in cstore operation.
+ */
+ clind_val cv;
+ if (!cstore_get_var_ref(var_ref_handle, pathp, &cv,
+ is_in_delete_action())) {
+ status = -1;
+ } else {
+ /* success */
+ status = 0;
+ if(cv.value) {
+ res->val_type = cv.val_type;
+ res->val_types = NULL;
+ res->free_me = TRUE;
+ res->val = cv.value;
+ }
+ }
+ } else {
+ /* legacy usage */
+ 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(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,
+ TRUE,
+ &cv,
+ get_tdirp(),
+ FALSE,
+ is_in_delete_action());
+
+ if(status==0) {
+ if(cv.value) {
+ res->val_type = cv.val_type;
+ res->val_types = NULL;
+ 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);
+ 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 = ')';
@@ -1525,11 +1629,6 @@ static int expand_string(char *stringp)
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, ')');
@@ -1543,33 +1642,49 @@ static int expand_string(char *stringp)
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) {
+ if (var_ref_handle) {
+ /* XXX current var ref lib implementation is fs-specific.
+ * for now treat it as a part of the unionfs-specific
+ * cstore implementation.
+ * handle is set => we are in cstore operation.
+ */
+ clind_val cv;
+ if (cstore_get_var_ref(var_ref_handle, scanp, &cv,
+ is_in_delete_action())) {
+ cp=cv.value;
+ }
+ } else {
+ /* legacy usage */
+ 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(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,
+ TRUE,
+ &cv,
+ get_tdirp(),
+ FALSE,
+ is_in_delete_action())==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);
+ }
- clind_val cv;
-
- memset(&cv,0,sizeof(cv));
-
- if(clind_config_engine_apply_command_path(n_cfg_path,
- n_tmpl_path,
- n_cmd_path,
- TRUE,
- &cv,
- 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 {
@@ -2047,13 +2162,12 @@ boolean validate_value(vtw_def *def, char *cp)
int i = 0;
for (i = 0; i < strlen(cp); i++) {
if (cp[i] == '\'') {
- fprintf(out_stream, "Cannot use the \"'\" (single quote) character "
- "in a value string\n");
+ OUTPUT_USER("Cannot use the \"'\" (single quote) character "
+ "in a value string\n");
return FALSE;
}
if (cp[i] == '\n') {
- fprintf(out_stream, "Cannot use the newline character "
- "in a value string\n");
+ OUTPUT_USER("Cannot use the newline character in a value string\n");
return FALSE;
}
}
@@ -2062,17 +2176,18 @@ boolean validate_value(vtw_def *def, char *cp)
/* prepare cur_value */
set_at_string(cp);
status = char2val(def, cp, &validate_value_val);
- if (status != VTWERR_OK)
+ if (status != VTWERR_OK) {
return FALSE;
+ }
if ((def->def_type!=ERROR_TYPE) &&
((validate_value_val.val_type != def->def_type) &&
(validate_value_val.val_type != def->def_type2))) {
if (def->def_type_help){
(void)expand_string(def->def_type_help);
- fprintf(out_stream, "%s\n", exe_string);
+ OUTPUT_USER("%s\n", exe_string);
} else {
- fprintf(out_stream, "\"%s\" is not a valid value of type \"%s\"\n",
- cp, type_to_name(def->def_type));
+ OUTPUT_USER("\"%s\" is not a valid value of type \"%s\"\n", cp,
+ type_to_name(def->def_type));
}
ret = FALSE;
goto validate_value_free_and_return;
@@ -2241,7 +2356,7 @@ const char *type_to_name(vtw_type_e type) {
case IPV6NET_TYPE: return("ipv6net");
case MACADDR_TYPE: return("macaddr");
case DOMAIN_TYPE: return("domain");
- case TEXT_TYPE: return("text");
+ case TEXT_TYPE: return("txt");
case BOOL_TYPE: return("bool");
default: return("unknown");
}
@@ -2396,18 +2511,20 @@ restore_output()
/* system_out:
* call system() with output re-enabled.
* output is again redirected before returning from here.
+ * note: this function may be used outside of actual CLI operations, so output
+ * may not have been redirected. check out_stream for such cases.
*/
int
old_system_out(const char *command)
{
int ret = -1;
- if (restore_output() == -1) {
+ if (out_stream && restore_output() == -1) {
return -1;
}
ret = system(command);
- if (redirect_output() == -1) {
+ if (out_stream && redirect_output() == -1) {
return -1;
}