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:
parent
782bec605d
commit
80289e1e3b
@ -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
|
||||
|
||||
BIN
doc/simh_doc.doc
BIN
doc/simh_doc.doc
Binary file not shown.
150
sim_console.c
150
sim_console.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user