Add Remote Console support

This commit is contained in:
Mark Pizzolato 2013-04-19 13:54:19 -07:00
parent 1936f7ff75
commit b886fb23b6
5 changed files with 412 additions and 72 deletions

16
scp.c
View file

@ -351,8 +351,6 @@ t_stat set_dev_enbdis (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat set_dev_debug (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat set_dev_debug (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat set_unit_enbdis (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat set_unit_enbdis (DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat ssh_break (FILE *st, char *cptr, int32 flg); t_stat ssh_break (FILE *st, char *cptr, int32 flg);
t_stat set_default_cmd (int32 flg, char *cptr);
t_stat pwd_cmd (int32 flg, char *cptr);
t_stat show_cmd_fi (FILE *ofile, int32 flag, char *cptr); t_stat show_cmd_fi (FILE *ofile, int32 flag, char *cptr);
t_stat show_config (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat show_config (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat show_queue (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat show_queue (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
@ -432,7 +430,6 @@ t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
UNIT *uptr, int32 dfltinc); UNIT *uptr, int32 dfltinc);
void fprint_fields (FILE *stream, t_value before, t_value after, BITFIELD* bitdefs); void fprint_fields (FILE *stream, t_value before, t_value after, BITFIELD* bitdefs);
t_stat step_svc (UNIT *ptr); t_stat step_svc (UNIT *ptr);
void sub_args (char *instr, size_t instr_size, char *do_arg[]);
t_stat shift_args (char *do_arg[], size_t arg_count); t_stat shift_args (char *do_arg[], size_t arg_count);
t_stat set_on (int32 flag, char *cptr); t_stat set_on (int32 flag, char *cptr);
t_stat set_verify (int32 flag, char *cptr); t_stat set_verify (int32 flag, char *cptr);
@ -564,6 +561,7 @@ const struct scp_error {
{"TTMO", "Console Telnet connection timed out"}, {"TTMO", "Console Telnet connection timed out"},
{"STALL", "Console Telnet output stall"}, {"STALL", "Console Telnet output stall"},
{"AFAIL", "Assertion failed"}, {"AFAIL", "Assertion failed"},
{"INVREM", "Invalid remote console command"},
}; };
const size_t size_map[] = { sizeof (int8), const size_t size_map[] = { sizeof (int8),
@ -676,6 +674,9 @@ static CTAB cmd_table[] = {
" specified destination {STDOUT,STDERR,DEBUG\n" " specified destination {STDOUT,STDERR,DEBUG\n"
" or filename)\n" " or filename)\n"
"set console NOLOG disable console logging\n" "set console NOLOG disable console logging\n"
"set remote TELNET=port specify remote console telnet port\n"
"set remote NOTELNET disables remote console\n"
"set remote CONNECTIONS=n specify number of concurrent remote console sessions\n"
"set default <dir> set the current directory\n" "set default <dir> set the current directory\n"
"set log log_file specify the log destination\n" "set log log_file specify the log destination\n"
" (STDOUT,DEBUG or filename)\n" " (STDOUT,DEBUG or filename)\n"
@ -729,6 +730,7 @@ static CTAB cmd_table[] = {
"sh{ow} a{synch} show asynchronouse I/O state\n" "sh{ow} a{synch} show asynchronouse I/O state\n"
"sh{ow} ve{rsion} show simulator version\n" "sh{ow} ve{rsion} show simulator version\n"
"sh{ow} def{ault} show current directory\n" "sh{ow} def{ault} show current directory\n"
"sh{ow} rem{oteconsole} show remote console configuration\n"
"sh{ow} <dev> RADIX show device display radix\n" "sh{ow} <dev> RADIX show device display radix\n"
"sh{ow} <dev> DEBUG show device debug flags\n" "sh{ow} <dev> DEBUG show device debug flags\n"
"sh{ow} <dev> MODIFIERS show device modifiers\n" "sh{ow} <dev> MODIFIERS show device modifiers\n"
@ -927,7 +929,7 @@ while (stat != SCPE_EXIT) { /* in case exit */
} }
if (*cptr == 0) /* ignore blank */ if (*cptr == 0) /* ignore blank */
continue; continue;
sub_args (cbuf, sizeof(cbuf), argv); sim_sub_args (cbuf, sizeof(cbuf), argv);
if (sim_log) /* log cmd */ if (sim_log) /* log cmd */
fprintf (sim_log, "%s%s\n", sim_prompt, cptr); fprintf (sim_log, "%s%s\n", sim_prompt, cptr);
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
@ -1574,7 +1576,7 @@ do {
ocptr = cptr = read_line (cbuf, sizeof(cbuf), fpin);/* get cmd line */ ocptr = cptr = read_line (cbuf, sizeof(cbuf), fpin);/* get cmd line */
sim_goto_line[sim_do_depth] += 1; sim_goto_line[sim_do_depth] += 1;
} }
sub_args (cbuf, sizeof(cbuf), do_arg); /* substitute args */ sim_sub_args (cbuf, sizeof(cbuf), do_arg); /* substitute args */
if (cptr == NULL) { /* EOF? */ if (cptr == NULL) { /* EOF? */
stat = SCPE_OK; /* set good return */ stat = SCPE_OK; /* set good return */
break; break;
@ -1733,7 +1735,7 @@ return stat | SCPE_NOMESSAGE; /* suppress message sinc
untouched. untouched.
*/ */
void sub_args (char *instr, size_t instr_size, char *do_arg[]) void sim_sub_args (char *instr, size_t instr_size, char *do_arg[])
{ {
char gbuf[CBUFSIZE]; char gbuf[CBUFSIZE];
char *ip = instr, *op, *ap, *oend, *istart, *tmpbuf; char *ip = instr, *op, *ap, *oend, *istart, *tmpbuf;
@ -2207,6 +2209,7 @@ C1TAB *ctbr, *glbr;
static CTAB set_glob_tab[] = { static CTAB set_glob_tab[] = {
{ "CONSOLE", &sim_set_console, 0 }, { "CONSOLE", &sim_set_console, 0 },
{ "REMOTE", &sim_set_remote_console, 0 },
{ "BREAK", &brk_cmd, SSH_ST }, { "BREAK", &brk_cmd, SSH_ST },
{ "DEFAULT", &set_default_cmd, 1 }, { "DEFAULT", &set_default_cmd, 1 },
{ "NOBREAK", &brk_cmd, SSH_CL }, { "NOBREAK", &brk_cmd, SSH_CL },
@ -2505,6 +2508,7 @@ static SHTAB show_glob_tab[] = {
{ "VERSION", &show_version, 1 }, { "VERSION", &show_version, 1 },
{ "DEFAULT", &show_default, 0 }, { "DEFAULT", &show_default, 0 },
{ "CONSOLE", &sim_show_console, 0 }, { "CONSOLE", &sim_show_console, 0 },
{ "REMOTE", &sim_show_remote_console, 0 },
{ "BREAK", &show_break, 0 }, { "BREAK", &show_break, 0 },
{ "LOG", &sim_show_log, 0 }, /* deprecated */ { "LOG", &sim_show_log, 0 }, /* deprecated */
{ "TELNET", &sim_show_telnet, 0 }, /* deprecated */ { "TELNET", &sim_show_telnet, 0 }, /* deprecated */

3
scp.h
View file

@ -69,6 +69,8 @@ t_stat restore_cmd (int32 flag, char *ptr);
t_stat exit_cmd (int32 flag, char *ptr); t_stat exit_cmd (int32 flag, char *ptr);
t_stat set_cmd (int32 flag, char *ptr); t_stat set_cmd (int32 flag, char *ptr);
t_stat show_cmd (int32 flag, char *ptr); t_stat show_cmd (int32 flag, char *ptr);
t_stat set_default_cmd (int32 flg, char *cptr);
t_stat pwd_cmd (int32 flg, char *cptr);
t_stat brk_cmd (int32 flag, char *ptr); t_stat brk_cmd (int32 flag, char *ptr);
t_stat do_cmd (int32 flag, char *ptr); t_stat do_cmd (int32 flag, char *ptr);
t_stat goto_cmd (int32 flag, char *ptr); t_stat goto_cmd (int32 flag, char *ptr);
@ -122,6 +124,7 @@ DEVICE *find_dev (char *ptr);
DEVICE *find_unit (char *ptr, UNIT **uptr); DEVICE *find_unit (char *ptr, UNIT **uptr);
DEVICE *find_dev_from_unit (UNIT *uptr); DEVICE *find_dev_from_unit (UNIT *uptr);
t_stat sim_register_internal_device (DEVICE *dptr); t_stat sim_register_internal_device (DEVICE *dptr);
void sim_sub_args (char *in_str, size_t in_str_size, char *do_arg[]);
REG *find_reg (char *ptr, char **optr, DEVICE *dptr); REG *find_reg (char *ptr, char **optr, DEVICE *dptr);
CTAB *find_ctab (CTAB *tab, char *gbuf); CTAB *find_ctab (CTAB *tab, char *gbuf);
C1TAB *find_c1tab (C1TAB *tab, char *gbuf); C1TAB *find_c1tab (C1TAB *tab, char *gbuf);

View file

@ -125,14 +125,17 @@
/* Forward Declaraations of Platform specific routines */ /* Forward Declaraations of Platform specific routines */
t_stat sim_os_poll_kbd (void); static t_stat sim_os_poll_kbd (void);
t_bool sim_os_poll_kbd_ready (int ms_timeout); static t_bool sim_os_poll_kbd_ready (int ms_timeout);
t_stat sim_os_putchar (int32 out); static t_stat sim_os_putchar (int32 out);
t_stat sim_os_ttinit (void); static t_stat sim_os_ttinit (void);
t_stat sim_os_ttrun (void); static t_stat sim_os_ttrun (void);
t_stat sim_os_ttcmd (void); static t_stat sim_os_ttcmd (void);
t_stat sim_os_ttclose (void); static t_stat sim_os_ttclose (void);
t_bool sim_os_ttisatty (void); static t_bool sim_os_ttisatty (void);
static t_stat sim_set_rem_telnet (int32 flag, char *cptr);
static t_stat sim_set_rem_connections (int32 flag, char *cptr);
#define KMAP_WRU 0 #define KMAP_WRU 0
#define KMAP_BRK 1 #define KMAP_BRK 1
@ -148,8 +151,8 @@ int32 sim_del_char = '\b'; /* delete character */
#else #else
int32 sim_del_char = 0177; int32 sim_del_char = 0177;
#endif #endif
t_stat sim_con_poll_svc (UNIT *uptr); /* console connection poll routine */ static t_stat sim_con_poll_svc (UNIT *uptr); /* console connection poll routine */
t_stat sim_con_reset (DEVICE *dptr); /* console connection poll routine */ static t_stat sim_con_reset (DEVICE *dptr); /* console reset routine */
UNIT sim_con_unit = { UDATA (&sim_con_poll_svc, 0, 0) }; /* console connection unit */ UNIT sim_con_unit = { UDATA (&sim_con_poll_svc, 0, 0) }; /* console connection unit */
/* debugging bitmaps */ /* debugging bitmaps */
#define DBG_TRC TMXR_DBG_TRC /* trace routine calls */ #define DBG_TRC TMXR_DBG_TRC /* trace routine calls */
@ -157,7 +160,7 @@ UNIT sim_con_unit = { UDATA (&sim_con_poll_svc, 0, 0) }; /* console connectio
#define DBG_RCV TMXR_DBG_RCV /* display Received Data */ #define DBG_RCV TMXR_DBG_RCV /* display Received Data */
#define DBG_ASY TMXR_DBG_ASY /* asynchronous thread activity */ #define DBG_ASY TMXR_DBG_ASY /* asynchronous thread activity */
DEBTAB sim_con_debug[] = { static DEBTAB sim_con_debug[] = {
{"TRC", DBG_TRC}, {"TRC", DBG_TRC},
{"XMT", DBG_XMT}, {"XMT", DBG_XMT},
{"RCV", DBG_RCV}, {"RCV", DBG_RCV},
@ -165,7 +168,7 @@ DEBTAB sim_con_debug[] = {
{0} {0}
}; };
MTAB sim_con_mod[] = { static MTAB sim_con_mod[] = {
{ 0 }, { 0 },
}; };
@ -179,7 +182,7 @@ TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc, NULL, &sim_con_telnet };/* console
/* Unit service for console connection polling */ /* Unit service for console connection polling */
t_stat sim_con_poll_svc (UNIT *uptr) static t_stat sim_con_poll_svc (UNIT *uptr)
{ {
if ((sim_con_tmxr.master == 0) && /* not Telnet and not serial? */ if ((sim_con_tmxr.master == 0) && /* not Telnet and not serial? */
(sim_con_ldsc.serport == 0)) (sim_con_ldsc.serport == 0))
@ -192,7 +195,7 @@ if (sim_con_ldsc.conn)
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_con_reset (DEVICE *dptr) static t_stat sim_con_reset (DEVICE *dptr)
{ {
return sim_con_poll_svc (&dptr->units[0]); /* establish polling as needed */ return sim_con_poll_svc (&dptr->units[0]); /* establish polling as needed */
} }
@ -216,6 +219,13 @@ static CTAB set_con_tab[] = {
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
static CTAB set_rem_con_tab[] = {
{ "CONNECTIONS", &sim_set_rem_connections, 0 },
{ "TELNET", &sim_set_rem_telnet, 1 },
{ "NOTELNET", &sim_set_rem_telnet, 0 },
{ NULL, NULL, 0 }
};
static SHTAB show_con_tab[] = { static SHTAB show_con_tab[] = {
{ "WRU", &sim_show_kmap, KMAP_WRU }, { "WRU", &sim_show_kmap, KMAP_WRU },
{ "BRK", &sim_show_kmap, KMAP_BRK }, { "BRK", &sim_show_kmap, KMAP_BRK },
@ -304,6 +314,320 @@ while (*cptr != 0) {
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_rem_con_poll_svc (UNIT *uptr); /* remote console connection poll routine */
t_stat sim_rem_con_data_svc (UNIT *uptr); /* remote console connection data routine */
t_stat sim_rem_con_reset (DEVICE *dptr); /* remote console reset routine */
UNIT sim_rem_con_unit[2] = {
{ UDATA (&sim_rem_con_poll_svc, 0, 0) }, /* remote console connection polling unit */
{ UDATA (&sim_rem_con_data_svc, 0, 0) }}; /* console data handling unit */
DEBTAB sim_rem_con_debug[] = {
{"TRC", DBG_TRC},
{"XMT", DBG_XMT},
{"RCV", DBG_RCV},
{0}
};
MTAB sim_rem_con_mod[] = {
{ 0 },
};
DEVICE sim_remote_console = {
"REM-CON", sim_rem_con_unit, NULL, sim_rem_con_mod,
2, 0, 0, 0, 0, 0,
NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL,
NULL, DEV_DEBUG, 0, sim_rem_con_debug};
int32 *sim_rem_buf_size = NULL;
int32 *sim_rem_buf_ptr = NULL;
char **sim_rem_buf = NULL;
TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };/* remote console line mux */
/* SET REMOTE CONSOLE command */
t_stat sim_set_remote_console (int32 flag, char *cptr)
{
char *cvptr, gbuf[CBUFSIZE];
CTAB *ctptr;
t_stat r;
if ((cptr == NULL) || (*cptr == 0))
return SCPE_2FARG;
while (*cptr != 0) { /* do all mods */
cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */
if ((cvptr = strchr (gbuf, '='))) /* = value? */
*cvptr++ = 0;
get_glyph (gbuf, gbuf, 0); /* modifier to UC */
if ((ctptr = find_ctab (set_rem_con_tab, gbuf))) { /* match? */
r = ctptr->action (ctptr->arg, cvptr); /* do the rest */
if (r != SCPE_OK)
return r;
}
else return SCPE_NOPARAM;
}
return SCPE_OK;
}
/* SHOW REMOTE CONSOLE command */
t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
{
if (*cptr != 0)
return SCPE_NOPARAM;
if (!sim_rem_con_tmxr.master) {
fprintf (st, "Remote Console Command input is disabled\n");
return SCPE_OK;
}
fprintf (st, "Remote Console Command Input listening on TCP port: %s\n", sim_rem_con_unit[0].filename);
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);
return SCPE_OK;
}
/* Unit service for remote console connection polling */
t_stat sim_rem_con_poll_svc (UNIT *uptr)
{
int32 c;
c = tmxr_poll_conn (&sim_rem_con_tmxr);
if (c >= 0) { /* poll connect */
TMLN *lp = &sim_rem_con_tmxr.ldsc[c];
sim_activate_after(uptr+1, 1000000); /* start data poll after 100ms */
lp->rcve = 1; /* rcv enabled */
sim_rem_buf_ptr[c] = 0; /* start with empty command buffer */
tmxr_linemsg (lp, sim_name);
tmxr_linemsg (lp, " Remote Console\r\nSimulator Running...");
tmxr_send_buffered_data (lp); /* flush buffered data */
}
sim_activate_after(uptr, 1000000); /* check again in 1 second */
if (sim_con_ldsc.conn)
tmxr_send_buffered_data (&sim_con_ldsc); /* try to flush any buffered data */
return SCPE_OK;
}
static t_stat x_continue_cmd (int32 flag, char *cptr)
{
return SCPE_IERR; /* This routine should never be called */
}
/* Unit service for remote console data polling */
t_stat sim_rem_con_data_svc (UNIT *uptr)
{
int32 i, c;
t_stat stat, stat_nomessage;
t_bool got_command;
TMLN *lp;
char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *cptr, *argv[1] = {NULL};
CTAB *cmdp;
long cmd_log_start;
#define EX_D 0 /* deposit */
#define EX_E 1 /* examine */
#define EX_I 2 /* interactive */
static CTAB allowed_remote_cmds[] = {
{ "EXAMINE", &exdep_cmd, EX_E },
{ "IEXAMINE", &exdep_cmd, EX_E+EX_I },
{ "DEPOSIT", &exdep_cmd, EX_D },
{ "EVALUATE", &eval_cmd },
{ "ATTACH", &attach_cmd },
{ "DETACH", &detach_cmd },
{ "ASSIGN", &assign_cmd },
{ "DEASSIGN", &deassign_cmd },
{ "CONT", &x_continue_cmd },
{ "PROCEED", &noop_cmd },
{ "IGNORE", &noop_cmd },
{ "PWD", &pwd_cmd },
{ "SAVE", &save_cmd },
{ "SET", &save_cmd },
{ "SHOW", &show_cmd },
{ "ECHO", &echo_cmd },
{ "HELP", &help_cmd },
{ NULL, NULL }
};
tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
for (i=0; i < sim_rem_con_tmxr.lines; i++) {
lp = &sim_rem_con_tmxr.ldsc[i];
if (!lp->conn)
continue;
c = tmxr_getc_ln (lp);
if (!(TMXR_VALID & c))
continue;
c = c & ~TMXR_VALID;
if (c != sim_int_char)
continue; /* ^E (the interrupt character) must start console interaction */
tmxr_linemsg (lp, "\r\n");
while (1) {
tmxr_linemsg (lp, "sim> ");
tmxr_send_buffered_data (lp); /* try to flush any buffered data */
got_command = FALSE;
while (!got_command) {
c = tmxr_getc_ln (lp);
if (!(TMXR_VALID & c)) {
tmxr_send_buffered_data (lp); /* try to flush any buffered data */
sim_os_ms_sleep (100);
tmxr_poll_rx (&sim_rem_con_tmxr);/* poll input */
continue;
}
c = c & ~TMXR_VALID;
switch (c) {
case 0: /* no data */
break;
case '\b': /* Backspace */
case 127: /* Rubout */
if (sim_rem_buf_ptr[i] > 0) {
tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i];
}
break;
case 27: /* escape */
case 21: /* ^U */
while (sim_rem_buf_ptr[i] > 0) {
tmxr_linemsg (lp, "\b \b");
--sim_rem_buf_ptr[i];
}
break;
case '\r':
tmxr_putc_ln (lp, c);
tmxr_putc_ln (lp, '\n');
if (sim_rem_buf_ptr[i]+1 >= sim_rem_buf_size[i]) {
sim_rem_buf_size[i] += 1024;
sim_rem_buf[i] = realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
}
sim_rem_buf[i][sim_rem_buf_ptr[i]++] = '\0';
got_command = 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] = realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
}
sim_rem_buf[i][sim_rem_buf_ptr[i]++] = c;
sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0';
break;
}
}
tmxr_send_buffered_data (lp); /* try to flush any buffered data */
printf ("Remote Console Command from %s> %s\n", lp->ipad, sim_rem_buf[i]);
if (sim_log)
fprintf (sim_log, "Remote Console Command from %s> %s\n", lp->ipad, sim_rem_buf[i]);
if (strlen(sim_rem_buf[i]) >= sizeof(cbuf)) {
tmxr_linemsg (lp, "Line too long. Ignored. Continuing Simulator execution\r\n");
tmxr_send_buffered_data (lp); /* try to flush any buffered data */
break;
}
strcpy (cbuf, sim_rem_buf[i]);
if (cbuf[0] == '\0')
continue;
sim_rem_buf_ptr[i] = 0;
sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0';
sim_sub_args (cbuf, sizeof(cbuf), argv);
cptr = cbuf;
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
sim_switches = 0; /* init switches */
cmd_log_start = ftell (sim_log);
if (!find_cmd (gbuf)) /* validate command */
stat = SCPE_UNK;
else {
if ((cmdp = find_ctab (allowed_remote_cmds, gbuf))) {/* lookup command */
if (cmdp->action != &x_continue_cmd)
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
else
stat = SCPE_OK;
}
else
stat = SCPE_INVREM;
}
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
stat = SCPE_BARE_STATUS(stat); /* remove possible flag */
if (!stat_nomessage) { /* displaying message status? */
if (cmdp && (cmdp->message)) /* special message handler? */
cmdp->message (NULL, stat); /* let it deal with display */
else
if (stat >= SCPE_BASE) { /* error? */
printf ("%s\n", sim_error_text (stat));
if (sim_log)
fprintf (sim_log, "%s\n", sim_error_text (stat));
}
}
fflush (sim_log);
fseek (sim_log, cmd_log_start, SEEK_SET);
cbuf[sizeof(cbuf)-1] = '\0';
while (fgets (cbuf, sizeof(cbuf)-1, sim_log)) {
tmxr_linemsg (lp, cbuf);
tmxr_linemsg (lp, "\r");
tmxr_send_buffered_data (lp);
}
if (cmdp->action == &x_continue_cmd)
break;
}
}
sim_activate_after(uptr, 100000); /* check again in 100 milliaeconds */
return SCPE_OK;
}
t_stat sim_rem_con_reset (DEVICE *dptr)
{
if (sim_rem_con_tmxr.lines)
return sim_rem_con_poll_svc (&dptr->units[0]); /* establish polling as needed */
return SCPE_OK;
}
static t_stat sim_set_rem_telnet (int32 flag, char *cptr)
{
t_stat r;
if (flag) {
r = sim_parse_addr (cptr, NULL, 0, NULL, NULL, 0, NULL, NULL);
if (r == SCPE_OK) {
if (!sim_log) {
printf ("Logging must be enabled to activate Remote Console support\n");
return SCPE_ARG;
}
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_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 */
return r;
}
return SCPE_NOPARAM;
}
else {
if (sim_rem_con_tmxr.master)
tmxr_detach (&sim_rem_con_tmxr, &sim_rem_con_unit[0]);
}
return SCPE_OK;
}
static t_stat sim_set_rem_connections (int32 flag, char *cptr)
{
int32 lines = atoi(cptr);
int32 i;
if (sim_rem_con_tmxr.master)
return SCPE_ARG;
for (i=0; i<sim_rem_con_tmxr.lines; i++)
free (sim_rem_buf[i]);
sim_rem_con_tmxr.lines = lines;
sim_rem_con_tmxr.ldsc = 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 = realloc (sim_rem_buf, sizeof(*sim_rem_buf)*lines);
memset (sim_rem_buf, 0, sizeof(*sim_rem_buf)*lines);
sim_rem_buf_size = realloc (sim_rem_buf_size, sizeof(*sim_rem_buf_size)*lines);
memset (sim_rem_buf_size, 0, sizeof(*sim_rem_buf_size)*lines);
sim_rem_buf_ptr = realloc (sim_rem_buf_ptr, sizeof(*sim_rem_buf_ptr)*lines);
memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines);
return SCPE_OK;
}
/* Set keyboard map */ /* Set keyboard map */
t_stat sim_set_kmap (int32 flag, char *cptr) t_stat sim_set_kmap (int32 flag, char *cptr)
@ -396,6 +720,12 @@ if (cptr && (*cptr != 0)) /* now eol? */
return SCPE_2MARG; return SCPE_2MARG;
if (sim_log == NULL) /* no log? */ if (sim_log == NULL) /* no log? */
return SCPE_OK; return SCPE_OK;
if (sim_rem_con_tmxr.master) {
if (!sim_quiet)
printf ("Can't close log, Remote Console is enabled\n");
fprintf (sim_log, "Can't close log, Remote Console is enabled\n");
return SCPE_ARG;
}
if (!sim_quiet) if (!sim_quiet)
printf ("Log file closed\n"); printf ("Log file closed\n");
fprintf (sim_log, "Log file closed\n"); fprintf (sim_log, "Log file closed\n");
@ -723,7 +1053,7 @@ else {
return SCPE_MEM; return SCPE_MEM;
get_glyph_nc (filename, gbuf, 0); /* reparse */ get_glyph_nc (filename, gbuf, 0); /* reparse */
strncpy ((*pref)->name, gbuf, sizeof((*pref)->name)-1); strncpy ((*pref)->name, gbuf, sizeof((*pref)->name)-1);
*pf = sim_fopen (gbuf, (binary ? "ab" : "a")); /* open file */ *pf = sim_fopen (gbuf, (binary ? "a+b" : "a+")); /* open file */
if (*pf == NULL) { /* error? */ if (*pf == NULL) { /* error? */
free (*pref); free (*pref);
*pref = NULL; *pref = NULL;
@ -1130,7 +1460,7 @@ typedef struct {
SENSE_BUF cmd_mode = { 0 }; SENSE_BUF cmd_mode = { 0 };
SENSE_BUF run_mode = { 0 }; SENSE_BUF run_mode = { 0 };
t_stat sim_os_ttinit (void) static t_stat sim_os_ttinit (void)
{ {
unsigned int status; unsigned int status;
IOSB iosb; IOSB iosb;
@ -1149,7 +1479,7 @@ run_mode.stat2 = cmd_mode.stat2 | TT2$M_PASTHRU;
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttrun (void) static t_stat sim_os_ttrun (void)
{ {
unsigned int status; unsigned int status;
IOSB iosb; IOSB iosb;
@ -1161,7 +1491,7 @@ if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL))
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttcmd (void) static t_stat sim_os_ttcmd (void)
{ {
unsigned int status; unsigned int status;
IOSB iosb; IOSB iosb;
@ -1173,19 +1503,19 @@ if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL))
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttclose (void) static t_stat sim_os_ttclose (void)
{ {
sim_ttcmd (); sim_ttcmd ();
sys$dassgn (tty_chan); sys$dassgn (tty_chan);
return SCPE_OK; return SCPE_OK;
} }
t_bool sim_os_ttisatty (void) static t_bool sim_os_ttisatty (void)
{ {
return isatty (fileno (stdin)); return isatty (fileno (stdin));
} }
t_stat sim_os_poll_kbd_data (void) static t_stat sim_os_poll_kbd_data (void)
{ {
unsigned int status, term[2]; unsigned int status, term[2];
unsigned char buf[4]; unsigned char buf[4];
@ -1210,7 +1540,7 @@ if (sim_brk_char && (buf[0] == sim_brk_char))
return (buf[0] | SCPE_KFLAG); return (buf[0] | SCPE_KFLAG);
} }
t_stat sim_os_poll_kbd (void) static t_stat sim_os_poll_kbd (void)
{ {
t_stat response; t_stat response;
@ -1221,7 +1551,7 @@ if (response = buffered_character) {
return sim_os_poll_kbd_data (); return sim_os_poll_kbd_data ();
} }
t_bool sim_os_poll_kbd_ready (int ms_timeout) static t_bool sim_os_poll_kbd_ready (int ms_timeout)
{ {
unsigned int status, term[2]; unsigned int status, term[2];
unsigned char buf[4]; unsigned char buf[4];
@ -1244,7 +1574,7 @@ return TRUE;
} }
t_stat sim_os_putchar (int32 out) static t_stat sim_os_putchar (int32 out)
{ {
unsigned int status; unsigned int status;
char c; char c;
@ -1300,7 +1630,7 @@ ControlHandler(DWORD dwCtrlType)
return FALSE; return FALSE;
} }
t_stat sim_os_ttinit (void) static t_stat sim_os_ttinit (void)
{ {
SetConsoleCtrlHandler( ControlHandler, TRUE ); SetConsoleCtrlHandler( ControlHandler, TRUE );
std_input = GetStdHandle (STD_INPUT_HANDLE); std_input = GetStdHandle (STD_INPUT_HANDLE);
@ -1311,7 +1641,7 @@ if ((std_input) && /* Not Background proces
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttrun (void) static t_stat sim_os_ttrun (void)
{ {
if ((std_input) && /* If Not Background process? */ if ((std_input) && /* If Not Background process? */
(std_input != INVALID_HANDLE_VALUE) && (std_input != INVALID_HANDLE_VALUE) &&
@ -1326,7 +1656,7 @@ SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttcmd (void) static t_stat sim_os_ttcmd (void)
{ {
if (sim_log) { if (sim_log) {
fflush (sim_log); fflush (sim_log);
@ -1340,19 +1670,19 @@ if ((std_input) && /* If Not Background pro
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttclose (void) static t_stat sim_os_ttclose (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_bool sim_os_ttisatty (void) static t_bool sim_os_ttisatty (void)
{ {
DWORD Mode; DWORD Mode;
return (std_input) && (std_input != INVALID_HANDLE_VALUE) && GetConsoleMode (std_input, &Mode); return (std_input) && (std_input != INVALID_HANDLE_VALUE) && GetConsoleMode (std_input, &Mode);
} }
t_stat sim_os_poll_kbd (void) static t_stat sim_os_poll_kbd (void)
{ {
int c = -1; int c = -1;
DWORD nkbevents, nkbevent; DWORD nkbevents, nkbevent;
@ -1395,7 +1725,7 @@ if ((sim_brk_char && ((c & 0177) == sim_brk_char)) || (c & SCPE_BREAK))
return c | SCPE_KFLAG; return c | SCPE_KFLAG;
} }
t_bool sim_os_poll_kbd_ready (int ms_timeout) static t_bool sim_os_poll_kbd_ready (int ms_timeout)
{ {
sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_poll_kbd_ready()\n"); sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_poll_kbd_ready()\n");
if ((std_input == NULL) || /* No keyboard for */ if ((std_input == NULL) || /* No keyboard for */
@ -1406,7 +1736,7 @@ if ((std_input == NULL) || /* No keyboard for */
return (WAIT_OBJECT_0 == WaitForSingleObject (std_input, ms_timeout)); return (WAIT_OBJECT_0 == WaitForSingleObject (std_input, ms_timeout));
} }
t_stat sim_os_putchar (int32 c) static t_stat sim_os_putchar (int32 c)
{ {
DWORD unused; DWORD unused;
@ -1421,32 +1751,32 @@ return SCPE_OK;
#include <conio.h> #include <conio.h>
t_stat sim_os_ttinit (void) static t_stat sim_os_ttinit (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttrun (void) static t_stat sim_os_ttrun (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttcmd (void) static t_stat sim_os_ttcmd (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttclose (void) static t_stat sim_os_ttclose (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_bool sim_os_ttisatty (void) static t_bool sim_os_ttisatty (void)
{ {
return 1; return 1;
} }
t_stat sim_os_poll_kbd (void) static t_stat sim_os_poll_kbd (void)
{ {
int c; int c;
@ -1477,13 +1807,13 @@ if (sim_brk_char && ((c & 0177) == sim_brk_char))
return c | SCPE_KFLAG; return c | SCPE_KFLAG;
} }
t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */ static t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */
{ {
sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */ sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */
return TRUE; /* force a poll */ return TRUE; /* force a poll */
} }
t_stat sim_os_putchar (int32 c) static t_stat sim_os_putchar (int32 c)
{ {
if (c != 0177) { if (c != 0177) {
#if defined (__EMX__) #if defined (__EMX__)
@ -1609,7 +1939,7 @@ int ps_getch(void) {
/* Note that this only works if the call to sim_ttinit comes before any output to the console */ /* Note that this only works if the call to sim_ttinit comes before any output to the console */
t_stat sim_os_ttinit (void) { static t_stat sim_os_ttinit (void) {
int i; int i;
/* this blank will later be replaced by the number of characters */ /* this blank will later be replaced by the number of characters */
char title[50] = " "; char title[50] = " ";
@ -1632,27 +1962,27 @@ t_stat sim_os_ttinit (void) {
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttrun (void) static t_stat sim_os_ttrun (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttcmd (void) static t_stat sim_os_ttcmd (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttclose (void) static t_stat sim_os_ttclose (void)
{ {
return SCPE_OK; return SCPE_OK;
} }
t_bool sim_os_ttisatty (void) static t_bool sim_os_ttisatty (void)
{ {
return 1; return 1;
} }
t_stat sim_os_poll_kbd (void) static t_stat sim_os_poll_kbd (void)
{ {
int c; int c;
@ -1667,13 +1997,13 @@ if (sim_brk_char && ((c & 0177) == sim_brk_char))
return c | SCPE_KFLAG; return c | SCPE_KFLAG;
} }
t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */ static t_bool sim_os_poll_kbd_ready (int ms_timeout) /* Don't know how to do this on this platform */
{ {
sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */ sim_os_ms_sleep (MIN(20,ms_timeout)); /* Wait a little */
return TRUE; /* force a poll */ return TRUE; /* force a poll */
} }
t_stat sim_os_putchar (int32 c) static t_stat sim_os_putchar (int32 c)
{ {
if (c != 0177) { if (c != 0177) {
putchar (c); putchar (c);
@ -1695,7 +2025,7 @@ struct tchars cmdtchars,runtchars; /* V7 editing */
struct ltchars cmdltchars,runltchars; /* 4.2 BSD editing */ struct ltchars cmdltchars,runltchars; /* 4.2 BSD editing */
int cmdfl,runfl; /* TTY flags */ int cmdfl,runfl; /* TTY flags */
t_stat sim_os_ttinit (void) static t_stat sim_os_ttinit (void)
{ {
cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */ cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */
runfl = cmdfl | FNDELAY; runfl = cmdfl | FNDELAY;
@ -1722,7 +2052,7 @@ runltchars.t_lnextc = 0xFF;
return SCPE_OK; /* return success */ return SCPE_OK; /* return success */
} }
t_stat sim_os_ttrun (void) static t_stat sim_os_ttrun (void)
{ {
runtchars.t_intrc = sim_int_char; /* in case changed */ runtchars.t_intrc = sim_int_char; /* in case changed */
fcntl (0, F_SETFL, runfl); /* non-block mode */ fcntl (0, F_SETFL, runfl); /* non-block mode */
@ -1736,7 +2066,7 @@ nice (10); /* lower priority */
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttcmd (void) static t_stat sim_os_ttcmd (void)
{ {
nice (-10); /* restore priority */ nice (-10); /* restore priority */
fcntl (0, F_SETFL, cmdfl); /* block mode */ fcntl (0, F_SETFL, cmdfl); /* block mode */
@ -1749,17 +2079,17 @@ if (ioctl (0, TIOCSLTC, &cmdltchars) < 0)
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttclose (void) static t_stat sim_os_ttclose (void)
{ {
return sim_ttcmd (); return sim_ttcmd ();
} }
t_bool sim_os_ttisatty (void) static t_bool sim_os_ttisatty (void)
{ {
return isatty (0); return isatty (0);
} }
t_stat sim_os_poll_kbd (void) static static t_stat sim_os_poll_kbd (void)
{ {
int status; int status;
unsigned char buf[1]; unsigned char buf[1];
@ -1771,7 +2101,7 @@ if (sim_brk_char && (buf[0] == sim_brk_char))
else return (buf[0] | SCPE_KFLAG); else return (buf[0] | SCPE_KFLAG);
} }
t_bool sim_os_poll_kbd_ready (int ms_timeout) static t_bool sim_os_poll_kbd_ready (int ms_timeout)
{ {
fd_set readfds; fd_set readfds;
struct timeval timeout; struct timeval timeout;
@ -1787,7 +2117,7 @@ timeout.tv_usec = (ms_timeout*1000)%1000000;
return (1 == select (1, &readfds, NULL, NULL, &timeout)); return (1 == select (1, &readfds, NULL, NULL, &timeout));
} }
t_stat sim_os_putchar (int32 out) static t_stat sim_os_putchar (int32 out)
{ {
char c; char c;
@ -1806,7 +2136,7 @@ return SCPE_OK;
struct termios cmdtty, runtty; struct termios cmdtty, runtty;
static int prior_norm = 1; static int prior_norm = 1;
t_stat sim_os_ttinit (void) static t_stat sim_os_ttinit (void)
{ {
if (!isatty (fileno (stdin))) /* skip if !tty */ if (!isatty (fileno (stdin))) /* skip if !tty */
return SCPE_OK; return SCPE_OK;
@ -1848,7 +2178,7 @@ runtty.c_cc[VSTATUS] = 0;
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttrun (void) static t_stat sim_os_ttrun (void)
{ {
if (!isatty (fileno (stdin))) /* skip if !tty */ if (!isatty (fileno (stdin))) /* skip if !tty */
return SCPE_OK; return SCPE_OK;
@ -1863,7 +2193,7 @@ if (prior_norm) { /* at normal pri? */
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttcmd (void) static t_stat sim_os_ttcmd (void)
{ {
if (!isatty (fileno (stdin))) /* skip if !tty */ if (!isatty (fileno (stdin))) /* skip if !tty */
return SCPE_OK; return SCPE_OK;
@ -1877,17 +2207,17 @@ if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0)
return SCPE_OK; return SCPE_OK;
} }
t_stat sim_os_ttclose (void) static t_stat sim_os_ttclose (void)
{ {
return sim_ttcmd (); return sim_ttcmd ();
} }
t_bool sim_os_ttisatty (void) static t_bool sim_os_ttisatty (void)
{ {
return isatty (fileno (stdin)); return isatty (fileno (stdin));
} }
t_stat sim_os_poll_kbd (void) static t_stat sim_os_poll_kbd (void)
{ {
int status; int status;
unsigned char buf[1]; unsigned char buf[1];
@ -1899,7 +2229,7 @@ if (sim_brk_char && (buf[0] == sim_brk_char))
else return (buf[0] | SCPE_KFLAG); else return (buf[0] | SCPE_KFLAG);
} }
t_bool sim_os_poll_kbd_ready (int ms_timeout) static t_bool sim_os_poll_kbd_ready (int ms_timeout)
{ {
fd_set readfds; fd_set readfds;
struct timeval timeout; struct timeval timeout;
@ -1915,7 +2245,7 @@ timeout.tv_usec = (ms_timeout*1000)%1000000;
return (1 == select (1, &readfds, NULL, NULL, &timeout)); return (1 == select (1, &readfds, NULL, NULL, &timeout));
} }
t_stat sim_os_putchar (int32 out) static t_stat sim_os_putchar (int32 out)
{ {
char c; char c;

View file

@ -52,6 +52,7 @@
#define TT_GET_MODE(x) (((x) >> TTUF_V_MODE) & TTUF_M_MODE) #define TT_GET_MODE(x) (((x) >> TTUF_V_MODE) & TTUF_M_MODE)
t_stat sim_set_console (int32 flag, char *cptr); t_stat sim_set_console (int32 flag, char *cptr);
t_stat sim_set_remote_console (int32 flag, char *cptr);
t_stat sim_set_kmap (int32 flag, char *cptr); t_stat sim_set_kmap (int32 flag, char *cptr);
t_stat sim_set_telnet (int32 flag, char *cptr); t_stat sim_set_telnet (int32 flag, char *cptr);
t_stat sim_set_notelnet (int32 flag, char *cptr); t_stat sim_set_notelnet (int32 flag, char *cptr);
@ -68,6 +69,7 @@ t_stat sim_set_cons_nolog (int32 flg, char *cptr);
t_stat sim_set_deboff (int32 flag, char *cptr); t_stat sim_set_deboff (int32 flag, char *cptr);
t_stat sim_set_pchar (int32 flag, char *cptr); t_stat sim_set_pchar (int32 flag, char *cptr);
t_stat sim_show_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_kmap (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_kmap (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_telnet (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_telnet (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);

View file

@ -273,8 +273,9 @@ typedef uint32 t_addr;
#define SCPE_TTMO (SCPE_BASE + 40) /* Telnet conn timeout */ #define SCPE_TTMO (SCPE_BASE + 40) /* Telnet conn timeout */
#define SCPE_STALL (SCPE_BASE + 41) /* Telnet conn stall */ #define SCPE_STALL (SCPE_BASE + 41) /* Telnet conn stall */
#define SCPE_AFAIL (SCPE_BASE + 42) /* assert failed */ #define SCPE_AFAIL (SCPE_BASE + 42) /* assert failed */
#define SCPE_INVREM (SCPE_BASE + 43) /* invalid remote console command */
#define SCPE_MAX_ERR (SCPE_BASE + 43) /* Maximum SCPE Error Value */ #define SCPE_MAX_ERR (SCPE_BASE + 44) /* Maximum SCPE Error Value */
#define SCPE_KFLAG 0x1000 /* tti data flag */ #define SCPE_KFLAG 0x1000 /* tti data flag */
#define SCPE_BREAK 0x2000 /* tti break flag */ #define SCPE_BREAK 0x2000 /* tti break flag */
#define SCPE_NOMESSAGE 0x10000000 /* message display supression flag */ #define SCPE_NOMESSAGE 0x10000000 /* message display supression flag */