REMOTE_CONSOLE: reorganized code to use array of structs

The original model started with two array variables each with one element
for each potential concurrent remote console.  As functionality was added
the number of arrays grew to an unreasonable number.  This change
merely gets rid of the separate arrays of per connection info and uses a
single array of REMOTE struct which contains all the per connection info.
This will make future functional extensions much cleaner.
This commit is contained in:
Mark Pizzolato 2017-01-31 21:09:49 -08:00
parent 724b23844c
commit 0913edb2f3

View file

@ -463,16 +463,25 @@ DEVICE sim_remote_console = {
NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL, NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL,
NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug, NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug,
NULL, NULL, NULL, NULL, NULL, sim_rem_con_description}; NULL, NULL, NULL, NULL, NULL, sim_rem_con_description};
static int32 *sim_rem_buf_size = NULL;
static int32 *sim_rem_buf_ptr = NULL; typedef struct REMOTE REMOTE;
static char **sim_rem_buf = NULL; struct REMOTE {
static char **sim_rem_act_buf = NULL; int32 buf_size;
static size_t *sim_rem_act_buf_size = NULL; int32 buf_ptr;
static char **sim_rem_act = NULL; char *buf;
static uint32 *sim_rem_repeat_interval = NULL; char *act_buf;
static t_bool *sim_rem_repeat_pending = NULL; size_t act_buf_size;
static char **sim_rem_repeat_action = NULL; char *act;
static t_bool *sim_rem_single_mode = NULL; /* per line command mode (single command or must continue) */ uint32 repeat_interval;
t_bool repeat_pending;
char *repeat_action;
t_bool single_mode;
uint32 read_timeout;
int line;
TMLN *lp;
UNIT *uptr;
};
REMOTE *sim_rem_consoles = NULL;
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 uint32 *sim_rem_read_timeouts = NULL;/* per line read timeout (default from sim_rem_read_timeout) */
@ -518,7 +527,7 @@ return SCPE_OK;
t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
{ {
int32 i, connections; int32 i, connections;
TMLN *lp; REMOTE *rem;
if (*cptr != 0) if (*cptr != 0)
return SCPE_NOPARAM; return SCPE_NOPARAM;
@ -539,22 +548,22 @@ else {
fprintf (st, "Remote Console Per Command Output buffer size: %d bytes\n", sim_rem_con_tmxr.buffered); fprintf (st, "Remote Console Per Command Output buffer size: %d bytes\n", sim_rem_con_tmxr.buffered);
} }
for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) { for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
lp = &sim_rem_con_tmxr.ldsc[i]; rem = &sim_rem_consoles[i];
if (!lp->conn) if (!rem->lp->conn)
continue; continue;
++connections; ++connections;
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, rem->lp, i);
if (sim_rem_read_timeouts[i] != sim_rem_read_timeout) { if (rem->read_timeout != sim_rem_read_timeout) {
if (sim_rem_read_timeouts[i]) if (rem->read_timeout)
fprintf (st, "Remote Console Input on connection %d automatically continues after %d seconds\n", i, sim_rem_read_timeouts[i]); fprintf (st, "Remote Console Input on connection %d automatically continues after %d seconds\n", i, rem->read_timeout);
else else
fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i); fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i);
} }
if (sim_rem_repeat_action[i]) { if (rem->repeat_action) {
fprintf (st, "The Command: %s\n", sim_rem_repeat_action[i]); fprintf (st, "The Command: %s\n", rem->repeat_action);
fprintf (st, " is repeated every %s\n", sim_fmt_secs (sim_rem_repeat_interval[i] / 1000000.0)); fprintf (st, " is repeated every %s\n", sim_fmt_secs (rem->repeat_interval / 1000000.0));
} }
} }
return SCPE_OK; return SCPE_OK;
@ -568,14 +577,15 @@ int32 c;
c = tmxr_poll_conn (&sim_rem_con_tmxr); c = tmxr_poll_conn (&sim_rem_con_tmxr);
if (c >= 0) { /* poll connect */ if (c >= 0) { /* poll connect */
TMLN *lp = &sim_rem_con_tmxr.ldsc[c]; REMOTE *rem = &sim_rem_consoles[c];
TMLN *lp = rem->lp;
char wru_name[8]; char wru_name[8];
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 */ rem->buf_ptr = 0; /* start with empty command buffer */
sim_rem_single_mode[c] = TRUE; /* start in single command mode */ rem->single_mode = TRUE; /* start in single command mode */
sim_rem_read_timeouts[c] = sim_rem_read_timeout; /* Start with default timeout */ rem->read_timeout = 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
@ -589,7 +599,7 @@ if (c >= 0) { /* poll connect */
sim_name, wru_name, sim_name, wru_name,
((sim_rem_master_mode && (c == 0)) ? "" : "\nSimulator Running...")); ((sim_rem_master_mode && (c == 0)) ? "" : "\nSimulator Running..."));
if (sim_rem_master_mode && (c == 0)) /* Master Mode session? */ if (sim_rem_master_mode && (c == 0)) /* Master Mode session? */
sim_rem_single_mode[c] = FALSE; /* start in multi-command mode */ rem->single_mode = 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 */
@ -739,7 +749,8 @@ return stat;
static void _sim_rem_log_out (TMLN *lp) static void _sim_rem_log_out (TMLN *lp)
{ {
char cbuf[4*CBUFSIZE]; char cbuf[4*CBUFSIZE];
int line = (int)(lp - sim_rem_con_tmxr.ldsc); REMOTE *rem = &sim_rem_consoles[(int)(lp - sim_rem_con_tmxr.ldsc)];
int line = rem->line;
if ((!sim_oline) && (sim_log)) { if ((!sim_oline) && (sim_log)) {
fflush (sim_log); fflush (sim_log);
@ -749,7 +760,7 @@ if ((!sim_oline) && (sim_log)) {
tmxr_linemsgf (lp, "%s", cbuf); tmxr_linemsgf (lp, "%s", cbuf);
} }
sim_oline = NULL; sim_oline = NULL;
if ((sim_rem_act[line] == NULL) && if ((rem->act == NULL) &&
(!tmxr_input_pending_ln (lp))) { (!tmxr_input_pending_ln (lp))) {
int32 unwritten; int32 unwritten;
@ -795,10 +806,10 @@ sim_switches = saved_switches; /* restore original switches */
static char *sim_rem_clract (int32 line) static char *sim_rem_clract (int32 line)
{ {
TMLN *lp = &sim_rem_con_tmxr.ldsc[line]; REMOTE *rem = &sim_rem_consoles[line];
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (rem->lp); /* flush any buffered data */
return sim_rem_act[line] = NULL; return rem->act = NULL;
} }
/* Set up pending actions */ /* Set up pending actions */
@ -807,13 +818,14 @@ static void sim_rem_setact (int32 line, const char *action)
{ {
if (action) { if (action) {
size_t act_size = strlen (action) + 1; size_t act_size = strlen (action) + 1;
REMOTE *rem = &sim_rem_consoles[line];
if (act_size > sim_rem_act_buf_size[line]) {/* expand buffer if necessary */ if (act_size > rem->act_buf_size) { /* expand buffer if necessary */
sim_rem_act_buf[line] = (char *)realloc (sim_rem_act_buf[line], act_size); rem->act_buf = (char *)realloc (rem->act_buf, act_size);
sim_rem_act_buf_size[line] = act_size; rem->act_buf_size = act_size;
} }
strcpy (sim_rem_act_buf[line], action); /* populate buffer */ strcpy (rem->act_buf, action); /* populate buffer */
sim_rem_act[line] = sim_rem_act_buf[line]; /* start at beginning of buffer */ rem->act = rem->act_buf; /* start at beginning of buffer */
} }
else else
sim_rem_clract (line); sim_rem_clract (line);
@ -825,22 +837,23 @@ static char *sim_rem_getact (int32 line, char *buf, int32 size)
{ {
char *ep; char *ep;
size_t lnt; size_t lnt;
REMOTE *rem = &sim_rem_consoles[line];
if (sim_rem_act[line] == NULL) /* any action? */ if (rem->act == NULL) /* any action? */
return NULL; return NULL;
while (sim_isspace (*sim_rem_act[line])) /* skip spaces */ while (sim_isspace (*rem->act)) /* skip spaces */
sim_rem_act[line]++; rem->act++;
if (*sim_rem_act[line] == 0) /* now empty? */ if (*rem->act == 0) /* now empty? */
return sim_rem_clract (line); return sim_rem_clract (line);
if ((ep = strchr (sim_rem_act[line], ';'))) { /* cmd delimiter? */ if ((ep = strchr (rem->act, ';'))) { /* cmd delimiter? */
lnt = ep - sim_rem_act[line]; /* cmd length */ lnt = ep - rem->act; /* cmd length */
memcpy (buf, sim_rem_act[line], lnt + 1); /* copy with ; */ memcpy (buf, rem->act, lnt + 1); /* copy with ; */
buf[lnt] = 0; /* erase ; */ buf[lnt] = 0; /* erase ; */
sim_rem_act[line] += lnt + 1; /* adv ptr */ rem->act += lnt + 1; /* adv ptr */
} }
else { else {
strncpy (buf, sim_rem_act[line], size); /* copy action */ strncpy (buf, rem->act, size); /* copy action */
sim_rem_act[line] += strlen (sim_rem_act[line]);/* adv ptr to end */ rem->act += strlen (rem->act); /* adv ptr to end */
} }
return buf; return buf;
} }
@ -856,6 +869,7 @@ int32 val;
t_bool all_stop = FALSE; t_bool all_stop = FALSE;
t_stat stat = SCPE_OK; t_stat stat = SCPE_OK;
CONST char *cptr = *iptr; CONST char *cptr = *iptr;
REMOTE *rem = &sim_rem_consoles[line];
sim_debug (DBG_REP, &sim_remote_console, "Repeat Setup: %s\n", cptr); sim_debug (DBG_REP, &sim_remote_console, "Repeat Setup: %s\n", cptr);
if (*cptr == 0) /* required argument? */ if (*cptr == 0) /* required argument? */
@ -872,7 +886,7 @@ else {
if ((MATCH_CMD (gbuf, "USECS") != 0) || (*cptr == 0)) if ((MATCH_CMD (gbuf, "USECS") != 0) || (*cptr == 0))
stat = SCPE_ARG; stat = SCPE_ARG;
else else
sim_rem_repeat_interval[line] = val; rem->repeat_interval = val;
} }
} }
else { else {
@ -887,7 +901,7 @@ else {
all_stop = TRUE; all_stop = TRUE;
} }
else else
sim_rem_repeat_interval[line] = 0; rem->repeat_interval = 0;
} }
else else
stat = SCPE_ARG; stat = SCPE_ARG;
@ -896,26 +910,27 @@ else {
if (stat == SCPE_OK) { if (stat == SCPE_OK) {
if (all_stop) { if (all_stop) {
for (line = 0; line < sim_rem_con_tmxr.lines; line++) { for (line = 0; line < sim_rem_con_tmxr.lines; line++) {
free (sim_rem_repeat_action[line]); rem = &sim_rem_consoles[line];
sim_rem_repeat_action[line] = NULL; free (rem->repeat_action);
sim_cancel (&sim_rem_con_unit[line + 2]); rem->repeat_action = NULL;
sim_rem_repeat_pending[line] = FALSE; sim_cancel (rem->uptr);
rem->repeat_pending = FALSE;
sim_rem_clract (line); sim_rem_clract (line);
} }
} }
else { else {
if (sim_rem_repeat_interval[line] != 0) { if (rem->repeat_interval != 0) {
sim_rem_repeat_action[line] = (char *)realloc (sim_rem_repeat_action[line], 1 + strlen (cptr)); rem->repeat_action = (char *)realloc (rem->repeat_action, 1 + strlen (cptr));
strcpy (sim_rem_repeat_action[line], cptr); strcpy (rem->repeat_action, cptr);
cptr += strlen (cptr); cptr += strlen (cptr);
stat = sim_activate_after (&sim_rem_con_unit[line + 2], sim_rem_repeat_interval[line]); stat = sim_activate_after (rem->uptr, rem->repeat_interval);
} }
else { else {
free (sim_rem_repeat_action[line]); free (rem->repeat_action);
sim_rem_repeat_action[line] = NULL; rem->repeat_action = NULL;
sim_cancel (&sim_rem_con_unit[line + 2]); sim_cancel (rem->uptr);
} }
sim_rem_repeat_pending[line] = FALSE; rem->repeat_pending = FALSE;
sim_rem_clract (line); sim_rem_clract (line);
} }
} }
@ -945,11 +960,12 @@ tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
for (i=(was_active_command ? sim_rem_cmd_active_line : 0); 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);
i++) { i++) {
REMOTE *rem = &sim_rem_consoles[i];
t_bool master_session = (sim_rem_master_mode && (i == 0)); t_bool master_session = (sim_rem_master_mode && (i == 0));
lp = &sim_rem_con_tmxr.ldsc[i]; lp = rem->lp;
if (!lp->conn) { if (!lp->conn) {
if (sim_rem_repeat_interval[i]) { /* was repeated enabled? */ if (rem->repeat_interval) { /* was repeated enabled? */
cptr = strcpy (gbuf, "STOP"); cptr = strcpy (gbuf, "STOP");
_rem_repeat_cmd_setup (i, &cptr); /* make sure it is now disabled */ _rem_repeat_cmd_setup (i, &cptr); /* make sure it is now disabled */
} }
@ -962,8 +978,8 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
sim_rem_master_was_connected |= master_session; /* Remember if master ever connected */ sim_rem_master_was_connected |= master_session; /* Remember if master ever connected */
stat = SCPE_OK; stat = SCPE_OK;
if ((was_active_command) || if ((was_active_command) ||
(master_session && !sim_rem_single_mode[i])) { (master_session && !rem->single_mode)) {
sim_debug (DBG_MOD, &sim_remote_console, "Session: %d %s %s\n", i, was_active_command ? "Was Active" : "", (master_session && !sim_rem_single_mode[i]) ? "master_session && !sim_rem_single_mode[i]" : ""); sim_debug (DBG_MOD, &sim_remote_console, "Session: %d %s %s\n", i, was_active_command ? "Was Active" : "", (master_session && !rem->single_mode) ? "master_session && !single_mode" : "");
if (was_active_command) { if (was_active_command) {
sim_rem_cmd_active_line = -1; /* Done with active command */ sim_rem_cmd_active_line = -1; /* Done with active command */
if (!sim_rem_active_command) { /* STEP command? */ if (!sim_rem_active_command) { /* STEP command? */
@ -989,14 +1005,14 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
} }
} }
else { else {
if ((!sim_rem_repeat_pending[i]) || (sim_rem_buf_ptr[i] != 0)) { if ((!rem->repeat_pending) || (rem->buf_ptr != 0)) {
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 (rem->single_mode) {
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 */ rem->single_mode = FALSE; /* enter multi command mode */
sim_is_running = 0; sim_is_running = 0;
sim_stop_timer_services (); sim_stop_timer_services ();
stat = SCPE_STOP; stat = SCPE_STOP;
@ -1012,14 +1028,14 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
lp = &sim_rem_con_tmxr.ldsc[i]; lp = &sim_rem_con_tmxr.ldsc[i];
if (!master_session) if (!master_session)
tmxr_linemsg (lp, "\r\nSimulator paused.\r\n"); tmxr_linemsg (lp, "\r\nSimulator paused.\r\n");
if (!master_session && sim_rem_read_timeouts[i]) { if (!master_session && 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, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeouts[i]);
tmxr_linemsgf (lp, "\r\n"); tmxr_linemsgf (lp, "\r\n");
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (lp); /* flush any buffered data */
} }
} }
else { else {
if ((sim_rem_buf_ptr[i] == 0) && /* At beginning of input line */ if ((rem->buf_ptr == 0) && /* At beginning of input line */
((c == '\n') || /* Ignore bare LF between commands (Microsoft Telnet bug) */ ((c == '\n') || /* Ignore bare LF between commands (Microsoft Telnet bug) */
(c == '\r'))) /* Ignore empty commands */ (c == '\r'))) /* Ignore empty commands */
continue; continue;
@ -1029,14 +1045,14 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
tmxr_reset_ln (lp); tmxr_reset_ln (lp);
continue; continue;
} }
if (sim_rem_buf_ptr[i] == 0) { if (rem->buf_ptr == 0) {
/* we just picked up the first character on a command line */ /* we just picked up the first character on a command line */
if (!master_session) if (!master_session)
tmxr_linemsgf (lp, "\r\n%s", sim_prompt); tmxr_linemsgf (lp, "\r\n%s", sim_prompt);
else else
tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> "); 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> "); sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> ");
if ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp))) if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp)))
tmxr_send_buffered_data (lp);/* flush any buffered data */ tmxr_send_buffered_data (lp);/* flush any buffered data */
} }
} }
@ -1047,7 +1063,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
while (1) { while (1) {
if (stat == SCPE_EXIT) if (stat == SCPE_EXIT)
return stat|SCPE_NOMESSAGE; return stat|SCPE_NOMESSAGE;
if (!sim_rem_single_mode[i]) { if (!rem->single_mode) {
read_start_time = sim_os_msec(); read_start_time = sim_os_msec();
if (master_session) if (master_session)
tmxr_linemsg (lp, "sim> "); tmxr_linemsg (lp, "sim> ");
@ -1056,55 +1072,55 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (lp); /* flush any buffered data */
} }
do { do {
if (sim_rem_buf_ptr[i] == 0) { if (rem->buf_ptr == 0) {
if (sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i])) { if (sim_rem_getact (i, rem->buf, rem->buf_size)) {
if (!master_session) if (!master_session)
tmxr_linemsgf (lp, "%s%s\n", sim_prompt, sim_rem_buf[i]); tmxr_linemsgf (lp, "%s%s\n", sim_prompt, rem->buf);
else else
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]); tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", rem->buf);
sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]); rem->buf_ptr = strlen (rem->repeat_action);
got_command = TRUE; got_command = TRUE;
break; break;
} }
else { else {
if (sim_rem_repeat_pending[i]) { if (rem->repeat_pending) {
sim_rem_repeat_pending[i] = FALSE; rem->repeat_pending = FALSE;
sim_rem_setact (i, sim_rem_repeat_action[i]); sim_rem_setact (i, rem->repeat_action);
sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i]); sim_rem_getact (i, rem->buf, rem->buf_size);
if (!master_session) if (!master_session)
tmxr_linemsgf (lp, "%s%s\n", sim_prompt, sim_rem_buf[i]); tmxr_linemsgf (lp, "%s%s\n", sim_prompt, rem->buf);
else else
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]); tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", rem->buf);
sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]); rem->buf_ptr = strlen (rem->repeat_action);
got_command = TRUE; got_command = TRUE;
break; break;
} }
} }
} }
if (!sim_rem_single_mode[i]) { if (!rem->single_mode) {
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 (!master_session && if (!master_session &&
sim_rem_read_timeouts[i] && rem->read_timeout &&
((sim_os_msec() - read_start_time)/1000 >= sim_rem_read_timeouts[i])) { ((sim_os_msec() - read_start_time)/1000 >= rem->read_timeout)) {
while (sim_rem_buf_ptr[i] > 0) {/* Erase current input line */ while (rem->buf_ptr > 0) { /* Erase current input line */
tmxr_linemsg (lp, "\b \b"); tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i]; --rem->buf_ptr;
} }
if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) { if (rem->buf_ptr+80 >= rem->buf_size) {
sim_rem_buf_size[i] += 1024; rem->buf_size += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]); rem->buf = (char *)realloc (rem->buf, rem->buf_size);
} }
strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue due to timeout"); strcpy (rem->buf, "CONTINUE ! Automatic continue due to timeout");
tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]); tmxr_linemsgf (lp, "%s\n", rem->buf);
got_command = TRUE; got_command = TRUE;
break; break;
} }
sim_os_ms_sleep (50); sim_os_ms_sleep (50);
tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */ tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
if (!lp->conn) { /* if connection lost? */ if (!lp->conn) { /* if connection lost? */
sim_rem_single_mode[i] = TRUE; /* No longer multi-command more */ rem->single_mode = TRUE; /* No longer multi-command more */
break; /* done waiting */ break; /* done waiting */
} }
continue; continue;
@ -1117,88 +1133,88 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
break; break;
case '\b': /* Backspace */ case '\b': /* Backspace */
case 127: /* Rubout */ case 127: /* Rubout */
if (sim_rem_buf_ptr[i] > 0) { if (rem->buf_ptr > 0) {
tmxr_linemsg (lp, "\b \b"); tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i]; --rem->buf_ptr;
} }
break; break;
case 27: /* escape */ case 27: /* escape */
case 21: /* ^U */ case 21: /* ^U */
while (sim_rem_buf_ptr[i] > 0) { while (rem->buf_ptr > 0) {
tmxr_linemsg (lp, "\b \b"); tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i]; --rem->buf_ptr;
} }
break; break;
case '\n': case '\n':
if (sim_rem_buf_ptr[i] == 0) if (rem->buf_ptr == 0)
break; break;
case '\r': case '\r':
tmxr_linemsg (lp, "\r\n"); tmxr_linemsg (lp, "\r\n");
if (sim_rem_buf_ptr[i]+1 >= sim_rem_buf_size[i]) { if (rem->buf_ptr+1 >= rem->buf_size) {
sim_rem_buf_size[i] += 1024; rem->buf_size += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]); rem->buf = (char *)realloc (rem->buf, rem->buf_size);
} }
sim_rem_buf[i][sim_rem_buf_ptr[i]++] = '\0'; rem->buf[rem->buf_ptr++] = '\0';
sim_debug (DBG_RCV, &sim_remote_console, "Got Command (%d bytes still in buffer): %s\n", tmxr_input_pending_ln (lp), sim_rem_buf[i]); sim_debug (DBG_RCV, &sim_remote_console, "Got Command (%d bytes still in buffer): %s\n", tmxr_input_pending_ln (lp), rem->buf);
got_command = TRUE; got_command = TRUE;
break; break;
case '\004': /* EOF (^D) */ case '\004': /* EOF (^D) */
case '\032': /* EOF (^Z) */ case '\032': /* EOF (^Z) */
while (sim_rem_buf_ptr[i] > 0) { /* Erase current input line */ while (rem->buf_ptr > 0) { /* Erase current input line */
tmxr_linemsg (lp, "\b \b"); tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i]; --rem->buf_ptr;
} }
if (!sim_rem_single_mode[i]) { if (!rem->single_mode) {
if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) { if (rem->buf_ptr+80 >= rem->buf_size) {
sim_rem_buf_size[i] += 1024; rem->buf_size += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]); rem->buf = (char *)realloc (rem->buf, rem->buf_size);
} }
strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue before close"); strcpy (rem->buf, "CONTINUE ! Automatic continue before close");
tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]); tmxr_linemsgf (lp, "%s\n", rem->buf);
got_command = TRUE; got_command = TRUE;
} }
close_session = TRUE; close_session = TRUE;
break; break;
default: default:
tmxr_putc_ln (lp, c); tmxr_putc_ln (lp, c);
if (sim_rem_buf_ptr[i]+2 >= sim_rem_buf_size[i]) { if (rem->buf_ptr+2 >= rem->buf_size) {
sim_rem_buf_size[i] += 1024; rem->buf_size += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]); rem->buf = (char *)realloc (rem->buf, rem->buf_size);
} }
sim_rem_buf[i][sim_rem_buf_ptr[i]++] = (char)c; rem->buf[rem->buf_ptr++] = (char)c;
sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0'; rem->buf[rem->buf_ptr] = '\0';
if (((size_t)sim_rem_buf_ptr[i]) >= sizeof(cbuf)) if (((size_t)rem->buf_ptr) >= sizeof(cbuf))
got_command = TRUE; /* command too long */ got_command = TRUE; /* command too long */
break; break;
} }
c = 0; c = 0;
if ((!got_command) && (sim_rem_single_mode[i]) && (tmxr_input_pending_ln (lp))) { if ((!got_command) && (rem->single_mode) && (tmxr_input_pending_ln (lp))) {
c = tmxr_getc_ln (lp); c = tmxr_getc_ln (lp);
c = c & ~TMXR_VALID; c = c & ~TMXR_VALID;
} }
} while ((!got_command) && ((!sim_rem_single_mode[i]) || c)); } while ((!got_command) && ((!rem->single_mode) || c));
if ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp))) if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp)))
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (lp); /* flush any buffered data */
if ((sim_rem_single_mode[i]) && !got_command) { if ((rem->single_mode) && !got_command) {
break; break;
} }
if (!sim_rem_master_mode) if (!sim_rem_master_mode)
sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]); sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, rem->buf);
got_command = FALSE; got_command = FALSE;
if (strlen(sim_rem_buf[i]) >= sizeof(cbuf)) { if (strlen(rem->buf) >= sizeof(cbuf)) {
sim_printf ("\r\nLine too long. Ignored. Continuing Simulator execution\r\n"); sim_printf ("\r\nLine too long. Ignored. Continuing Simulator execution\r\n");
tmxr_linemsgf (lp, "\nLine too long. Ignored. Continuing Simulator execution\n"); tmxr_linemsgf (lp, "\nLine too long. Ignored. Continuing Simulator execution\n");
tmxr_send_buffered_data (lp); /* try to flush any buffered data */ tmxr_send_buffered_data (lp); /* try to flush any buffered data */
break; break;
} }
strcpy (cbuf, sim_rem_buf[i]); strcpy (cbuf, rem->buf);
sim_rem_buf_ptr[i] = 0; rem->buf_ptr = 0;
sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0'; rem->buf[rem->buf_ptr] = '\0';
while (isspace(cbuf[0])) while (isspace(cbuf[0]))
memmove (cbuf, cbuf+1, strlen(cbuf+1)+1); /* skip leading whitespace */ memmove (cbuf, cbuf+1, strlen(cbuf+1)+1); /* skip leading whitespace */
if (cbuf[0] == '\0') { if (cbuf[0] == '\0') {
if (sim_rem_single_mode[i]) { if (rem->single_mode) {
sim_rem_single_mode[i] = FALSE; rem->single_mode = FALSE;
break; break;
} }
else else
@ -1235,7 +1251,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
stat = SCPE_UNK; stat = SCPE_UNK;
} }
else { else {
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 = find_ctab (rem->single_mode ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {/* lookup command */
sim_debug (DBG_CMD, &sim_remote_console, "gbuf='%s', basecmd='%s', cmd='%s', action=%p, continue_cmd=%p, repeat_cmd=%p\n", gbuf, basecmdp->name, cmdp->name, cmdp->action, &x_continue_cmd, &x_repeat_cmd); sim_debug (DBG_CMD, &sim_remote_console, "gbuf='%s', basecmd='%s', cmd='%s', action=%p, continue_cmd=%p, repeat_cmd=%p\n", gbuf, basecmdp->name, cmdp->name, cmdp->action, &x_continue_cmd, &x_repeat_cmd);
if (cmdp->action == &x_continue_cmd) { if (cmdp->action == &x_continue_cmd) {
sim_debug (DBG_CMD, &sim_remote_console, "continue_cmd executing\n"); sim_debug (DBG_CMD, &sim_remote_console, "continue_cmd executing\n");
@ -1305,7 +1321,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
stat = _sim_rem_message (gbuf, stat); stat = _sim_rem_message (gbuf, stat);
_sim_rem_log_out (lp); _sim_rem_log_out (lp);
if (master_session && !sim_rem_master_mode) { if (master_session && !sim_rem_master_mode) {
sim_rem_single_mode[i] = TRUE; rem->single_mode = TRUE;
return SCPE_STOP; return SCPE_STOP;
} }
if (cmdp && (cmdp->action == &x_continue_cmd)) { if (cmdp && (cmdp->action == &x_continue_cmd)) {
@ -1324,7 +1340,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
fflush (sim_log); fflush (sim_log);
sim_rem_cmd_log_start = sim_ftell (sim_log); sim_rem_cmd_log_start = sim_ftell (sim_log);
} }
if (!sim_rem_single_mode[i]) { if (!rem->single_mode) {
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++) {
@ -1338,9 +1354,9 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
sim_start_timer_services (); sim_start_timer_services ();
} }
if (cmdp && (cmdp->action == &x_continue_cmd)) if (cmdp && (cmdp->action == &x_continue_cmd))
sim_rem_single_mode[i] = TRUE; rem->single_mode = TRUE;
else { else {
if (!sim_rem_single_mode[i]) { if (!rem->single_mode) {
if (master_session) if (master_session)
tmxr_linemsgf (lp, "%s", "sim> "); tmxr_linemsgf (lp, "%s", "sim> ");
else else
@ -1360,7 +1376,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
tmxr_linemsgf (lp, "\r\nGoodbye\r\n"); tmxr_linemsgf (lp, "\r\nGoodbye\r\n");
tmxr_send_buffered_data (lp); /* flush any buffered data */ tmxr_send_buffered_data (lp); /* flush any buffered data */
tmxr_reset_ln (lp); tmxr_reset_ln (lp);
sim_rem_single_mode[i] = FALSE; rem->single_mode = FALSE;
} }
} }
if (sim_rem_master_was_connected && /* Master mode ever connected? */ if (sim_rem_master_was_connected && /* Master mode ever connected? */
@ -1387,11 +1403,12 @@ else
t_stat sim_rem_con_repeat_svc (UNIT *uptr) t_stat sim_rem_con_repeat_svc (UNIT *uptr)
{ {
int line = uptr - (sim_rem_con_unit + 2); int line = uptr - (sim_rem_con_unit + 2);
REMOTE *rem = &sim_rem_consoles[line];
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, sim_rem_repeat_interval[line]); sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, rem->repeat_interval);
if (sim_rem_repeat_interval[line]) { if (rem->repeat_interval) {
sim_rem_repeat_pending[line] = TRUE; rem->repeat_pending = TRUE;
sim_activate_after (uptr, sim_rem_repeat_interval[line]); /* reschedule */ sim_activate_after (uptr, rem->repeat_interval); /* reschedule */
sim_activate_abs (&sim_rem_con_unit[1], -1); /* wake up to process */ sim_activate_abs (&sim_rem_con_unit[1], -1); /* wake up to process */
} }
return SCPE_OK; return SCPE_OK;
@ -1408,11 +1425,13 @@ if (sim_rem_con_tmxr.lines) {
sim_rem_con_unit[i + 2].action = &sim_rem_con_repeat_svc; sim_rem_con_unit[i + 2].action = &sim_rem_con_repeat_svc;
} }
for (i=0; i<sim_rem_con_tmxr.lines; i++) { for (i=0; i<sim_rem_con_tmxr.lines; i++) {
REMOTE *rem = &sim_rem_consoles[i];
if (!sim_rem_con_tmxr.ldsc[i].conn) if (!sim_rem_con_tmxr.ldsc[i].conn)
continue; continue;
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, sim_rem_repeat_interval[i]); sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, rem->repeat_interval);
if (sim_rem_repeat_interval[i]) if (rem->repeat_interval)
sim_activate_after (sim_rem_con_unit + 2 + i, sim_rem_repeat_interval[i]);/* schedule */ sim_activate_after (sim_rem_con_unit + 2 + i, rem->repeat_interval);/* schedule */
} }
if (i != sim_rem_con_tmxr.lines) if (i != sim_rem_con_tmxr.lines)
sim_activate_after (&dptr->units[1], 100000); /* continue polling for open sessions */ sim_activate_after (&dptr->units[1], 100000); /* continue polling for open sessions */
@ -1447,11 +1466,12 @@ else {
tmxr_detach (&sim_rem_con_tmxr, &sim_rem_con_unit[0]); tmxr_detach (&sim_rem_con_tmxr, &sim_rem_con_unit[0]);
for (i=0; i<sim_rem_con_tmxr.lines; i++) { for (i=0; i<sim_rem_con_tmxr.lines; i++) {
free (sim_rem_buf[i]); REMOTE *rem = &sim_rem_consoles[i];
sim_rem_buf[i] = NULL; free (rem->buf);
sim_rem_buf_size[i] = 0; rem->buf = NULL;
sim_rem_buf_ptr[i] = 0; rem->buf_size = 0;
sim_rem_single_mode[i] = TRUE; rem->buf_ptr = 0;
rem->single_mode = TRUE;
} }
} }
} }
@ -1461,6 +1481,7 @@ return SCPE_OK;
static t_stat sim_set_rem_connections (int32 flag, CONST char *cptr) static t_stat sim_set_rem_connections (int32 flag, CONST char *cptr)
{ {
int32 lines; int32 lines;
REMOTE *rem;
t_stat r; t_stat r;
int32 i; int32 i;
@ -1470,36 +1491,27 @@ lines = (int32) get_uint (cptr, 10, MAX_REMOTE_SESSIONS, &r);
if (r != SCPE_OK) if (r != SCPE_OK)
return r; return r;
if (sim_rem_con_tmxr.master) if (sim_rem_con_tmxr.master)
return SCPE_ARG; return SCPE_ALATT;
for (i=0; i<sim_rem_con_tmxr.lines; i++) for (i=0; i<sim_rem_con_tmxr.lines; i++) {
free (sim_rem_buf[i]); rem = &sim_rem_consoles[i];
free (rem->buf);
free (rem->act_buf);
free (rem->act);
free (rem->repeat_action);
}
sim_rem_con_tmxr.lines = lines; sim_rem_con_tmxr.lines = lines;
sim_rem_con_tmxr.ldsc = (TMLN *)realloc (sim_rem_con_tmxr.ldsc, sizeof(*sim_rem_con_tmxr.ldsc)*lines); sim_rem_con_tmxr.ldsc = (TMLN *)realloc (sim_rem_con_tmxr.ldsc, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines); memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
sim_rem_buf = (char **)realloc (sim_rem_buf, sizeof(*sim_rem_buf)*lines); sim_rem_consoles = (REMOTE *)realloc (sim_rem_consoles, sizeof(*sim_rem_consoles)*lines);
memset (sim_rem_buf, 0, sizeof(*sim_rem_buf)*lines); memset (sim_rem_consoles, 0, sizeof(*sim_rem_consoles)*lines);
sim_rem_act_buf = (char **)realloc (sim_rem_act_buf, sizeof(*sim_rem_act_buf)*lines);
memset (sim_rem_act_buf, 0, sizeof(*sim_rem_act_buf)*lines);
sim_rem_act_buf_size = (size_t *)realloc (sim_rem_act_buf_size, sizeof(*sim_rem_act_buf_size)*lines);
memset (sim_rem_act_buf_size, 0, sizeof(*sim_rem_act_buf_size)*lines);
sim_rem_act = (char **)realloc (sim_rem_act, sizeof(*sim_rem_act)*lines);
memset (sim_rem_act, 0, sizeof(*sim_rem_act)*lines);
sim_rem_buf_size = (int32 *)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 = (int32 *)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_repeat_interval = (uint32 *)realloc (sim_rem_repeat_interval, sizeof(*sim_rem_repeat_interval)*lines);
memset (sim_rem_repeat_interval, 0, sizeof(*sim_rem_repeat_interval)*lines);
sim_rem_repeat_pending = (t_bool *)realloc (sim_rem_repeat_pending, sizeof(*sim_rem_repeat_pending)*lines);
memset (sim_rem_repeat_pending, 0, sizeof(*sim_rem_repeat_pending)*lines);
sim_rem_repeat_action = (char **)realloc (sim_rem_repeat_action, sizeof(*sim_rem_repeat_action)*lines);
memset (sim_rem_repeat_action, 0, sizeof(*sim_rem_repeat_action)*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);
sim_rem_read_timeouts = (uint32 *)realloc (sim_rem_read_timeouts, sizeof(*sim_rem_read_timeouts)*lines);
memset (sim_rem_read_timeouts, 0, sizeof(*sim_rem_read_timeouts)*lines);
sim_rem_command_buf = (char *)realloc (sim_rem_command_buf, 4*CBUFSIZE+1); sim_rem_command_buf = (char *)realloc (sim_rem_command_buf, 4*CBUFSIZE+1);
memset (sim_rem_command_buf, 0, 4*CBUFSIZE+1); memset (sim_rem_command_buf, 0, 4*CBUFSIZE+1);
for (i=0; i<sim_rem_con_tmxr.lines; i++) {
rem = &sim_rem_consoles[i];
rem->line = i;
rem->lp = &sim_rem_con_tmxr.ldsc[i];
rem->uptr = &sim_rem_con_unit[i + 2];
}
return SCPE_OK; return SCPE_OK;
} }
@ -1514,7 +1526,7 @@ timeout = (int32) get_uint (cptr, 10, 3600, &r);
if (r != SCPE_OK) if (r != SCPE_OK)
return r; return r;
if (sim_rem_active_number >= 0) if (sim_rem_active_number >= 0)
sim_rem_read_timeouts[sim_rem_active_number] = timeout; sim_rem_consoles[sim_rem_active_number].read_timeout = timeout;
else else
sim_rem_read_timeout = timeout; sim_rem_read_timeout = timeout;
return SCPE_OK; return SCPE_OK;
@ -1571,7 +1583,7 @@ if (sim_rem_master_mode) {
stat = sim_run_boot_prep (0); stat = sim_run_boot_prep (0);
sim_rem_master_was_enabled = TRUE; sim_rem_master_was_enabled = TRUE;
while (sim_rem_master_mode) { while (sim_rem_master_mode) {
sim_rem_single_mode[0] = FALSE; sim_rem_consoles[0].single_mode = FALSE;
sim_cancel (&sim_rem_con_unit[1]); sim_cancel (&sim_rem_con_unit[1]);
sim_activate (&sim_rem_con_unit[1], -1); sim_activate (&sim_rem_con_unit[1], -1);
stat = run_cmd (RU_GO, ""); stat = run_cmd (RU_GO, "");
@ -1596,9 +1608,8 @@ if (sim_rem_master_mode) {
stat |= stat_nomessage; stat |= stat_nomessage;
} }
else { else {
sim_rem_single_mode[0] = TRUE; /* Force remote session into single command mode */ sim_rem_consoles[0].single_mode = TRUE; /* Force remote session into single command mode */
} }
return stat; return stat;
} }