summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2007-11-14 16:25:50 -0800
committerAn-Cheng Huang <ancheng@vyatta.com>2007-11-14 16:25:50 -0800
commit18d767fb17ec197d3ed24ec27a5364ee84b612ca (patch)
tree73f664a55c8a42afd3b72bb33ff5b389ad63905f
parentbff0c156047ae6ca0bb9a5e04587ebe1d1ef5249 (diff)
downloadvyatta-bash-18d767fb17ec197d3ed24ec27a5364ee84b612ca.tar.gz
vyatta-bash-18d767fb17ec197d3ed24ec27a5364ee84b612ca.zip
* add restricted modes ("output" and "full").
* support "root-level" programmable completion in restricted modes.
-rw-r--r--bashline.c12
-rw-r--r--eval.c95
-rw-r--r--general.c22
-rw-r--r--general.h3
-rw-r--r--pcomplete.c23
5 files changed, 144 insertions, 11 deletions
diff --git a/bashline.c b/bashline.c
index 776bdf4..c0f67c9 100644
--- a/bashline.c
+++ b/bashline.c
@@ -1067,7 +1067,8 @@ attempt_shell_completion (text, start, end)
#if defined (PROGRAMMABLE_COMPLETION)
/* Attempt programmable completion. */
- if (!matches && in_command_position == 0 && prog_completion_enabled &&
+ if (!matches && prog_completion_enabled &&
+ (in_vyatta_restricted_mode(OUTPUT) || in_command_position == 0) &&
(progcomp_size () > 0) && current_prompt_string == ps1_prompt)
{
int s, e, foundcs;
@@ -1081,7 +1082,9 @@ attempt_shell_completion (text, start, end)
s = find_cmd_start (start);
e = find_cmd_end (end);
n = find_cmd_name (s);
- if (e > s && assignment (n, 0) == 0)
+ if ((e > s || (in_vyatta_restricted_mode(OUTPUT) &&
+ strcmp(n, text) == 0)) &&
+ assignment (n, 0) == 0)
prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
else
foundcs = 0;
@@ -1126,6 +1129,11 @@ bash_default_completion (text, start, end, qc, in_command_position)
matches = (char **)NULL;
+ if (in_vyatta_restricted_mode(OUTPUT)) {
+ rl_ignore_some_completions_function = bash_ignore_everything;
+ return matches;
+ }
+
/* New posix-style command substitution or variable name? */
if (!matches && *text == '$')
{
diff --git a/eval.c b/eval.c
index 34a088c..72e5a45 100644
--- a/eval.c
+++ b/eval.c
@@ -29,6 +29,7 @@
#include "bashansi.h"
#include <stdio.h>
+#include <dirent.h>
#include "bashintl.h"
@@ -57,6 +58,11 @@ extern int expand_aliases;
static void send_pwd_to_eterm __P((void));
static sighandler alrm_catcher __P((int));
+#if defined (READLINE)
+extern char *current_readline_line;
+extern int current_readline_line_index;
+#endif
+
/* Read and execute commands until EOF is reached. This assumes that
the input source has already been initialized. */
int
@@ -192,6 +198,83 @@ send_pwd_to_eterm ()
fprintf (stderr, "\032/%s\n", pwd);
}
+static int
+is_in_command_list(const char *cmd, const char *cmds[])
+{
+ int idx = 0;
+ for (idx = 0; cmds[idx]; idx++) {
+ if (strcmp(cmd, cmds[idx]) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+is_vyatta_cfg_command(const char *cmd)
+{
+ char *valid_commands[] = { "set", "delete", "commit", "save", "load",
+ "show", "exit", "edit", "run", NULL };
+ return is_in_command_list(cmd, valid_commands);
+}
+
+static int
+is_vyatta_op_command(const char *cmd)
+{
+ char *dir = getenv("vyatta_op_templates");
+ DIR *dp = NULL;
+ struct dirent *dent = NULL;
+ char *other_commands[] = { "exit", NULL };
+ int ret = 0;
+
+ if (dir == NULL || (dp = opendir(dir)) == NULL) {
+ return 0;
+ }
+ while (dent = readdir(dp)) {
+ if (strncmp(dent->d_name, ".", 1) == 0) {
+ continue;
+ }
+ if (strcmp(dent->d_name, cmd) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ closedir(dp);
+ return (ret) ? 1 : is_in_command_list(cmd, other_commands);
+}
+
+static int
+is_vyatta_command(char *cmdline)
+{
+ char *cfg = getenv("_OFR_CONFIGURE");
+ int in_cfg = (cfg) ? (strcmp(cfg, "ok") == 0) : 0;
+ char *start = cmdline;
+ char *end = NULL;
+ char save = 0;
+ int ret = 0;
+ while (*start && (whitespace(*start) || *start == '\n')) {
+ start++;
+ }
+ if (*start == 0) {
+ /* empty command line */
+ return 1;
+ }
+ end = start;
+ while (*end && (!whitespace(*end) && *end != '\n')) {
+ end++;
+ }
+ save = *end;
+ *end = 0;
+
+ if (in_cfg) {
+ ret = is_vyatta_cfg_command(start);
+ } else {
+ ret = is_vyatta_op_command(start);
+ }
+ *end = save;
+ return ret;
+}
+
/* Call the YACC-generated parser and return the status of the parse.
Input is read from the current input stream (bash_input). yyparse
leaves the parsed command in the global variable GLOBAL_COMMAND.
@@ -221,6 +304,18 @@ parse_command ()
current_command_line_count = 0;
r = yyparse ();
+#if defined (READLINE)
+ if (in_vyatta_restricted_mode(FULL) && current_readline_line) {
+ if (!is_vyatta_command(current_readline_line)) {
+ printf("Invalid command\n");
+ current_readline_line_index = 0;
+ current_readline_line[0] = '\n';
+ current_readline_line[1] = '\0';
+ return 1;
+ }
+ }
+#endif
+
if (need_here_doc)
gather_here_documents ();
diff --git a/general.c b/general.c
index 3384e84..500f7b9 100644
--- a/general.c
+++ b/general.c
@@ -1023,3 +1023,25 @@ get_group_array (ngp)
*ngp = ngroups;
return group_iarray;
}
+
+int
+in_vyatta_restricted_mode(enum vyatta_restricted_type type)
+{
+ char *rval = getenv("VYATTA_RESTRICTED_MODE");
+ int output = 0, full = 0;
+ if (rval == NULL) {
+ return 0;
+ }
+ output = (strcmp(rval, "output") == 0);
+ full = (strcmp(rval, "full") == 0);
+
+ if (type == OUTPUT && (output || full)) {
+ return 1;
+ }
+ if (type == FULL && full) {
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/general.h b/general.h
index e1d01f5..52b2ed1 100644
--- a/general.h
+++ b/general.h
@@ -317,4 +317,7 @@ extern int group_member __P((gid_t));
extern char **get_group_list __P((int *));
extern int *get_group_array __P((int *));
+enum vyatta_restricted_type { OUTPUT, FULL };
+extern int in_vyatta_restricted_mode __P((enum vyatta_restricted_type));
+
#endif /* _GENERAL_H_ */
diff --git a/pcomplete.c b/pcomplete.c
index ee462dc..74dad05 100644
--- a/pcomplete.c
+++ b/pcomplete.c
@@ -1353,15 +1353,20 @@ programmable_completions (cmd, word, start, end, foundp)
STRINGLIST *ret;
char **rmatches, *t;
- /* We look at the basename of CMD if the full command does not have
- an associated COMPSPEC. */
- cs = progcomp_search (cmd);
- if (cs == 0)
- {
- t = strrchr (cmd, '/');
- if (t)
- cs = progcomp_search (++t);
- }
+ if (in_vyatta_restricted_mode(OUTPUT) && strcmp(cmd, word) == 0) {
+ /* command completion */
+ cs = progcomp_search("");
+ } else {
+ /* We look at the basename of CMD if the full command does not have
+ an associated COMPSPEC. */
+ cs = progcomp_search (cmd);
+ if (cs == 0)
+ {
+ t = strrchr (cmd, '/');
+ if (t)
+ cs = progcomp_search (++t);
+ }
+ }
if (cs == 0)
{
if (foundp)