1
0
mirror of https://github.com/open-simh/simh.git synced 2026-01-14 15:46:31 +00:00

Enhanced Remote Console support to allow two separate command processing modes.

1) Single Command Mode:  commands are processed between simulated instructions once CR is received.
 2) Multiple Command Mode: commands are initiated with the WRU character (usually *E) which suspends simulation execution and commands are processed until a CONTINUE command is entered (or automatically provided if the SET REMOTE TIMEOUT=seconds interval has elapsed).
This commit is contained in:
Mark Pizzolato 2013-05-10 16:10:07 -07:00
parent 782bec605d
commit 80289e1e3b
3 changed files with 102 additions and 56 deletions

View File

@ -23,7 +23,13 @@
#### Remote Console Facility
A new capability has been added which allows a TELNET Connection to a user designated port so that some out of band commands can be entered to manipulate and/or adjust a running simulator. The commands which enable and control this capability are SET REMOTE TELNET=port, SET REMOTE CONNECTIONS=n, SET REMOTE TIMEOUT=seconds, and SHOW REMOTE.
A subset of normal simh commands are available for use in remote console sessions. These are: EXAMINE, IEXAMINE, DEPOSIT, EVALUATE, ATTACH, DETACH, ASSIGN, DEASSIGN, STEP, CONTINUE, PWD, SAVE, SET, SHOW, DIR, LS, ECHO, HELP
The remote console facility has two modes of operation: 1) single command mode. and 2) multiple command mode.
In single command mode you enter one command at a time and aren't concerned about what the simulated system is doing while you enter that command. The command is executed once you've hit return.
In multiple command mode you initiate your activities by entering the WRU character (usually ^E). This will suspend the current simulator execution. You then enter commands as needed and when you are done you enter a CONTINUE command. While entering Multiple Command commands, if you fail to enter a complete command before the timeout (specified by "SET REMOTE TIMEOUT=seconds"), a CONTINUE command is automatically processed and simulation proceeds.
A subset of normal simh commands are available for use in remote console sessions.
The Single Command Mode commands are: ATTACH, DETACH, PWD, SHOW, DIR, LS, ECHO, HELP
The Multiple Command Mode commands are: EXAMINE, IEXAMINE, DEPOSIT, EVALUATE, ATTACH, DETACH, ASSIGN, DEASSIGN, STEP, CONTINUE, PWD, SAVE, SET, SHOW, DIR, LS, ECHO, HELP
#### VAX/PDP11 Enhancements
RQ has new disk types: RC25, RCF25, RA80

Binary file not shown.

View File

@ -346,6 +346,7 @@ DEVICE sim_remote_console = {
static int32 *sim_rem_buf_size = NULL;
static int32 *sim_rem_buf_ptr = NULL;
static char **sim_rem_buf = NULL;
static t_bool *sim_rem_single_mode = NULL; /* per line command mode (single command or must continue) */
static TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };/* remote console line mux */
static uint32 sim_rem_read_timeout = 30; /* seconds before automatic continue */
static int32 sim_rem_step_line = -1; /* step in progress on line # */
@ -419,7 +420,9 @@ if (c >= 0) { /* poll connect */
sim_activate_after(uptr+1, 1000000); /* start data poll after 100ms */
lp->rcve = 1; /* rcv enabled */
sim_rem_buf_ptr[c] = 0; /* start with empty command buffer */
tmxr_linemsgf (lp, "%s Remote Console\r\nSimulator Running...", sim_name);
tmxr_linemsgf (lp, "%s Remote Console\r\n"
"Enter single commands or to enter multiple command mode enter the WRU character\r\n"
"Simulator Running...", sim_name);
tmxr_send_buffered_data (lp); /* flush buffered data */
}
sim_activate_after(uptr, 1000000); /* check again in 1 second */
@ -465,6 +468,18 @@ static CTAB allowed_remote_cmds[] = {
{ NULL, NULL }
};
static CTAB allowed_single_remote_cmds[] = {
{ "ATTACH", &attach_cmd, 0 },
{ "DETACH", &detach_cmd, 0 },
{ "PWD", &pwd_cmd, 0 },
{ "DIR", &dir_cmd, 0 },
{ "LS", &dir_cmd, 0 },
{ "ECHO", &echo_cmd, 0 },
{ "SHOW", &show_cmd, 0 },
{ "HELP", &x_help_cmd, 0 },
{ NULL, NULL }
};
static t_stat x_help_cmd (int32 flag, char *cptr)
{
CTAB *cmdp, *cmdph;
@ -539,52 +554,63 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
if (!(TMXR_VALID & c))
continue;
c = c & ~TMXR_VALID;
if (c != sim_int_char)
continue; /* ^E (the interrupt character) must start console interaction */
sim_is_running = 0;
sim_stop_timer_services ();
for (j=0; j < sim_rem_con_tmxr.lines; j++) {
lp = &sim_rem_con_tmxr.ldsc[j];
if ((i == j) || (!lp->conn))
continue;
tmxr_linemsgf (lp, "\nRemote Console(%s) Entering Commands\n", lp->ipad);
if (!sim_rem_single_mode[i]) {
if (c == sim_int_char) { /* ^E (the interrupt character) must start continue mode console interaction */
sim_is_running = 0;
sim_stop_timer_services ();
for (j=0; j < sim_rem_con_tmxr.lines; j++) {
lp = &sim_rem_con_tmxr.ldsc[j];
if ((i == j) || (!lp->conn))
continue;
tmxr_linemsgf (lp, "\nRemote Console(%s) Entering Commands\n", lp->ipad);
tmxr_send_buffered_data (lp); /* flush any buffered data */
}
lp = &sim_rem_con_tmxr.ldsc[i];
tmxr_linemsg (lp, "\r\nSimulator paused.\r\n");
if (sim_rem_read_timeout)
tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeout);
}
else {
sim_rem_single_mode[i] = TRUE;
tmxr_linemsg (lp, "\r\nsim> ");
tmxr_send_buffered_data (lp); /* flush any buffered data */
}
}
}
got_command = FALSE;
while (1) {
if (!sim_rem_single_mode[i]) {
read_start_time = sim_os_msec();
tmxr_linemsg (lp, "sim> ");
tmxr_send_buffered_data (lp); /* flush any buffered data */
}
lp = &sim_rem_con_tmxr.ldsc[i];
tmxr_linemsg (lp, "\r\nSimulator paused.\r\n");
if (sim_rem_read_timeout)
tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeout);
}
while (1) {
read_start_time = sim_os_msec();
tmxr_linemsg (lp, "sim> ");
tmxr_send_buffered_data (lp); /* flush any buffered data */
got_command = FALSE;
while (!got_command) {
c = tmxr_getc_ln (lp);
if (!(TMXR_VALID & c)) {
tmxr_send_buffered_data (lp); /* flush any buffered data */
if (sim_rem_read_timeout &&
((sim_os_msec() - read_start_time)/1000 >= sim_rem_read_timeout)) {
while (sim_rem_buf_ptr[i] > 0) { /* Erase current input line */
tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i];
do {
if (!sim_rem_single_mode[i]) {
c = tmxr_getc_ln (lp);
if (!(TMXR_VALID & c)) {
tmxr_send_buffered_data (lp); /* flush any buffered data */
if (sim_rem_read_timeout &&
((sim_os_msec() - read_start_time)/1000 >= sim_rem_read_timeout)) {
while (sim_rem_buf_ptr[i] > 0) { /* Erase current input line */
tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i];
}
if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) {
sim_rem_buf_size[i] += 1024;
sim_rem_buf[i] = realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
}
strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue due to timeout");
tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]);
got_command = TRUE;
break;
}
if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) {
sim_rem_buf_size[i] += 1024;
sim_rem_buf[i] = realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
}
strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue due to timeout");
tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]);
got_command = TRUE;
break;
sim_os_ms_sleep (100);
tmxr_poll_rx (&sim_rem_con_tmxr);/* poll input */
continue;
}
sim_os_ms_sleep (100);
tmxr_poll_rx (&sim_rem_con_tmxr);/* poll input */
continue;
read_start_time = sim_os_msec();
c = c & ~TMXR_VALID;
}
read_start_time = sim_os_msec();
c = c & ~TMXR_VALID;
switch (c) {
case 0: /* no data */
break;
@ -626,8 +652,10 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
got_command = TRUE; /* command too long */
break;
}
}
} while ((!got_command) && (!sim_rem_single_mode[i]));
tmxr_send_buffered_data (lp); /* flush any buffered data */
if ((sim_rem_single_mode[i]) && !got_command)
break;
printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]);
if (sim_log)
fprintf (sim_log, "Remote Console Command from %s> %s\n", lp->ipad, sim_rem_buf[i]);
@ -643,7 +671,12 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
sim_rem_buf_ptr[i] = 0;
sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0';
if (cbuf[0] == '\0')
continue;
if (sim_rem_single_mode[i]) {
sim_rem_single_mode[i] = FALSE;
break;
}
else
continue;
sim_sub_args (cbuf, sizeof(cbuf), argv);
cptr = cbuf;
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
@ -661,7 +694,7 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
if (!find_cmd (gbuf)) /* validate command */
stat = SCPE_UNK;
else {
if ((cmdp = find_ctab (allowed_remote_cmds, gbuf))) {/* lookup command */
if ((cmdp = find_ctab (sim_rem_single_mode[i] ? allowed_single_remote_cmds : allowed_remote_cmds, gbuf))) {/* lookup command */
if (cmdp->action == &x_continue_cmd)
stat = SCPE_OK;
else {
@ -709,28 +742,32 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
tmxr_linemsgf (lp, "%s", cbuf);
tmxr_send_buffered_data (lp);
}
if (cmdp && (cmdp->action == &x_continue_cmd)) {
if ((cmdp && (cmdp->action == &x_continue_cmd)) ||
(sim_rem_single_mode[i])) {
sim_rem_step_line = -1; /* Not stepping */
if (sim_log_temp) { /* If we setup a temporary log, clean it now */
int32 save_quiet = sim_quiet;
sim_quiet = 0;
sim_quiet = 1;
sim_set_logoff (0, NULL);
sim_quiet = save_quiet;
remove (sim_rem_con_temp_name);
sim_log_temp = FALSE;
}
tmxr_linemsg (lp, "Simulator Running...");
tmxr_send_buffered_data (lp);
for (j=0; j < sim_rem_con_tmxr.lines; j++) {
lp = &sim_rem_con_tmxr.ldsc[j];
if ((i == j) || (!lp->conn))
continue;
if (!sim_rem_single_mode[i]) {
tmxr_linemsg (lp, "Simulator Running...");
tmxr_send_buffered_data (lp);
for (j=0; j < sim_rem_con_tmxr.lines; j++) {
lp = &sim_rem_con_tmxr.ldsc[j];
if ((i == j) || (!lp->conn))
continue;
tmxr_linemsg (lp, "Simulator Running...");
tmxr_send_buffered_data (lp);
}
sim_is_running = 1;
sim_start_timer_services ();
}
sim_is_running = 1;
sim_start_timer_services ();
sim_rem_single_mode[i] = FALSE;
break;
}
if (cmdp && (cmdp->action == &x_step_cmd)) {
@ -782,6 +819,7 @@ else {
sim_rem_buf[i] = NULL;
sim_rem_buf_size[i] = 0;
sim_rem_buf_ptr[i] = 0;
sim_rem_single_mode[i] = FALSE;
}
}
}
@ -812,6 +850,8 @@ sim_rem_buf_size = realloc (sim_rem_buf_size, sizeof(*sim_rem_buf_size)*lines);
memset (sim_rem_buf_size, 0, sizeof(*sim_rem_buf_size)*lines);
sim_rem_buf_ptr = realloc (sim_rem_buf_ptr, sizeof(*sim_rem_buf_ptr)*lines);
memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines);
sim_rem_single_mode = realloc (sim_rem_single_mode, sizeof(*sim_rem_single_mode)*lines);
memset (sim_rem_single_mode, 0, sizeof(*sim_rem_single_mode)*lines);
return SCPE_OK;
}