diff options
Diffstat (limited to 'usr/src/cmd/mdb/common/mdb/mdb_termio.c')
-rw-r--r-- | usr/src/cmd/mdb/common/mdb/mdb_termio.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_termio.c b/usr/src/cmd/mdb/common/mdb/mdb_termio.c index d2f3d59f83..1f2992ba65 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_termio.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_termio.c @@ -22,6 +22,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012 Joyent, Inc. All rights reserved. */ /* @@ -76,6 +78,7 @@ #include <mdb/mdb_string.h> #include <mdb/mdb_modapi.h> #include <mdb/mdb_frame.h> +#include <mdb/mdb_tab.h> #include <mdb/mdb.h> #ifdef ERR @@ -174,6 +177,7 @@ typedef void (*putp_t)(struct termio_data *, const char *, uint_t); #define TIO_TTYWARN 0x20 /* Warnings about tty issued */ #define TIO_CAPWARN 0x40 /* Warnings about terminfo issued */ #define TIO_XTERM 0x80 /* Terminal is xterm compatible */ +#define TIO_TAB 0x100 /* Tab completion mode */ static const mdb_bitmask_t tio_flag_masks[] = { { "FINDHIST", TIO_FINDHIST, TIO_FINDHIST }, @@ -184,6 +188,7 @@ static const mdb_bitmask_t tio_flag_masks[] = { { "TTYWARN", TIO_TTYWARN, TIO_TTYWARN }, { "CAPWARN", TIO_CAPWARN, TIO_CAPWARN }, { "XTERM", TIO_XTERM, TIO_XTERM }, + { "TAB", TIO_TAB, TIO_TAB}, { NULL, 0, 0 } }; @@ -256,6 +261,7 @@ static void termio_clear(termio_data_t *); static void termio_redraw(termio_data_t *); static void termio_prompt(termio_data_t *); +static const char *termio_tab(termio_data_t *, int); static const char *termio_insert(termio_data_t *, int); static const char *termio_accept(termio_data_t *, int); static const char *termio_backspace(termio_data_t *, int); @@ -398,7 +404,10 @@ termio_read(mdb_io_t *io, void *buf, size_t nbytes) goto out; } - termio_prompt(td); + if (td->tio_flags & TIO_TAB) + termio_redraw(td); + else + termio_prompt(td); /* * We need to redraw the entire command-line and restart our read loop @@ -428,6 +437,13 @@ termio_read(mdb_io_t *io, void *buf, size_t nbytes) td->tio_active = TRUE; + /* + * We may have had some error while in tab completion mode which sent us + * longjmping all over the place. If that's the case, come back here and + * make sure the flag is off. + */ + td->tio_flags &= ~TIO_TAB; + do { char_loop: if ((c = mdb_iob_getc(td->tio_in)) == EOF) { @@ -1488,6 +1504,11 @@ mdb_termio_create(const char *name, mdb_io_t *rio, mdb_io_t *wio) td->tio_keymap['['] = termio_accel; td->tio_keymap[']'] = termio_accel; + /* + * Grab tabs + */ + td->tio_keymap['\t'] = termio_tab; + td->tio_x = 0; td->tio_y = 0; td->tio_max_x = 0; @@ -1590,6 +1611,66 @@ termio_backspace(termio_data_t *td, int c) return (NULL); } +/* + * This function may end up calling termio_read recursively as part of invoking + * the mdb pager. To work around this fact, we need to go through and make sure + * that we change the underlying terminal settings before and after this + * function call. If we don't do this, we invoke the pager, and don't abort + * (which will longjmp us elsewhere) we're going to return to the read loop with + * the wrong termio settings. + * + * Furthermore, because of the fact that we're being invoked in a user context + * that allows us to be interrupted, we need to actually allocate the memory + * that we're using with GC so that it gets cleaned up in case of the pager + * resetting us and never reaching the end. + */ +/*ARGSUSED*/ +static const char * +termio_tab(termio_data_t *td, int c) +{ + char *buf; + const char *result; + int nres; + mdb_tab_cookie_t *mtp; + + if (termio_ctl(td->tio_io, TCSETSW, &td->tio_dtios) == -1) + warn("failed to restore terminal attributes"); + + buf = mdb_alloc(td->tio_cmdbuf.cmd_bufidx + 1, UM_SLEEP | UM_GC); + (void) strncpy(buf, td->tio_cmdbuf.cmd_buf, td->tio_cmdbuf.cmd_bufidx); + buf[td->tio_cmdbuf.cmd_bufidx] = '\0'; + buf = strndup(td->tio_cmdbuf.cmd_buf, td->tio_cmdbuf.cmd_bufidx); + td->tio_flags |= TIO_TAB; + mtp = mdb_tab_init(); + nres = mdb_tab_command(mtp, buf); + + if (nres == 0) { + result = NULL; + } else { + result = mdb_tab_match(mtp); + if (nres != 1) + mdb_tab_print(mtp); + } + + if (result != NULL) { + int index = 0; + + while (result[index] != '\0') { + (void) termio_insert(td, result[index]); + index++; + } + } + + termio_redraw(td); + mdb_tab_fini(mtp); + td->tio_flags &= ~TIO_TAB; + if (termio_ctl(td->tio_io, TCSETSW, &td->tio_rtios) == -1) + warn("failed to set terminal attributes"); + + + return (NULL); +} + static const char * termio_delchar(termio_data_t *td, int c) { |