int(*execute)(struct lldpctl_conn_t*, struct writer*,
struct cmd_env*, void *),
void *);
+struct cmd_node* commands_privileged(struct cmd_node *);
void commands_free(struct cmd_node *);
const char *cmdenv_arg(struct cmd_env*);
const char *cmdenv_get(struct cmd_env*, const char*);
int cmdenv_put(struct cmd_env*, const char*, const char*);
int cmdenv_pop(struct cmd_env*, int);
int commands_execute(struct lldpctl_conn_t *, struct writer *,
- struct cmd_node *, int argc, const char **argv);
-char *commands_complete(struct cmd_node *, int argc, const char **argv,
- int all);
+ struct cmd_node *, int, const char **, int);
+char *commands_complete(struct cmd_node *, int, const char **,
+ int, int);
/* helpers */
int cmd_check_no_env(struct cmd_env *, void *);
int cmd_check_env(struct cmd_env *, void *);
const char *token; /**< Token to enter this cnode */
const char *doc; /**< Documentation string */
+ int privileged; /**< Privileged command? */
/**
* Function validating entry in this node. Can be @c NULL.
}
/**
- * Create a new node.
+ * Make a node accessible only to privileged users.
+ *
+ * @param node Node to change privileges
+ * @return the modified node
+ *
+ * The node is modified. It is returned to ease chaining.
+ */
+struct cmd_node*
+commands_privileged(struct cmd_node *node)
+{
+ if (node) node->privileged = 1;
+ return node;
+}
+
+/**
+ * Create a new node acessible by any user.
*
* @param root The node we want to attach this node.
* @param token Token to enter this node. Or @c NULL if no token is needed.
* @param argv Array of arguments.
* @param word Completed word. Or NULL when no completion is required.
* @param all When completing, display possible completions even if only one choice is possible.
+ * @param priv Is the current user privileged?
* @return 0 on success, -1 otherwise.
*/
static int
_commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
struct cmd_node *root, int argc, const char **argv,
- char **word, int all)
+ char **word, int all, int priv)
{
int n, rc = 0, completion = (word != NULL);
int help = 0; /* Are we asking for help? */
log_debug("lldpctl", "argument %02d: `%s`", n, argv[n]);
if (completion) *word = NULL;
+#define CAN_EXECUTE(candidate) \
+ ((!candidate->privileged || priv) && \
+ (!candidate->validate || \
+ candidate->validate(&env, candidate->arg) == 1))
+
/* When completion is in progress, we use the same algorithm than for
* execution until we reach the cursor position. */
struct cmd_node *current = NULL;
env.argp, token);
TAILQ_FOREACH(candidate, ¤t->subentries, next) {
if (candidate->token &&
- !strncmp(candidate->token, token, strlen(token))) {
- if (!candidate->validate ||
- candidate->validate(&env, candidate->arg) == 1) {
- if (candidate->token &&
- !strcmp(candidate->token, token)) {
- /* Exact match */
- best = candidate;
- break;
- }
- if (!best) best = candidate;
- else {
- if (!completion)
- log_warnx("lldpctl", "ambiguous token: %s (%s or %s)",
- token, candidate->token, best->token);
- rc = -1;
- goto end;
- }
+ !strncmp(candidate->token, token, strlen(token)) &&
+ CAN_EXECUTE(candidate)) {
+ if (candidate->token &&
+ !strcmp(candidate->token, token)) {
+ /* Exact match */
+ best = candidate;
+ break;
+ }
+ if (!best) best = candidate;
+ else {
+ if (!completion)
+ log_warnx("lldpctl", "ambiguous token: %s (%s or %s)",
+ token, candidate->token, best->token);
+ rc = -1;
+ goto end;
}
}
}
if (!best) {
/* Take first that validate */
TAILQ_FOREACH(candidate, ¤t->subentries, next) {
- if (!candidate->token && (!candidate->validate ||
- candidate->validate(&env, candidate->arg) == 1)) {
+ if (!candidate->token &&
+ CAN_EXECUTE(candidate)) {
best = candidate;
break;
}
if ((!candidate->token || help ||
!strncmp(env.argv[env.argc - 1], candidate->token,
strlen(env.argv[env.argc -1 ]))) &&
- (!candidate->validate ||
- candidate->validate(&env, candidate->arg) == 1)) {
+ CAN_EXECUTE(candidate)) {
struct candidate_word *cword =
malloc(sizeof(struct candidate_word));
if (!cword) break;
*/
char *
commands_complete(struct cmd_node *root, int argc, const char **argv,
- int all)
+ int all, int privileged)
{
char *word = NULL;
if (_commands_execute(NULL, NULL, root, argc, argv,
- &word, all) == 0)
+ &word, all, privileged) == 0)
return word;
return NULL;
}
*/
int
commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
- struct cmd_node *root, int argc, const char **argv)
+ struct cmd_node *root, int argc, const char **argv, int privileged)
{
- return _commands_execute(conn, w, root, argc, argv, NULL, 0);
+ return _commands_execute(conn, w, root, argc, argv, NULL, 0, privileged);
}
/**
if (tokenize_line(line, &argc, &argv) != 0)
goto end;
- char *compl = commands_complete(root, argc, (const char **)argv, all);
+ char *compl = commands_complete(root, argc, (const char **)argv, all, is_privileged());
if (compl && strlen(argv[argc-1]) < strlen(compl)) {
if (rl_insert_text(compl + strlen(argv[argc-1])) < 0) {
free(compl);
/* Execute command */
int rc = commands_execute(conn, w,
- root, argc, argv);
+ root, argc, argv, is_privileged());
if (rc != 0) {
log_info("lldpctl", "an error occurred while executing last command");
w->finish(w);
root = commands_root();
register_commands_show(root);
register_commands_watch(root);
- if (is_privileged()) {
- commands_new(
- commands_new(root, "update", "Update information and send LLDPU on all ports",
- NULL, NULL, NULL),
- NEWLINE, "Update information and send LLDPU on all ports",
- NULL, cmd_update, NULL);
- register_commands_configure(root);
- }
+ commands_privileged(commands_new(
+ commands_new(root, "update", "Update information and send LLDPU on all ports",
+ NULL, NULL, NULL),
+ NEWLINE, "Update information and send LLDPU on all ports",
+ NULL, cmd_update, NULL));
+ register_commands_configure(root);
commands_new(root, "help", "Get help on a possible command",
NULL, cmd_store_env_and_pop, "help");
commands_new(