diff -r 7728d6ec3abf -r 5229a5d098b2 src/console.c --- a/src/console.c Wed May 27 23:57:48 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +0,0 @@ -#include "console.h" -#include "log.h" - -#include -#include -#include -#include -#include - -#include -#include - -struct console { - /** Configuration */ - struct console_config config; - - /** Input event */ - struct event *ev; - - /** Callback functions */ - const struct console_callbacks *callbacks; - - /** Callback context argument */ - void *cb_arg; - - /** Old SIGINT handler */ - struct sigaction old_sigint; - - /** Already initialized? */ - bool initialized; - - /** Set as log output function? */ - bool log_output; - - /** Prompt displayed? */ - bool have_prompt; - - /** Waiting for line to be processed */ - bool waiting; -}; - -/** The global console state */ -static struct console _console; - -/** - * Our stdin input handler - */ -static void console_input (int fd, short what, void *arg) -{ - struct console *console = arg; - - (void) fd; - (void) what; - - if (console->waiting) - // can't feed readline input while it's disabled - return log_warn("discrding input while waiting"); - - else - // tell readline to process it - rl_callback_read_char(); -} - -/** - * Our readline line handler - */ -static void console_line (char *line) -{ - struct console *console = &_console; - enum console_line_status status = CONSOLE_CONTINUE; - - // special-case EOF - if (!line) { - // prettify - rl_crlf(); - rl_on_new_line(); - - if (console->callbacks->on_eof) - console->callbacks->on_eof(console->cb_arg); - - return; - } - - // update state for console_print during processing - console->have_prompt = false; - - // invoke the console callback - if (console->callbacks && console->callbacks->on_line) - status = console->callbacks->on_line(line, console->cb_arg); - - // add to history mechanism - add_history(line); - - // release the line - free(line); - - switch (status) { - case CONSOLE_CONTINUE: - // the prompt will be displayed again - console->have_prompt = true; - - break; - - case CONSOLE_WAIT: - // deactivate our read event - if (event_del(console->ev)) - log_warn("unable to deactivate console read event"); - - // remove the readline stuff to stop it from displaying the prompt - rl_callback_handler_remove(); - - // ignore input - console->waiting = true; - - break; - } -} -static void on_sigint (int sig) -{ - struct console *console = &_console; - - (void) sig; - - if (console->waiting) { - // notify user - if (console->callbacks->on_interrupt) - console->callbacks->on_interrupt(console->cb_arg); - - } else { - // interrupt the input line - // XXX: is this the right function to call? - rl_free_line_state(); - - // redisplay on new line - rl_crlf(); - rl_callback_handler_install(console->config.prompt, console_line); - } -} - -err_t console_init (struct console **console_ptr, struct event_base *ev_base, const struct console_config *config, - const struct console_callbacks *callbacks, void *cb_arg, error_t *err) -{ - struct console *console = &_console; - - // check it's not already initialized - assert(!console->initialized); - - // store - console->config = *config; - - // store callbacks? - if (callbacks) - console_set_callbacks(console, callbacks, cb_arg); - - // setup the input event - if ((console->ev = event_new(ev_base, STDIN_FILENO, EV_READ | EV_PERSIST, &console_input, console)) == NULL) - JUMP_SET_ERROR(err, ERR_EVENT_NEW); - - // set our SIGINT handler - struct sigaction sigact; - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = on_sigint; - sigaction(SIGINT, &sigact, &console->old_sigint); - - // setup state for initial readline prompt - console->have_prompt = true; - - // setup readline - rl_callback_handler_install(config->prompt, console_line); - - // mark it as initialized - console->initialized = true; - - // enable input - if (event_add(console->ev, NULL)) - JUMP_SET_ERROR(err, ERR_EVENT_ADD); - - // ok - *console_ptr = console; - - return SUCCESS; - -error: - console_destroy(console); - - return ERROR_CODE(err); -} - -void console_set_callbacks (struct console *console, const struct console_callbacks *callbacks, void *cb_arg) -{ - console->callbacks = callbacks; - console->cb_arg = cb_arg; -} - -void console_continue (struct console *console) -{ - if (!console->waiting) - return; - - // re-enable input - console->waiting = false; - - if (event_add(console->ev, NULL)) - log_fatal("unable to re-enable console read event"); - - // the prompt will be displayed again - console->have_prompt = true; - - // re-setup readline with prompt - rl_callback_handler_install(console->config.prompt, console_line); -} - -err_t console_print (struct console *console, const char *line) -{ - if (console->have_prompt) - // don't interrupt current input line - rl_crlf(); - - // output the line - if (printf("%s\n", line) < 0) - return _ERR_GENERAL; - - if (console->have_prompt) { - // restore input - rl_on_new_line(); - rl_redisplay(); - } - - // ok - return SUCCESS; -} - -/** - * Our log_output_func implementation - */ -static void console_log_output_func (const char *line, void *_console) -{ - struct console *console = _console; - - console_print(console, line); -} - -void console_set_log_output (struct console *console) -{ - // replace old one - log_set_func(console_log_output_func, console); - - // mark - console->log_output = true; -} - -void console_destroy (struct console *console) -{ - if (console->log_output) - // unset ourselves as the log handler - log_set_func(NULL, NULL); - - // remove the input event - if (console->ev) - event_free(console->ev); - - console->ev = NULL; - - // de-init rl? - if (console->initialized) - rl_callback_handler_remove(); - - console->initialized = false; - - // restore signal handler - sigaction(SIGINT, &console->old_sigint, NULL); - - // remove stored stuff - console->callbacks = console->cb_arg = NULL; -} -