src/console.c
author Tero Marttila <terom@fixme.fi>
Tue, 31 Mar 2009 15:41:24 +0300
changeset 92 99661e5aac91
child 93 42ade8285570
permissions -rw-r--r--
add a simple interactive readline console
#include "console.h"

#include <unistd.h>
#include <stdio.h>
#include <readline/readline.h>
#include <assert.h>

/** 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) console;
    (void) fd;
    (void) what;

    // tell readline to process it
    rl_callback_read_char();
}

/**
 * Our readline line handler
 */
static void console_line (char *line)
{
    struct console *console = &_console;

    // invoke the console callback
    console->callbacks->on_line(line, console->cb_arg);
}

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, struct error_info *err)
{
    struct console *console = &_console;

    // check it's not already initialized
    assert(!console->initialized);

    // store
    console->callbacks = callbacks;
    console->cb_arg = 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);

    // 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_destroy (struct console *console)
{
    // 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;

    // remove stored stuff
    console->callbacks = console->cb_arg = NULL;
}