SCP: Added a Remote Console Master Mode.

This capability will allow a GDB RSB stub to be created to support dynamic debugging of code running in a simulator.

This capability will also allow a complete front panel emulation system to operate a simulator.

This capability is engaged in a simulator by:
     sim> set remote telnet=remoteconsoleport#
     sim> set console telnet=consoleport#
     sim> set remote master

Master mode will provide a TCP session which accepts SCP commands that allow full control of the simulator.
This commit is contained in:
Mark Pizzolato 2014-10-26 15:15:31 -07:00
parent 4dbac410da
commit 611a7e94f0
3 changed files with 296 additions and 97 deletions

View file

@ -716,6 +716,11 @@ pager_tc = FALSE; /* not in trap cycle */
pflgs = 0; /* not in PXCT */ pflgs = 0; /* not in PXCT */
xct_cnt = 0; /* count XCT's */ xct_cnt = 0; /* count XCT's */
if (sim_interval <= 0) { /* check clock queue */ if (sim_interval <= 0) { /* check clock queue */
/* make sure all useful state is in simh registers while processing events */
saved_PC = pager_PC & AMASK; /* failing instr PC */
set_ac_display (ac_cur); /* set up AC display */
pcq_r->qptr = pcq_p; /* update pc q ptr */
if ((i = sim_process_event ())) /* error? stop sim */ if ((i = sim_process_event ())) /* error? stop sim */
ABORT (i); ABORT (i);
if (fe_xct) if (fe_xct)

View file

@ -731,6 +731,14 @@ while (reason == 0) {
AIO_CHECK_EVENT; AIO_CHECK_EVENT;
if (sim_interval <= 0) { /* intv cnt expired? */ if (sim_interval <= 0) { /* intv cnt expired? */
/* Make sure all intermediate state is visible in simh registers */
PSW = get_PSW ();
for (i = 0; i < 6; i++)
REGFILE[i][rs] = R[i];
STACKFILE[cm] = SP;
saved_PC = PC & 0177777;
pcq_r->qptr = pcq_p; /* update pc q ptr */
set_r_display (rs, cm);
reason = sim_process_event (); /* process events */ reason = sim_process_event (); /* process events */
trap_req = calc_ints (ipl, trap_req); /* recalc int req */ trap_req = calc_ints (ipl, trap_req); /* recalc int req */
continue; continue;
@ -3133,7 +3141,6 @@ return iopageW ((int32) val, addr, WRITEC);
void set_r_display (int32 rs, int32 cm) void set_r_display (int32 rs, int32 cm)
{ {
extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr);
REG *rptr; REG *rptr;
int32 i; int32 i;

View file

@ -148,6 +148,7 @@ static t_bool sim_os_ttisatty (void);
static t_stat sim_set_rem_telnet (int32 flag, char *cptr); static t_stat sim_set_rem_telnet (int32 flag, char *cptr);
static t_stat sim_set_rem_connections (int32 flag, char *cptr); static t_stat sim_set_rem_connections (int32 flag, char *cptr);
static t_stat sim_set_rem_timeout (int32 flag, char *cptr); static t_stat sim_set_rem_timeout (int32 flag, char *cptr);
static t_stat sim_set_rem_master (int32 flag, char *cptr);
/* Deprecated CONSOLE HALT, CONSOLE RESPONSE and CONSOLE DELAY support */ /* Deprecated CONSOLE HALT, CONSOLE RESPONSE and CONSOLE DELAY support */
static t_stat sim_set_halt (int32 flag, char *cptr); static t_stat sim_set_halt (int32 flag, char *cptr);
@ -259,6 +260,8 @@ static CTAB set_rem_con_tab[] = {
{ "TELNET", &sim_set_rem_telnet, 1 }, { "TELNET", &sim_set_rem_telnet, 1 },
{ "NOTELNET", &sim_set_rem_telnet, 0 }, { "NOTELNET", &sim_set_rem_telnet, 0 },
{ "TIMEOUT", &sim_set_rem_timeout, 0 }, { "TIMEOUT", &sim_set_rem_timeout, 0 },
{ "MASTER", &sim_set_rem_master, 1 },
{ "NOMASTER", &sim_set_rem_master, 0 },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
@ -385,9 +388,14 @@ static char **sim_rem_buf = NULL;
static t_bool *sim_rem_single_mode = NULL; /* per line command mode (single command or must continue) */ 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 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 uint32 sim_rem_read_timeout = 30; /* seconds before automatic continue */
static uint32 *sim_rem_read_timeouts = NULL;/* per line read timeout (default from sim_rem_read_timeout) */
static int32 sim_rem_active_number = -1; /* -1 - not active, >= 0 is index of active console */
static int32 sim_rem_step_line = -1; /* step in progress on line # */ static int32 sim_rem_step_line = -1; /* step in progress on line # */
static t_bool sim_log_temp = FALSE; /* temporary log file active */ static t_bool sim_log_temp = FALSE; /* temporary log file active */
static char sim_rem_con_temp_name[PATH_MAX+1]; static char sim_rem_con_temp_name[PATH_MAX+1];
static int32 sim_rem_master_mode = 0; /* Master Mode Enabled Flag */
static t_offset sim_rem_cmd_log_start = 0; /* Log File saved position */
/* SET REMOTE CONSOLE command */ /* SET REMOTE CONSOLE command */
@ -423,6 +431,11 @@ TMLN *lp;
if (*cptr != 0) if (*cptr != 0)
return SCPE_NOPARAM; return SCPE_NOPARAM;
if (sim_rem_active_number >= 0)
if (sim_rem_master_mode && (sim_rem_active_number == 0))
fprintf (st, "Running from Master Mode Remote Console Connection\n");
else
fprintf (st, "Running from Remote Console Connection %d\n", sim_rem_active_number);
if (sim_rem_con_tmxr.lines > 1) if (sim_rem_con_tmxr.lines > 1)
fprintf (st, "Remote Console Input Connections from %d sources are supported concurrently\n", sim_rem_con_tmxr.lines); fprintf (st, "Remote Console Input Connections from %d sources are supported concurrently\n", sim_rem_con_tmxr.lines);
if (sim_rem_read_timeout) if (sim_rem_read_timeout)
@ -439,6 +452,11 @@ for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
if (connections == 1) if (connections == 1)
fprintf (st, "Remote Console Connections:\n"); fprintf (st, "Remote Console Connections:\n");
tmxr_fconns (st, lp, i); tmxr_fconns (st, lp, i);
if (sim_rem_read_timeouts[i] != sim_rem_read_timeout)
if (sim_rem_read_timeouts[i])
fprintf (st, "Remote Console Input on connection %d automatically continues after %d seconds\n", i, sim_rem_read_timeouts[i]);
else
fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i);
} }
return SCPE_OK; return SCPE_OK;
} }
@ -457,7 +475,8 @@ if (c >= 0) { /* poll connect */
sim_activate_after(uptr+1, 1000000); /* start data poll after 1 second */ sim_activate_after(uptr+1, 1000000); /* start data poll after 1 second */
lp->rcve = 1; /* rcv enabled */ lp->rcve = 1; /* rcv enabled */
sim_rem_buf_ptr[c] = 0; /* start with empty command buffer */ sim_rem_buf_ptr[c] = 0; /* start with empty command buffer */
sim_rem_single_mode[c] = FALSE; /* in single command mode */ sim_rem_single_mode[c] = TRUE; /* start in single command mode */
sim_rem_read_timeouts[c] = sim_rem_read_timeout; /* Start with default timeout */
if (isprint(sim_int_char&0xFF)) if (isprint(sim_int_char&0xFF))
sprintf(wru_name, "'%c'", sim_int_char&0xFF); sprintf(wru_name, "'%c'", sim_int_char&0xFF);
else else
@ -467,7 +486,11 @@ if (c >= 0) { /* poll connect */
sprintf(wru_name, "'\\%03o'", sim_int_char&0xFF); sprintf(wru_name, "'\\%03o'", sim_int_char&0xFF);
tmxr_linemsgf (lp, "%s Remote Console\r\n" tmxr_linemsgf (lp, "%s Remote Console\r\n"
"Enter single commands or to enter multiple command mode enter the %s character\r\n" "Enter single commands or to enter multiple command mode enter the %s character\r\n"
"Simulator Running...", sim_name, wru_name); "%s",
sim_name, wru_name,
((sim_rem_master_mode && (c == 0)) ? "Master Mode Session\r\n" : "Simulator Running..."));
if (sim_rem_master_mode && (c == 0)) /* Master Mode session? */
sim_rem_single_mode[c] = FALSE; /* start in multi-command mode */
tmxr_send_buffered_data (lp); /* flush buffered data */ tmxr_send_buffered_data (lp); /* flush buffered data */
} }
sim_activate_after(uptr, 1000000); /* check again in 1 second */ sim_activate_after(uptr, 1000000); /* check again in 1 second */
@ -486,11 +509,13 @@ static t_stat x_step_cmd (int32 flag, char *cptr)
return SCPE_IERR; /* This routine should never be called */ return SCPE_IERR; /* This routine should never be called */
} }
static t_stat x_run_cmd (int32 flag, char *cptr)
{
return SCPE_IERR; /* This routine should never be called */
}
static t_stat x_help_cmd (int32 flag, char *cptr); static t_stat x_help_cmd (int32 flag, char *cptr);
#define EX_D 0 /* deposit */
#define EX_E 1 /* examine */
#define EX_I 2 /* interactive */
static CTAB allowed_remote_cmds[] = { static CTAB allowed_remote_cmds[] = {
{ "EXAMINE", &exdep_cmd, EX_E }, { "EXAMINE", &exdep_cmd, EX_E },
{ "IEXAMINE", &exdep_cmd, EX_E+EX_I }, { "IEXAMINE", &exdep_cmd, EX_E+EX_I },
@ -513,6 +538,35 @@ static CTAB allowed_remote_cmds[] = {
{ NULL, NULL } { NULL, NULL }
}; };
static CTAB allowed_master_remote_cmds[] = {
{ "EXAMINE", &exdep_cmd, EX_E },
{ "IEXAMINE", &exdep_cmd, EX_E+EX_I },
{ "DEPOSIT", &exdep_cmd, EX_D },
{ "EVALUATE", &eval_cmd, 0 },
{ "ATTACH", &attach_cmd, 0 },
{ "DETACH", &detach_cmd, 0 },
{ "ASSIGN", &assign_cmd, 0 },
{ "DEASSIGN", &deassign_cmd, 0 },
{ "CONTINUE", &x_continue_cmd, 0 },
{ "STEP", &x_step_cmd, 0 },
{ "PWD", &pwd_cmd, 0 },
{ "SAVE", &save_cmd, 0 },
{ "CD", &set_default_cmd, 0 },
{ "DIR", &dir_cmd, 0 },
{ "LS", &dir_cmd, 0 },
{ "ECHO", &echo_cmd, 0 },
{ "SET", &set_cmd, 0 },
{ "SHOW", &show_cmd, 0 },
{ "HELP", &x_help_cmd, 0 },
{ "EXIT", &exit_cmd, 0 },
{ "RUN", &x_run_cmd, RU_RUN },
{ "GO", &x_run_cmd, RU_GO },
{ "BOOT", &x_run_cmd, RU_BOOT },
{ "BREAK", &brk_cmd, SSH_ST },
{ "NOBREAK", &brk_cmd, SSH_CL },
{ NULL, NULL }
};
static CTAB allowed_single_remote_cmds[] = { static CTAB allowed_single_remote_cmds[] = {
{ "ATTACH", &attach_cmd, 0 }, { "ATTACH", &attach_cmd, 0 },
{ "DETACH", &detach_cmd, 0 }, { "DETACH", &detach_cmd, 0 },
@ -548,22 +602,59 @@ sim_printf ("Enter \"HELP cmd\" for detailed help on a command\r\n");
return SCPE_OK; return SCPE_OK;
} }
static t_stat _sim_rem_message (const char *cmd, t_stat stat)
{
CTAB *cmdp = NULL;
t_stat stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
cmdp = find_cmd (cmd);
stat = SCPE_BARE_STATUS(stat); /* remove possible flag */
if (cmdp && (cmdp->message)) /* special message handler? */
cmdp->message (NULL, stat); /* let it deal with display */
else
if (stat >= SCPE_BASE) /* error? */
sim_printf ("%s\r\n", sim_error_text (stat));
return stat;
}
static void _sim_rem_log_out (TMLN *lp)
{
char cbuf[4*CBUFSIZE];
if (sim_log) {
fflush (sim_log);
sim_fseeko (sim_log, sim_rem_cmd_log_start, SEEK_SET);
cbuf[sizeof(cbuf)-1] = '\0';
while (fgets (cbuf, sizeof(cbuf)-1, sim_log)) {
int32 unwritten;
tmxr_linemsgf (lp, "%s", cbuf);
do {
unwritten = tmxr_send_buffered_data (lp);
if (unwritten == lp->txbsz)
sim_os_ms_sleep (100);
} while (unwritten == lp->txbsz);
}
}
}
/* Unit service for remote console data polling */ /* Unit service for remote console data polling */
t_stat sim_rem_con_data_svc (UNIT *uptr) t_stat sim_rem_con_data_svc (UNIT *uptr)
{ {
int32 i, j, c = 0; int32 i, j, c = 0;
t_stat stat, stat_nomessage; t_stat stat = SCPE_OK;
t_bool stepping = FALSE; t_bool stepping = FALSE;
int32 steps = 1; int32 steps = 1;
t_bool was_stepping = (sim_rem_step_line != -1); t_bool was_stepping = (sim_rem_step_line != -1);
#define master_session (sim_rem_master_mode && (i == 0))
t_bool got_command; t_bool got_command;
t_bool close_session = FALSE; t_bool close_session = FALSE;
TMLN *lp; TMLN *lp;
char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *cptr, *argv[1] = {NULL}; char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *cptr, *argv[1] = {NULL};
CTAB *cmdp = NULL; CTAB *cmdp = NULL;
CTAB *basecmdp = NULL;
uint32 read_start_time = 0; uint32 read_start_time = 0;
t_offset cmd_log_start;
tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */ tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
for (i=(was_stepping ? sim_rem_step_line : 0); for (i=(was_stepping ? sim_rem_step_line : 0);
@ -572,49 +663,53 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
lp = &sim_rem_con_tmxr.ldsc[i]; lp = &sim_rem_con_tmxr.ldsc[i];
if (!lp->conn) if (!lp->conn)
continue; continue;
if ((was_stepping) ||
(master_session && !sim_rem_single_mode[i])) {
if (was_stepping) { if (was_stepping) {
sim_rem_step_line = -1; /* Done with step */ sim_rem_step_line = -1; /* Done with step */
stat = SCPE_STEP; stat = SCPE_STEP;
cmdp = find_cmd ("STEP"); _sim_rem_message ("STEP", stat);
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
stat = SCPE_BARE_STATUS(stat); /* remove possible flag */
if (!stat_nomessage) { /* displaying message status? */
fflush (sim_log);
cmd_log_start = sim_ftell (sim_log);
if (cmdp && (cmdp->message)) /* special message handler? */
cmdp->message (NULL, stat); /* let it deal with display */
else
if (stat >= SCPE_BASE) /* error? */
sim_printf ("%s\r\n", sim_error_text (stat));
fflush (sim_log);
sim_fseeko (sim_log, cmd_log_start, SEEK_SET);
cbuf[sizeof(cbuf)-1] = '\0';
while (fgets (cbuf, sizeof(cbuf)-1, sim_log)) {
tmxr_linemsgf (lp, "%s", cbuf);
tmxr_send_buffered_data (lp);
} }
else {
sim_is_running = 0;
sim_stop_timer_services ();
for (j=0; j < sim_rem_con_tmxr.lines; j++) {
TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
if ((i == j) || (!lpj->conn))
continue;
tmxr_linemsgf (lpj, "\nRemote Master Console(%s) Entering Commands\n", lp->ipad);
tmxr_send_buffered_data (lpj); /* flush any buffered data */
} }
lp = &sim_rem_con_tmxr.ldsc[i];
}
_sim_rem_log_out (lp);
} }
else { else {
c = tmxr_getc_ln (lp); c = tmxr_getc_ln (lp);
if (!(TMXR_VALID & c)) if (!(TMXR_VALID & c))
continue; continue;
c = c & ~TMXR_VALID; c = c & ~TMXR_VALID;
if (!sim_rem_single_mode[i]) { if (sim_rem_single_mode[i]) {
if (c == sim_int_char) { /* ^E (the interrupt character) must start continue mode console interaction */ if (c == sim_int_char) { /* ^E (the interrupt character) must start continue mode console interaction */
sim_rem_single_mode[i] = FALSE; /* enter multi command mode */
sim_is_running = 0; sim_is_running = 0;
sim_stop_timer_services (); sim_stop_timer_services ();
stat = SCPE_STOP;
_sim_rem_message ("RUN", stat);
_sim_rem_log_out (lp);
for (j=0; j < sim_rem_con_tmxr.lines; j++) { for (j=0; j < sim_rem_con_tmxr.lines; j++) {
lp = &sim_rem_con_tmxr.ldsc[j]; TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
if ((i == j) || (!lp->conn)) if ((i == j) || (!lpj->conn))
continue; continue;
tmxr_linemsgf (lp, "\nRemote Console(%s) Entering Commands\n", lp->ipad); tmxr_linemsgf (lpj, "\nRemote Console %d(%s) Entering Commands\n", i, lp->ipad);
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (lpj); /* flush any buffered data */
} }
lp = &sim_rem_con_tmxr.ldsc[i]; lp = &sim_rem_con_tmxr.ldsc[i];
tmxr_linemsg (lp, "\r\nSimulator paused.\r\n"); tmxr_linemsg (lp, "\r\nSimulator paused.\r\n");
if (sim_rem_read_timeout) if (sim_rem_read_timeouts[i])
tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeout); tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeouts[i]);
tmxr_linemsgf (lp, "\r\n%s", sim_prompt);
tmxr_send_buffered_data (lp); /* flush any buffered data */
} }
else { else {
if ((c == '\n') || /* Ignore bare LF between commands (Microsoft Telnet bug) */ if ((c == '\n') || /* Ignore bare LF between commands (Microsoft Telnet bug) */
@ -626,14 +721,18 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
tmxr_reset_ln (lp); tmxr_reset_ln (lp);
continue; continue;
} }
sim_rem_single_mode[i] = TRUE; if (sim_rem_buf_ptr[i] == 0) {
/* we just picked up the first character on a command line */
tmxr_linemsgf (lp, "\r\n%s", sim_prompt); tmxr_linemsgf (lp, "\r\n%s", sim_prompt);
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (lp); /* flush any buffered data */
} }
} }
} }
}
got_command = FALSE; got_command = FALSE;
while (1) { while (1) {
if (stat == SCPE_EXIT)
return stat|SCPE_NOMESSAGE;
if (!sim_rem_single_mode[i]) { if (!sim_rem_single_mode[i]) {
read_start_time = sim_os_msec(); read_start_time = sim_os_msec();
tmxr_linemsg (lp, sim_prompt); tmxr_linemsg (lp, sim_prompt);
@ -644,8 +743,8 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
c = tmxr_getc_ln (lp); c = tmxr_getc_ln (lp);
if (!(TMXR_VALID & c)) { if (!(TMXR_VALID & c)) {
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (lp); /* flush any buffered data */
if (sim_rem_read_timeout && if (sim_rem_read_timeouts[i] &&
((sim_os_msec() - read_start_time)/1000 >= sim_rem_read_timeout)) { ((sim_os_msec() - read_start_time)/1000 >= sim_rem_read_timeouts[i])) {
while (sim_rem_buf_ptr[i] > 0) { /* Erase current input line */ while (sim_rem_buf_ptr[i] > 0) { /* Erase current input line */
tmxr_linemsg (lp, "\b \b"); tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i]; --sim_rem_buf_ptr[i];
@ -752,6 +851,7 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
cptr = cbuf; cptr = cbuf;
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
sim_switches = 0; /* init switches */ sim_switches = 0; /* init switches */
sim_rem_active_number = i;
if (!sim_log) { /* Not currently logging? */ if (!sim_log) { /* Not currently logging? */
int32 save_quiet = sim_quiet; int32 save_quiet = sim_quiet;
@ -761,11 +861,12 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
sim_quiet = save_quiet; sim_quiet = save_quiet;
sim_log_temp = TRUE; sim_log_temp = TRUE;
} }
cmd_log_start = sim_ftell (sim_log); sim_rem_cmd_log_start = sim_ftell (sim_log);
if (!find_cmd (gbuf)) /* validate command */ basecmdp = find_cmd (gbuf); /* validate basic command */
if (basecmdp == NULL)
stat = SCPE_UNK; stat = SCPE_UNK;
else { else {
if ((cmdp = find_ctab (sim_rem_single_mode[i] ? allowed_single_remote_cmds : allowed_remote_cmds, gbuf))) {/* lookup command */ if ((cmdp = find_ctab (sim_rem_single_mode[i] ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {/* lookup command */
if (cmdp->action == &x_continue_cmd) if (cmdp->action == &x_continue_cmd)
stat = SCPE_OK; stat = SCPE_OK;
else { else {
@ -787,39 +888,33 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
else else
cmdp = NULL; cmdp = NULL;
} }
else {
if (cmdp->action == &x_run_cmd) {
sim_switches |= SIM_SW_HIDE; /* Request Setup only */
stat = basecmdp->action (cmdp->arg, cptr);
sim_switches &= ~SIM_SW_HIDE; /* Done with Setup only mode */
if (stat == SCPE_OK) {
/* switch to CONTINUE after x_run_cmd() did RUN setup */
cmdp = find_ctab (allowed_master_remote_cmds, "CONTINUE");
}
}
else else
stat = cmdp->action (cmdp->arg, cptr); stat = cmdp->action (cmdp->arg, cptr);
} }
} }
}
else else
stat = SCPE_INVREM; stat = SCPE_INVREM;
} }
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */ sim_rem_active_number = -1;
stat = SCPE_BARE_STATUS(stat); /* remove possible flag */ if (stat != SCPE_OK)
if (!stat_nomessage) { /* displaying message status? */ stat = _sim_rem_message (gbuf, stat);
if (cmdp && (cmdp->message)) /* special message handler? */ _sim_rem_log_out (lp);
cmdp->message (NULL, stat); /* let it deal with display */
else
if (stat >= SCPE_BASE) /* error? */
sim_printf ("%s\r\n", sim_error_text (stat));
}
fflush (sim_log);
sim_fseeko (sim_log, cmd_log_start, SEEK_SET);
cbuf[sizeof(cbuf)-1] = '\0';
while (fgets (cbuf, sizeof(cbuf)-1, sim_log)) {
int32 unwritten;
tmxr_linemsgf (lp, "%s", cbuf);
do {
unwritten = tmxr_send_buffered_data (lp);
if (unwritten == lp->txbsz)
sim_os_ms_sleep (100);
} while (unwritten == lp->txbsz);
}
if ((cmdp && (cmdp->action == &x_continue_cmd)) || if ((cmdp && (cmdp->action == &x_continue_cmd)) ||
(sim_rem_single_mode[i])) { (sim_rem_single_mode[i])) {
sim_rem_step_line = -1; /* Not stepping */ sim_rem_step_line = -1; /* Not stepping */
if (sim_log_temp) { /* If we setup a temporary log, clean it now */ if (sim_log_temp && /* If we setup a temporary log, clean it now */
(!sim_rem_master_mode)) {
int32 save_quiet = sim_quiet; int32 save_quiet = sim_quiet;
sim_quiet = 1; sim_quiet = 1;
@ -828,20 +923,29 @@ for (i=(was_stepping ? sim_rem_step_line : 0);
remove (sim_rem_con_temp_name); remove (sim_rem_con_temp_name);
sim_log_temp = FALSE; sim_log_temp = FALSE;
} }
else {
fflush (sim_log);
sim_rem_cmd_log_start = sim_ftell (sim_log);
}
if (!sim_rem_single_mode[i]) { if (!sim_rem_single_mode[i]) {
tmxr_linemsg (lp, "Simulator Running..."); tmxr_linemsg (lp, "Simulator Running...");
tmxr_send_buffered_data (lp); tmxr_send_buffered_data (lp);
for (j=0; j < sim_rem_con_tmxr.lines; j++) { for (j=0; j < sim_rem_con_tmxr.lines; j++) {
lp = &sim_rem_con_tmxr.ldsc[j]; TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
if ((i == j) || (!lp->conn)) if ((i == j) || (!lpj->conn))
continue; continue;
tmxr_linemsg (lp, "Simulator Running..."); tmxr_linemsg (lpj, "Simulator Running...");
tmxr_send_buffered_data (lp); tmxr_send_buffered_data (lpj);
} }
sim_is_running = 1; sim_is_running = 1;
sim_start_timer_services (); sim_start_timer_services ();
} }
sim_rem_single_mode[i] = FALSE; if (cmdp && (cmdp->action == &x_continue_cmd))
sim_rem_single_mode[i] = TRUE;
else {
tmxr_linemsgf (lp, "%s", sim_prompt);
tmxr_send_buffered_data (lp);
}
break; break;
} }
if (cmdp && (cmdp->action == &x_step_cmd)) { if (cmdp && (cmdp->action == &x_step_cmd)) {
@ -899,7 +1003,7 @@ else {
sim_rem_buf[i] = NULL; sim_rem_buf[i] = NULL;
sim_rem_buf_size[i] = 0; sim_rem_buf_size[i] = 0;
sim_rem_buf_ptr[i] = 0; sim_rem_buf_ptr[i] = 0;
sim_rem_single_mode[i] = FALSE; sim_rem_single_mode[i] = TRUE;
} }
} }
} }
@ -932,6 +1036,8 @@ sim_rem_buf_ptr = (int32 *)realloc (sim_rem_buf_ptr, sizeof(*sim_rem_buf_ptr)*li
memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines); memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines);
sim_rem_single_mode = (t_bool *)realloc (sim_rem_single_mode, sizeof(*sim_rem_single_mode)*lines); sim_rem_single_mode = (t_bool *)realloc (sim_rem_single_mode, sizeof(*sim_rem_single_mode)*lines);
memset (sim_rem_single_mode, 0, sizeof(*sim_rem_single_mode)*lines); memset (sim_rem_single_mode, 0, sizeof(*sim_rem_single_mode)*lines);
sim_rem_read_timeouts = (t_bool *)realloc (sim_rem_read_timeouts, sizeof(*sim_rem_read_timeouts)*lines);
memset (sim_rem_read_timeouts, 0, sizeof(*sim_rem_read_timeouts)*lines);
return SCPE_OK; return SCPE_OK;
} }
@ -945,10 +1051,70 @@ if (cptr == NULL)
timeout = (int32) get_uint (cptr, 10, 3600, &r); timeout = (int32) get_uint (cptr, 10, 3600, &r);
if (r != SCPE_OK) if (r != SCPE_OK)
return r; return r;
sim_rem_read_timeout = timeout; if (sim_rem_active_number >= 0)
sim_rem_read_timeouts[sim_rem_active_number] = timeout;
else
sim_rem_read_timeout = timeout;
return SCPE_OK; return SCPE_OK;
} }
/* Enable or disable Remote Console master mode */
/* In master mode, ... explain */
static t_stat sim_set_rem_master (int32 flag, char *cptr)
{
t_stat stat = SCPE_OK;
if (cptr && *cptr)
return SCPE_2MARG;
if (sim_rem_active_number > 0) {
sim_printf ("Can't change Remote Console mode from Remote Console\n");
return SCPE_INVREM;
}
if (sim_rem_con_tmxr.master || (!flag)) /* Remote Console Enabled? */
sim_rem_master_mode = flag;
else {
sim_printf ("Can't enable Remote Console Master mode with Remote Console disabled\n");
return SCPE_INVREM;
}
if (sim_rem_master_mode) {
t_stat stat_nomessage;
if ((!sim_con_ldsc.serport) &&
(sim_con_tmxr.master == 0)) {
sim_printf ("Console port must be Telnet or Serial with Master Remote Console\r\n");
return SCPE_IERR|SCPE_NOMESSAGE;
}
sim_printf ("Command input now processed on Master Remote Console Session\n");
stat = sim_run_boot_prep ();
while (sim_rem_master_mode) {
sim_rem_single_mode[0] = FALSE;
sim_cancel (&sim_rem_con_unit[1]);
sim_activate (&sim_rem_con_unit[1], -1);
stat = run_cmd (RU_GO, "");
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
stat = _sim_rem_message ("RUN", stat);
if (stat == SCPE_EXIT)
sim_rem_master_mode = FALSE;
}
if (sim_log_temp) { /* If we setup a temporary log, clean it now */
int32 save_quiet = sim_quiet;
sim_quiet = 1;
sim_set_logoff (0, NULL);
sim_quiet = save_quiet;
remove (sim_rem_con_temp_name);
sim_log_temp = FALSE;
}
stat |= stat_nomessage;
}
return stat;
}
/* Set keyboard map */ /* Set keyboard map */
t_stat sim_set_kmap (int32 flag, char *cptr) t_stat sim_set_kmap (int32 flag, char *cptr)
@ -1471,12 +1637,35 @@ if (!ref)
return ref->name; return ref->name;
} }
/* Check connection before executing */ /* Check connection before executing
(including a remote console which may be required in master mode) */
t_stat sim_check_console (int32 sec) t_stat sim_check_console (int32 sec)
{ {
int32 c, i; int32 c, trys = 0;
if (sim_rem_master_mode) {
if ((!sim_con_ldsc.serport) &&
(sim_con_tmxr.master == 0)) {
sim_printf ("Console port must be Telnet or Serial with Master Remote Console\r\n");
return SCPE_IERR|SCPE_NOMESSAGE;
}
for (;trys < sec; ++trys) {
sim_rem_con_poll_svc (&sim_rem_con_unit[0]);
if (sim_rem_con_tmxr.ldsc[0].conn)
break;
if ((trys % 10) == 0) { /* Status every 10 sec */
sim_printf ("Waiting for Remote Console connection\r\n");
fflush (stdout);
if (sim_log) /* log file? */
fflush (sim_log);
}
sim_os_sleep (1); /* wait 1 second */
}
}
if (trys == sec) {
return SCPE_TTMO; /* timed out */
}
if (sim_con_ldsc.serport) if (sim_con_ldsc.serport)
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) if (tmxr_poll_conn (&sim_con_tmxr) >= 0)
sim_con_ldsc.rcve = 1; /* rcv enabled */ sim_con_ldsc.rcve = 1; /* rcv enabled */
@ -1495,10 +1684,10 @@ if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* connected or buffered
return SCPE_OK; return SCPE_OK;
} }
} }
for (i = 0; i < sec; i++) { /* loop */ for (; trys < sec; trys++) { /* loop */
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */
sim_con_ldsc.rcve = 1; /* rcv enabled */ sim_con_ldsc.rcve = 1; /* rcv enabled */
if (i) { /* if delayed */ if (trys) { /* if delayed */
sim_printf ("Running\r\n"); /* print transition */ sim_printf ("Running\r\n"); /* print transition */
fflush (stdout); fflush (stdout);
if (sim_log) /* log file? */ if (sim_log) /* log file? */
@ -1509,7 +1698,7 @@ for (i = 0; i < sec; i++) { /* loop */
c = sim_os_poll_kbd (); /* check for stop char */ c = sim_os_poll_kbd (); /* check for stop char */
if ((c == SCPE_STOP) || stop_cpu) if ((c == SCPE_STOP) || stop_cpu)
return SCPE_STOP; return SCPE_STOP;
if ((i % 10) == 0) { /* Status every 10 sec */ if ((trys % 10) == 0) { /* Status every 10 sec */
sim_printf ("Waiting for console Telnet connection\r\n"); sim_printf ("Waiting for console Telnet connection\r\n");
fflush (stdout); fflush (stdout);
if (sim_log) /* log file? */ if (sim_log) /* log file? */
@ -1549,12 +1738,13 @@ int32 c;
if (sim_send_poll_data (&sim_con_send, &c)) /* injected input characters available? */ if (sim_send_poll_data (&sim_con_send, &c)) /* injected input characters available? */
return c; return c;
c = sim_os_poll_kbd (); /* get character */ if (!sim_rem_master_mode) {
if ((c == SCPE_STOP) || /* ^E or not Telnet? */ c = sim_os_poll_kbd (); /* get character */
if ((c == SCPE_STOP) || /* ^E or not Telnet? */
((sim_con_tmxr.master == 0) && /* and not serial? */ ((sim_con_tmxr.master == 0) && /* and not serial? */
(sim_con_ldsc.serport == 0))) (sim_con_ldsc.serport == 0)))
return c; /* in-window */ return c; /* in-window */
if (!sim_con_ldsc.conn) { /* no telnet or serial connection? */ if (!sim_con_ldsc.conn) { /* no telnet or serial connection? */
if (!sim_con_ldsc.txbfd) /* unbuffered? */ if (!sim_con_ldsc.txbfd) /* unbuffered? */
return SCPE_LOST; /* connection lost */ return SCPE_LOST; /* connection lost */
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */ if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */
@ -1562,6 +1752,7 @@ if (!sim_con_ldsc.conn) { /* no telnet or serial c
else /* fall through to poll reception */ else /* fall through to poll reception */
return SCPE_OK; /* unconnected and buffered - nothing to receive */ return SCPE_OK; /* unconnected and buffered - nothing to receive */
} }
}
tmxr_poll_rx (&sim_con_tmxr); /* poll for input */ tmxr_poll_rx (&sim_con_tmxr); /* poll for input */
if ((c = tmxr_getc_ln (&sim_con_ldsc))) /* any char? */ if ((c = tmxr_getc_ln (&sim_con_ldsc))) /* any char? */
return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG; return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG;
@ -1579,8 +1770,6 @@ if ((sim_con_tmxr.master == 0) && /* not Telnet? */
fputc (c, sim_log); fputc (c, sim_log);
return sim_os_putchar (c); /* in-window version */ return sim_os_putchar (c); /* in-window version */
} }
if (sim_log && !sim_con_ldsc.txlog) /* log file, but no line log? */
fputc (c, sim_log);
if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */ if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */
if (!sim_con_ldsc.txbfd) /* unbuffered? */ if (!sim_con_ldsc.txbfd) /* unbuffered? */
return SCPE_LOST; /* connection lost */ return SCPE_LOST; /* connection lost */
@ -1603,8 +1792,6 @@ if ((sim_con_tmxr.master == 0) && /* not Telnet? */
fputc (c, sim_log); fputc (c, sim_log);
return sim_os_putchar (c); /* in-window version */ return sim_os_putchar (c); /* in-window version */
} }
if (sim_log && !sim_con_ldsc.txlog) /* log file, but no line log? */
fputc (c, sim_log);
if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */ if (!sim_con_ldsc.conn) { /* no Telnet or serial connection? */
if (!sim_con_ldsc.txbfd) /* non-buffered Telnet connection? */ if (!sim_con_ldsc.txbfd) /* non-buffered Telnet connection? */
return SCPE_LOST; /* lost */ return SCPE_LOST; /* lost */