diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2011-01-05 15:18:59 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2011-01-05 15:18:59 +0300 |
commit | f28cb1b0a926f1ea98700b7871537ad1793511fd (patch) | |
tree | baf35570bc6b38b6fab5b6524e8f19f58f71e57f /accel-pppd/cli/cli.c | |
parent | 2fdf3586c13a72c36f9530084962e29d57dc0329 (diff) | |
download | accel-ppp-f28cb1b0a926f1ea98700b7871537ad1793511fd.tar.gz accel-ppp-f28cb1b0a926f1ea98700b7871537ad1793511fd.zip |
rename accel-pptp to accel-ppp
Diffstat (limited to 'accel-pppd/cli/cli.c')
-rw-r--r-- | accel-pppd/cli/cli.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/accel-pppd/cli/cli.c b/accel-pppd/cli/cli.c new file mode 100644 index 0000000..5009a74 --- /dev/null +++ b/accel-pppd/cli/cli.c @@ -0,0 +1,227 @@ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> + +#include "triton.h" + +#include "cli.h" +#include "cli_p.h" +#include "log.h" +#include "events.h" + +#include "memdebug.h" + +#define MAX_CMD_ITEMS 100 +#define MSG_SYNTAX_ERROR "syntax error\r\n" +#define MSG_INVAL_ERROR "invalid argument\r\n" +#define MSG_UNKNOWN_CMD "command unknown\r\n" + +char *conf_cli_passwd; +static const char *def_cli_prompt = "accel-ppp"; +char *conf_cli_prompt; + +static LIST_HEAD(simple_cmd_list); +static LIST_HEAD(regexp_cmd_list); + +void __export cli_register_simple_cmd(struct cli_simple_cmd_t *cmd) +{ + list_add_tail(&cmd->entry, &simple_cmd_list); +} + +void __export cli_register_simple_cmd2( + int (*exec)(const char *cmd, char * const *fields, int fields_cnt, void *client), + void (*help)(char * const *fields, int fields_cnt, void *client), + int hdr_len, + ... + ) +{ + struct cli_simple_cmd_t *c; + int i; + va_list ap; + + va_start(ap, hdr_len); + + c = malloc(sizeof(*c)); + memset(c, 0, sizeof(*c)); + + c->exec = exec; + c->help = help; + c->hdr_len = hdr_len; + c->hdr = malloc(hdr_len * sizeof(void*)); + + for (i = 0; i < hdr_len; i++) + c->hdr[i] = va_arg(ap, char *); + + list_add_tail(&c->entry, &simple_cmd_list); +} + +void __export cli_register_regexp_cmd(struct cli_regexp_cmd_t *cmd) +{ + int err; + cmd->re = pcre_compile2(cmd->pattern, cmd->options, &err, NULL, NULL, NULL); + if (!cmd->re) { + log_emerg("cli: failed to compile regexp %s: %i\n", cmd->pattern, err); + _exit(EXIT_FAILURE); + } + list_add_tail(&cmd->entry, &simple_cmd_list); +} + +int __export cli_send(void *client, const char *data) +{ + struct cli_client_t *cln = (struct cli_client_t *)client; + + return cln->send(cln, data, strlen(data)); +} + +int __export cli_sendv(void *client, const char *fmt, ...) +{ + struct cli_client_t *cln = (struct cli_client_t *)client; + int r; + + va_list ap; + va_start(ap, fmt); + r = cln->sendv(cln, fmt, ap); + va_end(ap); + + return r; +} + + +static char *skip_word(char *ptr) +{ + for(; *ptr; ptr++) + if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') + break; + return ptr; +} +static char *skip_space(char *ptr) +{ + for(; *ptr; ptr++) + if (*ptr != ' ' && *ptr != '\t') + break; + return ptr; +} +static int split(char *buf, char **ptr) +{ + int i; + + ptr[0] = buf; + + for (i = 1; i <= MAX_CMD_ITEMS; i++) { + buf = skip_word(buf); + if (!*buf) + return i; + + *buf = 0; + + buf = skip_space(buf + 1); + if (!*buf) + return i; + + ptr[i] = buf; + } + + buf = skip_word(buf); + *buf = 0; + + return i; +} + +int cli_process_cmd(struct cli_client_t *cln) +{ + struct cli_simple_cmd_t *cmd1; + struct cli_regexp_cmd_t *cmd2; + char *f[MAX_CMD_ITEMS]; + int r, i, n, found = 0; + + n = split((char *)cln->cmdline, f); + + if (n >= 1 && !strcmp(f[0], "help")) { + list_for_each_entry(cmd1, &simple_cmd_list, entry) + if (cmd1->help) + cmd1->help(f, n, cln); + + list_for_each_entry(cmd2, ®exp_cmd_list, entry) + if (cmd2->help) + cmd1->help(f, n, cln); + + return 0; + } + + list_for_each_entry(cmd1, &simple_cmd_list, entry) { + if (cmd1->hdr_len && n >= cmd1->hdr_len) { + for (i = 0; i < cmd1->hdr_len; i++) { + if (strcmp(cmd1->hdr[i], f[i])) + break; + } + if (i < cmd1->hdr_len) + continue; + r = cmd1->exec((char *)cln->cmdline, f, n, cln); + switch (r) { + case CLI_CMD_EXIT: + cln->disconnect(cln); + case CLI_CMD_FAILED: + return -1; + case CLI_CMD_SYNTAX: + cli_send(cln, MSG_SYNTAX_ERROR); + return 0; + case CLI_CMD_INVAL: + cli_send(cln, MSG_INVAL_ERROR); + return 0; + case CLI_CMD_OK: + found = 1; + } + } + } + + list_for_each_entry(cmd2, ®exp_cmd_list, entry) { + r = cmd2->exec((char *)cln->cmdline, cln); + switch (r) { + case CLI_CMD_EXIT: + cln->disconnect(cln); + case CLI_CMD_FAILED: + return 0; + case CLI_CMD_SYNTAX: + cli_send(cln, MSG_SYNTAX_ERROR); + return 0; + case CLI_CMD_OK: + found = 1; + } + } + + if (!found) { + if (cli_send(cln, MSG_UNKNOWN_CMD)) + return -1; + } + + return 0; +} + +static void load_config(void) +{ + const char *opt; + + if (conf_cli_passwd) + _free(conf_cli_passwd); + opt = conf_get_opt("cli", "password"); + if (opt) + conf_cli_passwd = _strdup(opt); + else + conf_cli_passwd = NULL; + + if (conf_cli_prompt && conf_cli_prompt != def_cli_prompt) + _free(conf_cli_prompt); + opt = conf_get_opt("cli", "prompt"); + if (opt) + conf_cli_prompt = _strdup(opt); + else + conf_cli_prompt = (char *)def_cli_prompt; +} + +static void __init init(void) +{ + load_config(); + + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); +} |