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, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug,
NULL, NULL, NULL, NULL, NULL, sim_rem_con_description};
static int32 *sim_rem_buf_size = NULL;
static int32 *sim_rem_buf_ptr = NULL;
static char **sim_rem_buf = NULL;
static char **sim_rem_act_buf = NULL;
static size_t *sim_rem_act_buf_size = NULL;
static char **sim_rem_act = NULL;
static uint32 *sim_rem_repeat_interval = NULL;
static t_bool *sim_rem_repeat_pending = NULL;
static char **sim_rem_repeat_action = NULL;
static t_bool *sim_rem_single_mode = NULL; /* per line command mode (single command or must continue) */
typedef struct REMOTE REMOTE;
struct REMOTE {
int32 buf_size;
int32 buf_ptr;
char *buf;
char *act_buf;
size_t act_buf_size;
char *act;
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 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) */
@ -518,7 +527,7 @@ return SCPE_OK;
t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
{
int32 i, connections;
TMLN *lp;
REMOTE *rem;
if (*cptr != 0)
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);
}
for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
lp = &sim_rem_con_tmxr.ldsc[i];
if (!lp->conn)
rem = &sim_rem_consoles[i];
if (!rem->lp->conn)
continue;
++connections;
if (connections == 1)
fprintf (st, "Remote Console Connections:\n");
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]);
tmxr_fconns (st, rem->lp, i);
if (rem->read_timeout != sim_rem_read_timeout) {
if (rem->read_timeout)
fprintf (st, "Remote Console Input on connection %d automatically continues after %d seconds\n", i, rem->read_timeout);
else
fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i);
}
if (sim_rem_repeat_action[i]) {
fprintf (st, "The Command: %s\n", sim_rem_repeat_action[i]);
fprintf (st, " is repeated every %s\n", sim_fmt_secs (sim_rem_repeat_interval[i] / 1000000.0));
if (rem->repeat_action) {
fprintf (st, "The Command: %s\n", rem->repeat_action);
fprintf (st, " is repeated every %s\n", sim_fmt_secs (rem->repeat_interval / 1000000.0));
}
}
return SCPE_OK;
@ -568,14 +577,15 @@ int32 c;
c = tmxr_poll_conn (&sim_rem_con_tmxr);
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];
sim_activate_after(uptr+1, 1000000); /* start data poll after 1 second */
lp->rcve = 1; /* rcv enabled */
sim_rem_buf_ptr[c] = 0; /* start with empty command buffer */
sim_rem_single_mode[c] = TRUE; /* start in single command mode */
sim_rem_read_timeouts[c] = sim_rem_read_timeout; /* Start with default timeout */
rem->buf_ptr = 0; /* start with empty command buffer */
rem->single_mode = TRUE; /* start in single command mode */
rem->read_timeout = sim_rem_read_timeout; /* Start with default timeout */
if (isprint(sim_int_char&0xFF))
sprintf(wru_name, "'%c'", sim_int_char&0xFF);
else
@ -589,7 +599,7 @@ if (c >= 0) { /* poll connect */
sim_name, wru_name,
((sim_rem_master_mode && (c == 0)) ? "" : "\nSimulator Running..."));
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 */
}
sim_activate_after(uptr, 1000000); /* check again in 1 second */
@ -739,7 +749,8 @@ return stat;
static void _sim_rem_log_out (TMLN *lp)
{
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)) {
fflush (sim_log);
@ -749,7 +760,7 @@ if ((!sim_oline) && (sim_log)) {
tmxr_linemsgf (lp, "%s", cbuf);
}
sim_oline = NULL;
if ((sim_rem_act[line] == NULL) &&
if ((rem->act == NULL) &&
(!tmxr_input_pending_ln (lp))) {
int32 unwritten;
@ -795,10 +806,10 @@ sim_switches = saved_switches; /* restore original switches */
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 */
return sim_rem_act[line] = NULL;
tmxr_send_buffered_data (rem->lp); /* flush any buffered data */
return rem->act = NULL;
}
/* Set up pending actions */
@ -807,13 +818,14 @@ static void sim_rem_setact (int32 line, const char *action)
{
if (action) {
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 */
sim_rem_act_buf[line] = (char *)realloc (sim_rem_act_buf[line], act_size);
sim_rem_act_buf_size[line] = act_size;
if (act_size > rem->act_buf_size) { /* expand buffer if necessary */
rem->act_buf = (char *)realloc (rem->act_buf, act_size);
rem->act_buf_size = act_size;
}
strcpy (sim_rem_act_buf[line], action); /* populate buffer */
sim_rem_act[line] = sim_rem_act_buf[line]; /* start at beginning of buffer */
strcpy (rem->act_buf, action); /* populate buffer */
rem->act = rem->act_buf; /* start at beginning of buffer */
}
else
sim_rem_clract (line);
@ -825,22 +837,23 @@ static char *sim_rem_getact (int32 line, char *buf, int32 size)
{
char *ep;
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;
while (sim_isspace (*sim_rem_act[line])) /* skip spaces */
sim_rem_act[line]++;
if (*sim_rem_act[line] == 0) /* now empty? */
while (sim_isspace (*rem->act)) /* skip spaces */
rem->act++;
if (*rem->act == 0) /* now empty? */
return sim_rem_clract (line);
if ((ep = strchr (sim_rem_act[line], ';'))) { /* cmd delimiter? */
lnt = ep - sim_rem_act[line]; /* cmd length */
memcpy (buf, sim_rem_act[line], lnt + 1); /* copy with ; */
if ((ep = strchr (rem->act, ';'))) { /* cmd delimiter? */
lnt = ep - rem->act; /* cmd length */
memcpy (buf, rem->act, lnt + 1); /* copy with ; */
buf[lnt] = 0; /* erase ; */
sim_rem_act[line] += lnt + 1; /* adv ptr */
rem->act += lnt + 1; /* adv ptr */
}
else {
strncpy (buf, sim_rem_act[line], size); /* copy action */
sim_rem_act[line] += strlen (sim_rem_act[line]);/* adv ptr to end */
strncpy (buf, rem->act, size); /* copy action */
rem->act += strlen (rem->act); /* adv ptr to end */
}
return buf;
}
@ -856,6 +869,7 @@ int32 val;
t_bool all_stop = FALSE;
t_stat stat = SCPE_OK;
CONST char *cptr = *iptr;
REMOTE *rem = &sim_rem_consoles[line];
sim_debug (DBG_REP, &sim_remote_console, "Repeat Setup: %s\n", cptr);
if (*cptr == 0) /* required argument? */
@ -872,7 +886,7 @@ else {
if ((MATCH_CMD (gbuf, "USECS") != 0) || (*cptr == 0))
stat = SCPE_ARG;
else
sim_rem_repeat_interval[line] = val;
rem->repeat_interval = val;
}
}
else {
@ -887,7 +901,7 @@ else {
all_stop = TRUE;
}
else
sim_rem_repeat_interval[line] = 0;
rem->repeat_interval = 0;
}
else
stat = SCPE_ARG;
@ -896,26 +910,27 @@ else {
if (stat == SCPE_OK) {
if (all_stop) {
for (line = 0; line < sim_rem_con_tmxr.lines; line++) {
free (sim_rem_repeat_action[line]);
sim_rem_repeat_action[line] = NULL;
sim_cancel (&sim_rem_con_unit[line + 2]);
sim_rem_repeat_pending[line] = FALSE;
rem = &sim_rem_consoles[line];
free (rem->repeat_action);
rem->repeat_action = NULL;
sim_cancel (rem->uptr);
rem->repeat_pending = FALSE;
sim_rem_clract (line);
}
}
else {
if (sim_rem_repeat_interval[line] != 0) {
sim_rem_repeat_action[line] = (char *)realloc (sim_rem_repeat_action[line], 1 + strlen (cptr));
strcpy (sim_rem_repeat_action[line], cptr);
if (rem->repeat_interval != 0) {
rem->repeat_action = (char *)realloc (rem->repeat_action, 1 + strlen (cptr));
strcpy (rem->repeat_action, 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 {
free (sim_rem_repeat_action[line]);
sim_rem_repeat_action[line] = NULL;
sim_cancel (&sim_rem_con_unit[line + 2]);
free (rem->repeat_action);
rem->repeat_action = NULL;
sim_cancel (rem->uptr);
}
sim_rem_repeat_pending[line] = FALSE;
rem->repeat_pending = FALSE;
sim_rem_clract (line);
}
}
@ -945,33 +960,34 @@ tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
(i < sim_rem_con_tmxr.lines) && (!active_command);
i++) {
REMOTE *rem = &sim_rem_consoles[i];
t_bool master_session = (sim_rem_master_mode && (i == 0));
lp = &sim_rem_con_tmxr.ldsc[i];
lp = rem->lp;
if (!lp->conn) {
if (sim_rem_repeat_interval[i]) { /* was repeated enabled? */
if (rem->repeat_interval) { /* was repeated enabled? */
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 */
}
continue;
}
if (master_session && !sim_rem_master_was_connected) {
tmxr_linemsgf (lp, "\nMaster Mode Session\r\n");
tmxr_send_buffered_data (lp); /* flush any buffered data */
tmxr_send_buffered_data (lp); /* flush any buffered data */
}
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;
if ((was_active_command) ||
(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 && !sim_rem_single_mode[i]) ? "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 && !rem->single_mode) ? "master_session && !single_mode" : "");
if (was_active_command) {
sim_rem_cmd_active_line = -1; /* Done with active command */
if (!sim_rem_active_command) { /* STEP command? */
sim_rem_cmd_active_line = -1; /* Done with active command */
if (!sim_rem_active_command) { /* STEP command? */
stat = SCPE_STEP;
_sim_rem_message ("STEP", stat); /* produce a STEP complete message */
_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 available input */
was_active_command = FALSE;
i = -1;
continue;
@ -984,19 +1000,19 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
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 */
tmxr_send_buffered_data (lpj); /* flush any buffered data */
}
}
}
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);
if (!(TMXR_VALID & c))
continue;
c = c & ~TMXR_VALID;
if (sim_rem_single_mode[i]) {
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 */
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 */
sim_is_running = 0;
sim_stop_timer_services ();
stat = SCPE_STOP;
@ -1007,37 +1023,37 @@ 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 any buffered data */
}
lp = &sim_rem_con_tmxr.ldsc[i];
if (!master_session)
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, "\r\n");
tmxr_send_buffered_data (lp); /* flush any buffered data */
tmxr_send_buffered_data (lp); /* flush any buffered data */
}
}
else {
if ((sim_rem_buf_ptr[i] == 0) && /* At beginning of input line */
((c == '\n') || /* Ignore bare LF between commands (Microsoft Telnet bug) */
(c == '\r'))) /* Ignore empty commands */
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) ? */
if ((c == '\004') || (c == '\032')) {/* EOF character (^D or ^Z) ? */
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);
continue;
}
if (sim_rem_buf_ptr[i] == 0) {
if (rem->buf_ptr == 0) {
/* we just picked up the first character on a command line */
if (!master_session)
tmxr_linemsgf (lp, "\r\n%s", sim_prompt);
else
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 ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp)))
tmxr_send_buffered_data (lp); /* flush any buffered data */
if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp)))
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) {
if (stat == SCPE_EXIT)
return stat|SCPE_NOMESSAGE;
if (!sim_rem_single_mode[i]) {
if (!rem->single_mode) {
read_start_time = sim_os_msec();
if (master_session)
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 */
}
do {
if (sim_rem_buf_ptr[i] == 0) {
if (sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i])) {
if (rem->buf_ptr == 0) {
if (sim_rem_getact (i, rem->buf, rem->buf_size)) {
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
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]);
sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]);
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", rem->buf);
rem->buf_ptr = strlen (rem->repeat_action);
got_command = TRUE;
break;
}
else {
if (sim_rem_repeat_pending[i]) {
sim_rem_repeat_pending[i] = FALSE;
sim_rem_setact (i, sim_rem_repeat_action[i]);
sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i]);
if (rem->repeat_pending) {
rem->repeat_pending = FALSE;
sim_rem_setact (i, rem->repeat_action);
sim_rem_getact (i, rem->buf, rem->buf_size);
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
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]);
sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]);
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", rem->buf);
rem->buf_ptr = strlen (rem->repeat_action);
got_command = TRUE;
break;
}
}
}
if (!sim_rem_single_mode[i]) {
if (!rem->single_mode) {
c = tmxr_getc_ln (lp);
if (!(TMXR_VALID & c)) {
tmxr_send_buffered_data (lp); /* flush any buffered data */
if (!master_session &&
sim_rem_read_timeouts[i] &&
((sim_os_msec() - read_start_time)/1000 >= sim_rem_read_timeouts[i])) {
while (sim_rem_buf_ptr[i] > 0) {/* Erase current input line */
rem->read_timeout &&
((sim_os_msec() - read_start_time)/1000 >= rem->read_timeout)) {
while (rem->buf_ptr > 0) { /* Erase current input line */
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]) {
sim_rem_buf_size[i] += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
if (rem->buf_ptr+80 >= rem->buf_size) {
rem->buf_size += 1024;
rem->buf = (char *)realloc (rem->buf, rem->buf_size);
}
strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue due to timeout");
tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]);
strcpy (rem->buf, "CONTINUE ! Automatic continue due to timeout");
tmxr_linemsgf (lp, "%s\n", rem->buf);
got_command = TRUE;
break;
}
sim_os_ms_sleep (50);
tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
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 */
}
continue;
@ -1117,88 +1133,88 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
break;
case '\b': /* Backspace */
case 127: /* Rubout */
if (sim_rem_buf_ptr[i] > 0) {
if (rem->buf_ptr > 0) {
tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i];
--rem->buf_ptr;
}
break;
case 27: /* escape */
case 21: /* ^U */
while (sim_rem_buf_ptr[i] > 0) {
while (rem->buf_ptr > 0) {
tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i];
--rem->buf_ptr;
}
break;
case '\n':
if (sim_rem_buf_ptr[i] == 0)
if (rem->buf_ptr == 0)
break;
case '\r':
tmxr_linemsg (lp, "\r\n");
if (sim_rem_buf_ptr[i]+1 >= sim_rem_buf_size[i]) {
sim_rem_buf_size[i] += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
if (rem->buf_ptr+1 >= rem->buf_size) {
rem->buf_size += 1024;
rem->buf = (char *)realloc (rem->buf, rem->buf_size);
}
sim_rem_buf[i][sim_rem_buf_ptr[i]++] = '\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]);
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), rem->buf);
got_command = TRUE;
break;
case '\004': /* EOF (^D) */
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");
--sim_rem_buf_ptr[i];
--rem->buf_ptr;
}
if (!sim_rem_single_mode[i]) {
if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) {
sim_rem_buf_size[i] += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
if (!rem->single_mode) {
if (rem->buf_ptr+80 >= rem->buf_size) {
rem->buf_size += 1024;
rem->buf = (char *)realloc (rem->buf, rem->buf_size);
}
strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue before close");
tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]);
strcpy (rem->buf, "CONTINUE ! Automatic continue before close");
tmxr_linemsgf (lp, "%s\n", rem->buf);
got_command = TRUE;
}
close_session = TRUE;
break;
default:
tmxr_putc_ln (lp, c);
if (sim_rem_buf_ptr[i]+2 >= sim_rem_buf_size[i]) {
sim_rem_buf_size[i] += 1024;
sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
if (rem->buf_ptr+2 >= rem->buf_size) {
rem->buf_size += 1024;
rem->buf = (char *)realloc (rem->buf, rem->buf_size);
}
sim_rem_buf[i][sim_rem_buf_ptr[i]++] = (char)c;
sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0';
if (((size_t)sim_rem_buf_ptr[i]) >= sizeof(cbuf))
rem->buf[rem->buf_ptr++] = (char)c;
rem->buf[rem->buf_ptr] = '\0';
if (((size_t)rem->buf_ptr) >= sizeof(cbuf))
got_command = TRUE; /* command too long */
break;
}
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 = c & ~TMXR_VALID;
}
} while ((!got_command) && ((!sim_rem_single_mode[i]) || c));
if ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp)))
} while ((!got_command) && ((!rem->single_mode) || c));
if ((rem->act == NULL) && (!tmxr_input_pending_ln (lp)))
tmxr_send_buffered_data (lp); /* flush any buffered data */
if ((sim_rem_single_mode[i]) && !got_command) {
if ((rem->single_mode) && !got_command) {
break;
}
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;
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");
tmxr_linemsgf (lp, "\nLine too long. Ignored. Continuing Simulator execution\n");
tmxr_send_buffered_data (lp); /* try to flush any buffered data */
break;
}
strcpy (cbuf, sim_rem_buf[i]);
sim_rem_buf_ptr[i] = 0;
sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0';
strcpy (cbuf, rem->buf);
rem->buf_ptr = 0;
rem->buf[rem->buf_ptr] = '\0';
while (isspace(cbuf[0]))
memmove (cbuf, cbuf+1, strlen(cbuf+1)+1); /* skip leading whitespace */
if (cbuf[0] == '\0') {
if (sim_rem_single_mode[i]) {
sim_rem_single_mode[i] = FALSE;
if (rem->single_mode) {
rem->single_mode = FALSE;
break;
}
else
@ -1235,7 +1251,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
stat = SCPE_UNK;
}
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);
if (cmdp->action == &x_continue_cmd) {
sim_debug (DBG_CMD, &sim_remote_console, "continue_cmd executing\n");
@ -1264,12 +1280,12 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
else {
if (cmdp->action == &x_run_cmd) {
sim_debug (DBG_CMD, &sim_remote_console, "run_cmd executing\n");
if (sim_con_stable_registers && /* can we process command now? */
if (sim_con_stable_registers && /* can we process command now? */
sim_rem_master_mode)
sim_oline = lp; /* specify output socket */
sim_switches |= SIM_SW_HIDE; /* Request Setup only */
sim_oline = lp; /* specify output socket */
sim_switches |= SIM_SW_HIDE; /* Request Setup only */
stat = basecmdp->action (cmdp->arg, cptr);
sim_switches &= ~SIM_SW_HIDE; /* Done with Setup only mode */
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");
@ -1282,15 +1298,15 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
}
else {
if (sim_con_stable_registers &&
sim_rem_master_mode) { /* can we process command now? */
sim_rem_master_mode) { /* can we process command now? */
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command directly\n");
sim_oline = lp; /* specify output socket */
sim_oline = lp; /* specify output socket */
sim_remote_process_command ();
stat = SCPE_OK; /* any message has already been emitted */
stat = SCPE_OK; /* any message has already been emitted */
}
else {
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command via SCPE_REMOTE\n");
stat = SCPE_REMOTE; /* force processing outside of sim_instr() */
stat = SCPE_REMOTE; /* force processing outside of sim_instr() */
}
}
}
@ -1305,12 +1321,12 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
stat = _sim_rem_message (gbuf, stat);
_sim_rem_log_out (lp);
if (master_session && !sim_rem_master_mode) {
sim_rem_single_mode[i] = TRUE;
rem->single_mode = TRUE;
return SCPE_STOP;
}
if (cmdp && (cmdp->action == &x_continue_cmd)) {
sim_rem_cmd_active_line = -1; /* Not active_command */
if (sim_log_temp && /* If we setup a temporary log, clean it now */
sim_rem_cmd_active_line = -1; /* Not active_command */
if (sim_log_temp && /* If we setup a temporary log, clean it now */
(!sim_rem_master_mode)) {
int32 save_quiet = sim_quiet;
@ -1324,7 +1340,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
fflush (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_send_buffered_data (lp);
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 ();
}
if (cmdp && (cmdp->action == &x_continue_cmd))
sim_rem_single_mode[i] = TRUE;
rem->single_mode = TRUE;
else {
if (!sim_rem_single_mode[i]) {
if (!rem->single_mode) {
if (master_session)
tmxr_linemsgf (lp, "%s", "sim> ");
else
@ -1358,41 +1374,42 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
}
if (close_session) {
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);
sim_rem_single_mode[i] = FALSE;
rem->single_mode = FALSE;
}
}
if (sim_rem_master_was_connected && /* Master mode ever connected? */
!sim_rem_con_tmxr.ldsc[0].sock) /* Master Connection lost? */
return SCPE_EXIT; /* simulator has been 'unplugged' */
if (sim_rem_master_was_connected && /* Master mode ever connected? */
!sim_rem_con_tmxr.ldsc[0].sock) /* Master Connection lost? */
return SCPE_EXIT; /* simulator has been 'unplugged' */
if (sim_rem_cmd_active_line != -1) {
if (steps)
sim_activate(uptr, steps); /* check again after 'steps' instructions */
sim_activate(uptr, steps); /* check again after 'steps' instructions */
else
return SCPE_REMOTE; /* force sim_instr() to exit to process command */
return SCPE_REMOTE; /* force sim_instr() to exit to process command */
}
else
sim_activate_after(uptr, 100000); /* check again in 100 milliaeconds */
if (sim_rem_master_was_enabled && !sim_rem_master_mode) {/* Transitioning out of master mode? */
sim_activate_after(uptr, 100000); /* check again in 100 milliaeconds */
if (sim_rem_master_was_enabled && !sim_rem_master_mode) { /* Transitioning out of master mode? */
lp = &sim_rem_con_tmxr.ldsc[0];
tmxr_linemsgf (lp, "Non Master Mode Session..."); /* report transition */
tmxr_send_buffered_data (lp); /* flush any buffered data */
return SCPE_STOP|SCPE_NOMESSAGE; /* Unwind to the normal input path */
tmxr_linemsgf (lp, "Non Master Mode Session..."); /* report transition */
tmxr_send_buffered_data (lp); /* flush any buffered data */
return SCPE_STOP|SCPE_NOMESSAGE; /* Unwind to the normal input path */
}
else
return SCPE_OK; /* keep going */
return SCPE_OK; /* keep going */
}
t_stat sim_rem_con_repeat_svc (UNIT *uptr)
{
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]);
if (sim_rem_repeat_interval[line]) {
sim_rem_repeat_pending[line] = TRUE;
sim_activate_after (uptr, sim_rem_repeat_interval[line]); /* reschedule */
sim_activate_abs (&sim_rem_con_unit[1], -1); /* wake up to process */
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, rem->repeat_interval);
if (rem->repeat_interval) {
rem->repeat_pending = TRUE;
sim_activate_after (uptr, rem->repeat_interval); /* reschedule */
sim_activate_abs (&sim_rem_con_unit[1], -1); /* wake up to process */
}
return SCPE_OK;
}
@ -1408,15 +1425,17 @@ if (sim_rem_con_tmxr.lines) {
sim_rem_con_unit[i + 2].action = &sim_rem_con_repeat_svc;
}
for (i=0; i<sim_rem_con_tmxr.lines; i++) {
REMOTE *rem = &sim_rem_consoles[i];
if (!sim_rem_con_tmxr.ldsc[i].conn)
continue;
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, sim_rem_repeat_interval[i]);
if (sim_rem_repeat_interval[i])
sim_activate_after (sim_rem_con_unit + 2 + i, sim_rem_repeat_interval[i]);/* schedule */
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, rem->repeat_interval);
if (rem->repeat_interval)
sim_activate_after (sim_rem_con_unit + 2 + i, rem->repeat_interval);/* schedule */
}
if (i != sim_rem_con_tmxr.lines)
sim_activate_after (&dptr->units[1], 100000); /* continue polling for open sessions */
return sim_rem_con_poll_svc (&dptr->units[0]); /* establish polling as needed */
sim_activate_after (&dptr->units[1], 100000); /* continue polling for open sessions */
return sim_rem_con_poll_svc (&dptr->units[0]); /* establish polling as needed */
}
return SCPE_OK;
}
@ -1428,15 +1447,15 @@ t_stat r;
if (flag) {
r = sim_parse_addr (cptr, NULL, 0, NULL, NULL, 0, NULL, NULL);
if (r == SCPE_OK) {
if (sim_rem_con_tmxr.master) /* already open? */
sim_set_rem_telnet (0, NULL); /* close first */
if (sim_rem_con_tmxr.lines == 0) /* Ir no connection limit set */
sim_set_rem_connections (0, "1"); /* use 1 */
sim_rem_con_tmxr.buffered = 8192; /* Use big enough buffers */
if (sim_rem_con_tmxr.master) /* already open? */
sim_set_rem_telnet (0, NULL); /* close first */
if (sim_rem_con_tmxr.lines == 0) /* Ir no connection limit set */
sim_set_rem_connections (0, "1"); /* use 1 */
sim_rem_con_tmxr.buffered = 8192; /* Use big enough buffers */
sim_register_internal_device (&sim_remote_console);
r = tmxr_attach (&sim_rem_con_tmxr, &sim_rem_con_unit[0], cptr);/* open master socket */
if (r == SCPE_OK)
sim_activate_after(&sim_rem_con_unit[0], 1000000); /* check for connection in 1 second */
sim_activate_after(&sim_rem_con_unit[0], 1000000);/* check for connection in 1 second */
return r;
}
return SCPE_NOPARAM;
@ -1447,11 +1466,12 @@ else {
tmxr_detach (&sim_rem_con_tmxr, &sim_rem_con_unit[0]);
for (i=0; i<sim_rem_con_tmxr.lines; i++) {
free (sim_rem_buf[i]);
sim_rem_buf[i] = NULL;
sim_rem_buf_size[i] = 0;
sim_rem_buf_ptr[i] = 0;
sim_rem_single_mode[i] = TRUE;
REMOTE *rem = &sim_rem_consoles[i];
free (rem->buf);
rem->buf = NULL;
rem->buf_size = 0;
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)
{
int32 lines;
REMOTE *rem;
t_stat r;
int32 i;
@ -1470,36 +1491,27 @@ lines = (int32) get_uint (cptr, 10, MAX_REMOTE_SESSIONS, &r);
if (r != SCPE_OK)
return r;
if (sim_rem_con_tmxr.master)
return SCPE_ARG;
for (i=0; i<sim_rem_con_tmxr.lines; i++)
free (sim_rem_buf[i]);
return SCPE_ALATT;
for (i=0; i<sim_rem_con_tmxr.lines; 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.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);
sim_rem_buf = (char **)realloc (sim_rem_buf, sizeof(*sim_rem_buf)*lines);
memset (sim_rem_buf, 0, sizeof(*sim_rem_buf)*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_consoles = (REMOTE *)realloc (sim_rem_consoles, sizeof(*sim_rem_consoles)*lines);
memset (sim_rem_consoles, 0, sizeof(*sim_rem_consoles)*lines);
sim_rem_command_buf = (char *)realloc (sim_rem_command_buf, 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;
}
@ -1514,7 +1526,7 @@ timeout = (int32) get_uint (cptr, 10, 3600, &r);
if (r != SCPE_OK)
return r;
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
sim_rem_read_timeout = timeout;
return SCPE_OK;
@ -1534,7 +1546,7 @@ if (r != SCPE_OK)
if (bufsize < 1400)
return sim_messagef (SCPE_ARG, "%d is too small. Minimum size is 1400\n", bufsize);
sprintf(cmdbuf, "BUFFERED=%d", bufsize);
return tmxr_open_master (&sim_rem_con_tmxr, cmdbuf); /* open master socket */
return tmxr_open_master (&sim_rem_con_tmxr, cmdbuf); /* open master socket */
}
/* Enable or disable Remote Console master mode */
@ -1557,7 +1569,7 @@ if (sim_rem_active_number > 0) {
return SCPE_INVREM;
}
if (sim_rem_con_tmxr.master || (!flag)) /* Remote Console Enabled? */
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");
@ -1571,12 +1583,12 @@ if (sim_rem_master_mode) {
stat = sim_run_boot_prep (0);
sim_rem_master_was_enabled = TRUE;
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_activate (&sim_rem_con_unit[1], -1);
stat = run_cmd (RU_GO, "");
if (stat != SCPE_TTMO) {
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
stat = _sim_rem_message ("RUN", stat);
}
if (stat == SCPE_EXIT)
@ -1596,9 +1608,8 @@ if (sim_rem_master_mode) {
stat |= stat_nomessage;
}
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;
}