Index: sys/ddb/db_input.c =================================================================== --- sys/ddb/db_input.c +++ sys/ddb/db_input.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,18 @@ static char * db_lc; /* current character */ static char * db_le; /* one past last character */ +/* + * Raw input buffer, processed only for certain control characters. + */ +#define DB_RAW_SIZE 512 +static char db_raw[DB_RAW_SIZE]; +static int db_raw_pos; +static int db_raw_cnt; +static int ddb_prioritize_control_input = 1; +SYSCTL_INT(_debug, OID_AUTO, ddb_prioritize_control_input, CTLFLAG_RW, + &ddb_prioritize_control_input, 0, + "Drop input when the buffer fills in order to keep servicing ^C/^S/^Q"); + /* * Simple input line history support. */ @@ -65,11 +78,13 @@ #define BLANK ' ' #define BACKUP '\b' -static int cnmaygetc(void); static void db_delete(int n, int bwd); static int db_inputchar(int c); static void db_putnchars(int c, int count); static void db_putstring(char *s, int count); +static int db_raw_pop(void); +static void db_raw_push(int); +static int db_raw_space(void); static void db_putstring(s, count) @@ -307,10 +322,49 @@ return (0); } +/* Get a character from the console, first checking the raw input buffer. */ +int +db_getc(void) +{ + int c; + + if (db_raw_cnt == 0) { + c = cngetc(); + } else { + c = db_raw_pop(); + if (c == '\r') + c = '\n'; + } + return (c); +} + +/* Whether the raw input buffer has space to accept another character. */ static int -cnmaygetc() +db_raw_space(void) +{ + + return (db_raw_cnt < DB_RAW_SIZE); +} + +/* Un-get a character from the console by buffering it. */ +static void +db_raw_push(int c) { - return (-1); + + if (!db_raw_space()) + db_error(NULL); + db_raw[(db_raw_pos + db_raw_cnt++) % DB_RAW_SIZE] = c; +} + +/* Drain a character from the raw input buffer. */ +static int +db_raw_pop(void) +{ + + if (db_raw_cnt == 0) + return (-1); + db_raw_cnt--; + return (db_raw[db_raw_pos++ % DB_RAW_SIZE]); } int @@ -339,7 +393,7 @@ db_lc = lstart; db_le = lstart; - while (!db_inputchar(cngetc())) + while (!db_inputchar(db_getc())) continue; db_capture_write(lstart, db_le - db_lbuf_start); @@ -361,30 +415,50 @@ return (db_le - db_lbuf_start); } +static void +db_do_interrupt(const char *reason) +{ + + db_disable_pager(); + db_pager_quit = 1; + db_error(reason); +} + void db_check_interrupt(void) { int c; - c = cnmaygetc(); - switch (c) { - case -1: /* no character */ - return; - - case CTRL('c'): - db_error((char *)0); - /*NOTREACHED*/ - - case CTRL('s'): - do { - c = cnmaygetc(); - if (c == CTRL('c')) - db_error((char *)0); - } while (c != CTRL('q')); - break; + /* + * Check console input for control characters. Non-control characters + * are buffered. When buffer space is exhausted, further non-control + * input is dropped on the floor in order to continue responding to + * control input. + */ + for (;;) { + if (!ddb_prioritize_control_input && !db_raw_space()) + return; + c = cncheckc(); + switch (c) { + case -1: /* no character */ + return; + + case CTRL('c'): + db_do_interrupt("^C"); + /*NOTREACHED*/ + + case CTRL('s'): + do { + c = cncheckc(); + if (c == CTRL('c')) + db_do_interrupt("^C"); + } while (c != CTRL('q')); + break; - default: - /* drop on floor */ - break; + default: + if (db_raw_space()) + db_raw_push(c); + break; + } } } Index: sys/ddb/db_output.c =================================================================== --- sys/ddb/db_output.c +++ sys/ddb/db_output.c @@ -260,7 +260,7 @@ db_printf("--More--\r"); done = 0; while (!done) { - c = cngetc(); + c = db_getc(); switch (c) { case 'e': case 'j': Index: sys/ddb/ddb.h =================================================================== --- sys/ddb/ddb.h +++ sys/ddb/ddb.h @@ -197,6 +197,7 @@ /* instruction disassembler */ void db_error(const char *s); int db_expression(db_expr_t *valuep); +int db_getc(void); int db_get_variable(db_expr_t *valuep); void db_iprintf(const char *,...) __printflike(1, 2); struct proc *db_lookup_proc(db_expr_t addr);