X-Git-Url: http://git.droids-corp.org/?p=libcmdline.git;a=blobdiff_plain;f=src%2Flib%2Fcmdline.c;h=70267de19b1af9537a2c2f8714855a0251e4d86d;hp=e6662bd339105c2d72cd142a446fa3a21832027e;hb=568d6d51fc9e6e2d8842fc1abe63c23de503f8bc;hpb=2e949478bc20b52358b9093a8d3ae88d186fb8fc diff --git a/src/lib/cmdline.c b/src/lib/cmdline.c index e6662bd..70267de 100644 --- a/src/lib/cmdline.c +++ b/src/lib/cmdline.c @@ -74,62 +74,79 @@ #include "cmdline.h" static void -cmdline_valid_buffer(struct rdline *rdl, const char *buf, - __attribute__((unused)) unsigned int size) +cmdline_default_valid_buffer(struct rdline *rdl, const char *buf, + __attribute__((unused)) unsigned int size) { struct cmdline *cl = rdl->opaque; int ret; - ret = cmdline_parse(cl, buf); + ret = cmdline_parse(cl->ctx, buf, cl); if (ret == CMDLINE_PARSE_AMBIGUOUS) cmdline_printf(cl, "Ambiguous command\n"); else if (ret == CMDLINE_PARSE_NOMATCH) - cmdline_printf(cl, "Command not found\n"); - else if (ret == CMDLINE_PARSE_BAD_ARGS) cmdline_printf(cl, "Bad arguments\n"); + else if (ret == CMDLINE_PARSE_UNTERMINATED_QUOTE) + cmdline_printf(cl, "Unterminated quote\n"); } static int -cmdline_complete_buffer(struct rdline *rdl, const char *buf, - char *dstbuf, unsigned int dstsize, - int *state) +cmdline_default_complete_buffer(struct rdline *rdl, const char *buf, + char *dstbuf, unsigned int dstsize) { struct cmdline *cl = rdl->opaque; - return cmdline_complete(cl, buf, state, dstbuf, dstsize); + // RDLINE_RES_COMPLETE ? + return cmdline_complete(cl->ctx, buf, dstbuf, dstsize); } -int -cmdline_write_char(struct rdline *rdl, char c) + +static int +cmdline_default_help(struct rdline *rdl, const char *buf, + rdline_write_t *write_cb, void *write_arg) { - int ret = -1; struct cmdline *cl = rdl->opaque; + return cmdline_help(cl->ctx, buf, cmdline_write, write_arg); +} - if (cl->s_out >= 0) - ret = write(cl->s_out, &c, 1); +/* ---- Some rdline wrappers ---- */ - return ret; +/* write a buffer, just use rdline */ +ssize_t +cmdline_write(void *arg, void *buf, size_t count) +{ + struct rdline *rdl = arg; +#ifdef NO_PAGER + return rdline_write(rdl, buf, count); +#else + return rdline_asyncpager_write(rdl, buf, count); +#endif } - void cmdline_set_prompt(struct cmdline *cl, const char *prompt) { - snprintf(cl->prompt, sizeof(cl->prompt), prompt); + snprintf(cl->prompt, sizeof(cl->prompt), "%s", prompt); } struct cmdline * cmdline_new(cmdline_parse_ctx_t *ctx, const char *prompt, int s_in, int s_out) { struct cmdline *cl; + cl = malloc(sizeof(struct cmdline)); if (cl == NULL) return NULL; + + /* init cmdline structure */ memset(cl, 0, sizeof(struct cmdline)); cl->s_in = s_in; cl->s_out = s_out; cl->ctx = ctx; - rdline_init(&cl->rdl, cmdline_write_char, - cmdline_valid_buffer, cmdline_complete_buffer); + /* init embedded rdline */ + rdline_init(&cl->rdl, s_in, s_out, + cmdline_default_valid_buffer, + cmdline_default_complete_buffer, + cmdline_default_help); + cl->rdl.opaque = cl; cmdline_set_prompt(cl, prompt); rdline_newline(&cl->rdl, cl->prompt); @@ -148,62 +165,41 @@ cmdline_free(struct cmdline *cl) free(cl); } -void +int cmdline_printf(const struct cmdline *cl, const char *fmt, ...) { va_list ap; - -#ifdef _GNU_SOURCE - if (cl->s_out < 0) - return; - va_start(ap, fmt); - vdprintf(cl->s_out, fmt, ap); - va_end(ap); -#else int ret; - char *buf; - - if (cl->s_out < 0) - return; - buf = malloc(BUFSIZ); - if (buf == NULL) - return; va_start(ap, fmt); - ret = vsnprintf(buf, BUFSIZ, fmt, ap); + ret = rdline_vprintf(&cl->rdl, fmt, ap); va_end(ap); - if (ret < 0) - return; - if (ret >= BUFSIZ) - ret = BUFSIZ - 1; - write(cl->s_out, buf, ret); - free(buf); -#endif + + return ret; } +/* Push an input buffer in the command line. Typically, this function + * is called by cmdline_interact() to send the input characters to the + * cmdline process. It can also be called by a user callback function, + * when a buffer is received from the input socket. + * + * The function returns the number of processed characters, or a + * negative value on error (EOF reached or command line exited. */ int cmdline_in(struct cmdline *cl, const char *buf, int size) { - const char *history, *buffer; int ret = 0; - int i, same; + int i; - for (i=0; irdl, buf[i]); - if (ret == RDLINE_RES_VALIDATED) { - buffer = rdline_get_buffer(&cl->rdl); - history = rdline_get_history_item(&cl->rdl, 0); - if (history) { - same = !memcmp(buffer, history, strlen(history)) && - buffer[strlen(history)] == '\n'; - } - else - same = 0; - if (strlen(buffer) > 1 && !same) - rdline_add_history(&cl->rdl, buffer); + if (ret == RDLINE_RES_VALIDATED && + cl->rdl.status == RDLINE_STOPPED) + break; + + if (ret == RDLINE_RES_VALIDATED) rdline_newline(&cl->rdl, cl->prompt); - } else if (ret == RDLINE_RES_EOF) return -1; else if (ret == RDLINE_RES_EXITED) @@ -212,12 +208,16 @@ cmdline_in(struct cmdline *cl, const char *buf, int size) return i; } +/* Interrupt a running command line process */ void cmdline_quit(struct cmdline *cl) { rdline_quit(&cl->rdl); } +/* Start command line on configured file descriptor. This function + * loops until the user explicitelly call cmdline_quit(), or if the + * input fd reaches EOF. */ void cmdline_interact(struct cmdline *cl) { @@ -230,5 +230,4 @@ cmdline_interact(struct cmdline *cl) if (cmdline_in(cl, &c, 1) < 0) break; } - cmdline_free(cl); }