mirror of
https://github.com/simh/simh.git
synced 2026-01-25 19:56:25 +00:00
CONSOLE: Cleanup Remote Console command interactions
- Fix potential buffer overrun while pending remote command actions - Add debug abort interface to close debug file - Flush partially read command line on EOF - Flush partially read command line when WRU HALTs execution and switches to multi-command mode. - Disable any pending repeat when WRU HALTs execution
This commit is contained in:
@@ -516,8 +516,8 @@ struct BITSAMPLE_REG {
|
||||
};
|
||||
typedef struct REMOTE REMOTE;
|
||||
struct REMOTE {
|
||||
int32 buf_size;
|
||||
int32 buf_ptr;
|
||||
size_t buf_size;
|
||||
size_t buf_ptr;
|
||||
char *buf;
|
||||
char *act_buf;
|
||||
size_t act_buf_size;
|
||||
@@ -970,7 +970,7 @@ else
|
||||
|
||||
/* Get next pending action, if any */
|
||||
|
||||
static char *sim_rem_getact (int32 line, char *buf, int32 size)
|
||||
static char *sim_rem_getact (int32 line, char *buf, size_t size)
|
||||
{
|
||||
char *ep;
|
||||
size_t lnt;
|
||||
@@ -996,8 +996,14 @@ if ((ep != NULL) && (*ep != ';')) { /* if a quoted string is present
|
||||
|
||||
if (ep != NULL) { /* if a semicolon is present */
|
||||
lnt = ep - rem->act; /* cmd length */
|
||||
memcpy (buf, rem->act, lnt + 1); /* copy with ; */
|
||||
buf[lnt] = 0; /* erase ; */
|
||||
if (lnt >= size) { /* command longer than buffer size? */
|
||||
memcpy (buf, rem->act, size); /* copy some */
|
||||
buf[size - 1] = 0; /* nul terminate cmd */
|
||||
}
|
||||
else {
|
||||
memcpy (buf, rem->act, lnt + 1); /* copy with ; */
|
||||
buf[lnt] = 0; /* erase ; */
|
||||
}
|
||||
rem->act += lnt + 1; /* adv ptr */
|
||||
}
|
||||
else {
|
||||
@@ -1366,7 +1372,7 @@ if (rem->smp_sample_interval && (rem->smp_reg_count != 0)) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Unit service for remote console data polling */
|
||||
/* Unit service for remote console data polling and managing of command execution/dispatch */
|
||||
|
||||
t_stat sim_rem_con_data_svc (UNIT *uptr)
|
||||
{
|
||||
@@ -1375,7 +1381,7 @@ t_stat stat = SCPE_OK;
|
||||
t_bool active_command = FALSE;
|
||||
int32 steps = 0;
|
||||
t_bool was_active_command = (sim_rem_cmd_active_line != -1);
|
||||
t_bool got_command;
|
||||
t_bool got_command = FALSE;
|
||||
t_bool close_session = FALSE;
|
||||
TMLN *lp;
|
||||
char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *argv[1] = {NULL};
|
||||
@@ -1383,16 +1389,19 @@ CONST char *cptr;
|
||||
CTAB *cmdp = NULL;
|
||||
CTAB *basecmdp = NULL;
|
||||
uint32 read_start_time = 0;
|
||||
t_bool abort_for_debug = FALSE;
|
||||
|
||||
tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
|
||||
if (abort_for_debug) /* Set this in the debugger to abort simulation and cleanly close debug output */
|
||||
SIM_SCP_ABORT ("Remote-Console-Data");
|
||||
tmxr_poll_rx (&sim_rem_con_tmxr); /* pickup any new input */
|
||||
for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
(i < sim_rem_con_tmxr.lines) && (!active_command);
|
||||
(i < sim_rem_con_tmxr.lines) && (!active_command) && (stat != SCPE_REMOTE);
|
||||
i++) {
|
||||
REMOTE *rem = &sim_rem_consoles[i];
|
||||
t_bool master_session = (sim_rem_master_mode && (i == 0));
|
||||
|
||||
lp = rem->lp;
|
||||
if (!lp->conn) {
|
||||
if (!lp->conn) { /* this line connection never connected or just dropped? */
|
||||
if (rem->repeat_interval) { /* was repeated enabled? */
|
||||
cptr = strcpy (gbuf, "STOP");
|
||||
sim_rem_repeat_cmd_setup (i, &cptr); /* make sure it is now disabled */
|
||||
@@ -1401,13 +1410,13 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
cptr = strcpy (gbuf, "STOP");
|
||||
sim_rem_collect_cmd_setup (i, &cptr); /* make sure it is now disabled */
|
||||
}
|
||||
continue;
|
||||
continue; /* process next line */
|
||||
}
|
||||
if (master_session && !sim_rem_master_was_connected) {
|
||||
if (master_session && !sim_rem_master_was_connected) { /* new/first master mode session */
|
||||
tmxr_linemsgf (lp, "\nMaster Mode Session\r\n");
|
||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||
tmxr_send_buffered_data (lp); /* flush just issued message from buffered data */
|
||||
sim_rem_master_was_connected = TRUE; /* Remember master actually connected */
|
||||
}
|
||||
sim_rem_master_was_connected |= master_session; /* Remember if master ever connected */
|
||||
stat = SCPE_OK;
|
||||
if ((was_active_command) ||
|
||||
(master_session && !rem->single_mode)) {
|
||||
@@ -1420,10 +1429,10 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
_sim_rem_message ("STEP", stat);/* produce a STEP complete message */
|
||||
}
|
||||
_sim_rem_log_out (lp);
|
||||
sim_rem_active_command = NULL; /* Restart loop to process available input */
|
||||
sim_rem_active_command = NULL; /* Restart loop to process any available input */
|
||||
was_active_command = FALSE;
|
||||
i = -1;
|
||||
continue;
|
||||
continue; /* process all lines */
|
||||
}
|
||||
else {
|
||||
sim_is_running = FALSE;
|
||||
@@ -1441,7 +1450,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else { /* (!was_active_command && (!master_session || rem->single_mode)) */
|
||||
if (((!rem->repeat_pending) && (rem->act == NULL)) || /* Repeat isn't pending AND no prior commands still active */
|
||||
(rem->buf_ptr != 0) || /* OR Not at beginning of line */
|
||||
(tmxr_input_pending_ln (lp))) { /* OR input available to read */
|
||||
@@ -1450,8 +1459,13 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
continue;
|
||||
c = c & ~TMXR_VALID;
|
||||
if (rem->single_mode) {
|
||||
if (c == sim_int_char) { /* ^E (the interrupt character) must start continue mode console interaction */
|
||||
rem->single_mode = FALSE; /* enter multi command mode */
|
||||
if (c == sim_int_char) { /* ^E (the interrupt character) must start continue mode console interaction */
|
||||
while (rem->buf_ptr > 0) { /* Erase current input line */
|
||||
tmxr_linemsg (lp, "\b \b");
|
||||
--rem->buf_ptr;
|
||||
}
|
||||
rem->single_mode = FALSE; /* enter multi command mode */
|
||||
rem->repeat_pending = FALSE;
|
||||
sim_is_running = FALSE;
|
||||
sim_rem_collect_all_registers ();
|
||||
sim_stop_timer_services ();
|
||||
@@ -1464,7 +1478,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
if ((i == j) || (!lpj->conn))
|
||||
continue;
|
||||
tmxr_linemsgf (lpj, "\nRemote Console %d(%s) Entering Commands\n", i, lp->ipad);
|
||||
tmxr_send_buffered_data (lpj); /* flush any buffered data */
|
||||
tmxr_send_buffered_data (lpj); /* flush the output message just buffered */
|
||||
}
|
||||
lp = &sim_rem_con_tmxr.ldsc[i];
|
||||
if (!master_session)
|
||||
@@ -1472,17 +1486,21 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
if (!master_session && rem->read_timeout) {
|
||||
tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", rem->read_timeout);
|
||||
tmxr_linemsgf (lp, "\r\n");
|
||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||
tmxr_send_buffered_data (lp); /* flush the output message just buffered */
|
||||
}
|
||||
}
|
||||
else {
|
||||
else { /* c != sim_int_char */
|
||||
if ((rem->buf_ptr == 0) && /* At beginning of input line */
|
||||
((c == '\n') || /* Ignore bare LF between commands (Microsoft Telnet bug) */
|
||||
(c == '\r'))) /* Ignore empty commands */
|
||||
continue;
|
||||
if ((c == '\004') || (c == '\032')) {/* EOF character (^D or ^Z) ? */
|
||||
while (rem->buf_ptr > 0) { /* Erase current input line */
|
||||
tmxr_linemsg (lp, "\b \b");
|
||||
--rem->buf_ptr;
|
||||
}
|
||||
tmxr_linemsgf (lp, "\r\nGoodbye\r\n");
|
||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||
tmxr_send_buffered_data (lp); /* flush the output message just buffered */
|
||||
tmxr_reset_ln (lp);
|
||||
continue;
|
||||
}
|
||||
@@ -1494,7 +1512,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> ");
|
||||
sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> ");
|
||||
if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp)))
|
||||
tmxr_send_buffered_data (lp);/* flush any buffered data */
|
||||
tmxr_send_buffered_data (lp);/* flush the output message just buffered */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1510,7 +1528,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
tmxr_linemsg (lp, "sim> ");
|
||||
else
|
||||
tmxr_linemsg (lp, sim_prompt);
|
||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||
tmxr_send_buffered_data (lp); /* flush the output message just buffered */
|
||||
}
|
||||
do {
|
||||
if (rem->buf_ptr == 0) {
|
||||
@@ -1525,7 +1543,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
}
|
||||
if ((rem->repeat_pending) && /* New repeat pending */
|
||||
(rem->act == NULL) && /* AND no prior still active */
|
||||
(!tmxr_input_pending_ln (lp))) { /* AND no session input pending */
|
||||
(!tmxr_input_pending_ln (lp))) { /* AND no session input pending on this line */
|
||||
rem->repeat_pending = FALSE;
|
||||
sim_rem_setact (rem-sim_rem_consoles, rem->repeat_action);
|
||||
sim_rem_getact (rem-sim_rem_consoles, rem->buf, rem->buf_size);
|
||||
@@ -1618,14 +1636,14 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
close_session = TRUE;
|
||||
break;
|
||||
default:
|
||||
tmxr_putc_ln (lp, c);
|
||||
tmxr_putc_ln (lp, c); /* echo input character */
|
||||
if (rem->buf_ptr+2 >= rem->buf_size) {
|
||||
rem->buf_size += 1024;
|
||||
rem->buf = (char *)realloc (rem->buf, rem->buf_size);
|
||||
}
|
||||
rem->buf[rem->buf_ptr++] = (char)c;
|
||||
rem->buf[rem->buf_ptr] = '\0';
|
||||
if (((size_t)rem->buf_ptr) >= sizeof(cbuf))
|
||||
if (rem->buf_ptr >= sizeof(cbuf))
|
||||
got_command = TRUE; /* command too long */
|
||||
break;
|
||||
}
|
||||
@@ -1850,6 +1868,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||
tmxr_reset_ln (lp);
|
||||
rem->single_mode = FALSE;
|
||||
close_session = FALSE;
|
||||
}
|
||||
}
|
||||
if (sim_rem_master_was_connected && /* Master mode ever connected? */
|
||||
|
||||
Reference in New Issue
Block a user