Added Buffered Console Capabilities
A key capability needed to support simulators running with background execution is the ability to have a Telnet connected console which isn’t continuously connected. This feature is called a Buffered Telnet console. Absolutely nothing changes for someone not interested in using the feature. However, if someone is interested in the feature, the following SCP commands are available: sim> SET CONSOLE TELNET=port ! Unchanged sim> SET CONSOLE TELNET=BUFFERED{=buffersize} ! buffersize defaults to 32K sim> SET CONSOLE TELNET=UNBUFFERED ! restores normal behavior sim> SET CONSOLE TELNET=NOBUFFERED ! synonym for UNBUFFERED sim> SET CONSOLE TELNET=LOG=logdestination ! enables logging of Telnet session traffic (potentially separate from destination specified by SET CONSOLE LOG=conlogdest) sim> SET CONSOLE TELNET=NOLOG ! turns off specific logging of Telnet session sim> SET CONSOLE TELNET=LOG=conlogdest ! turns on logging all console traffic (unless the telnet session logging is also specified). The logdestinations for any of the logging/debugging commands can now be: LOG, DEBUG, STDOUT, STDERR or any file specification (caps are not required, but these names are reserved to indicate the current destination of the specified file handles (sim_log, sim_deb, stdout, stderr). When a Console Telnet session is Buffered, a simulator will start (via BOOT CPU or whatever is appropriate for a particular simulator) without needing to have an active telnet connection. When a Telnet connection comes along for the telnet port, the contents of the saved buffer (which wraps on overflow) are presented on the telnet session as output before session traffic. This allows the connecting telnet client to see what happened before he connected since the likely reason he might be connecting to the console of a background simulator is to troubleshoot unusual behavior. The current structure has the optional ability to log the Telnet session separately from the simulator output (i.e. ini file command execution) is potentially useful when you need to review what the simulator may have output which may be difficult to find in and amongst the possibly verbose Operating system console output. If someone doesn’t use “SET CONSOLE TELNET=LOG=logdestination”, then the original strategy of logging all output to the target specified by “SET CONSOLE LOG=logdestination” is preserved. Looking at the isolated console output might be more interesting if/when control flow scp commands are ever implemented (ON,GOTO, RETURN, etc.)
This commit is contained in:
parent
35eac703c3
commit
454b706a11
6 changed files with 540 additions and 128 deletions
3
scp.c
3
scp.c
|
@ -377,9 +377,10 @@ static uint32 sim_rtime;
|
||||||
static int32 noqueue_time;
|
static int32 noqueue_time;
|
||||||
volatile int32 stop_cpu = 0;
|
volatile int32 stop_cpu = 0;
|
||||||
t_value *sim_eval = NULL;
|
t_value *sim_eval = NULL;
|
||||||
int32 sim_deb_close = 0; /* 1 = close debug */
|
|
||||||
FILE *sim_log = NULL; /* log file */
|
FILE *sim_log = NULL; /* log file */
|
||||||
|
FILEREF *sim_log_ref = NULL; /* log file file reference */
|
||||||
FILE *sim_deb = NULL; /* debug file */
|
FILE *sim_deb = NULL; /* debug file */
|
||||||
|
FILEREF *sim_deb_ref = NULL; /* debug file file reference */
|
||||||
static SCHTAB sim_stab;
|
static SCHTAB sim_stab;
|
||||||
|
|
||||||
static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) };
|
static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) };
|
||||||
|
|
402
sim_console.c
402
sim_console.c
|
@ -23,6 +23,27 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
20-Jan-11 MP Fixed support for BREAK key on Windows to account
|
||||||
|
for/ignore other keyboard Meta characters.
|
||||||
|
18-Jan-11 MP Added log file reference count support
|
||||||
|
17-Jan-11 MP Added support for a "Buffered" behaviors which include:
|
||||||
|
- If Buffering is enabled and Telnet is enabled, a
|
||||||
|
telnet connection is not required for simulator
|
||||||
|
operation (instruction execution).
|
||||||
|
- If Buffering is enabled, all console output is
|
||||||
|
written to the buffer at all times (deleting the
|
||||||
|
oldest buffer contents on overflow).
|
||||||
|
- when a connection is established on the console
|
||||||
|
telnet port, the whole contents of the Buffer is
|
||||||
|
presented on the telnet session and connection
|
||||||
|
will then proceed as if the connection had always
|
||||||
|
been there.
|
||||||
|
This concept allows a simulator to run in the background
|
||||||
|
and when needed a console session to be established.
|
||||||
|
The "when needed" case usually will be interested in
|
||||||
|
what already happened before looking to address what
|
||||||
|
to do, hence the buffer contents being presented.
|
||||||
|
28-Dec-10 MP Added support for BREAK key on Windows
|
||||||
30-Sep-06 RMS Fixed non-printable characters in KSR mode
|
30-Sep-06 RMS Fixed non-printable characters in KSR mode
|
||||||
22-Jun-06 RMS Implemented SET/SHOW PCHAR
|
22-Jun-06 RMS Implemented SET/SHOW PCHAR
|
||||||
31-May-06 JDB Fixed bug if SET CONSOLE DEBUG with no argument
|
31-May-06 JDB Fixed bug if SET CONSOLE DEBUG with no argument
|
||||||
|
@ -62,6 +83,12 @@
|
||||||
sim_putchar_s - output character to console, stall if congested
|
sim_putchar_s - output character to console, stall if congested
|
||||||
sim_set_console - set console parameters
|
sim_set_console - set console parameters
|
||||||
sim_show_console - show console parameters
|
sim_show_console - show console parameters
|
||||||
|
sim_set_cons_buff - set console buffered
|
||||||
|
sim_set_cons_unbuff -set console unbuffered
|
||||||
|
sim_set_cons_log - set console log
|
||||||
|
sim_set_cons_nolog - set console nolog
|
||||||
|
sim_show_cons_buff - show console buffered
|
||||||
|
sim_show_cons_log - show console log
|
||||||
sim_tt_inpcvt - convert input character per mode
|
sim_tt_inpcvt - convert input character per mode
|
||||||
sim_tt_outcvt - convert output character per mode
|
sim_tt_outcvt - convert output character per mode
|
||||||
|
|
||||||
|
@ -104,8 +131,9 @@ TMLN sim_con_ldsc = { 0 }; /* console line descr */
|
||||||
TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */
|
TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */
|
||||||
|
|
||||||
extern volatile int32 stop_cpu;
|
extern volatile int32 stop_cpu;
|
||||||
extern int32 sim_quiet, sim_deb_close;
|
extern int32 sim_quiet;
|
||||||
extern FILE *sim_log, *sim_deb;
|
extern FILE *sim_log, *sim_deb;
|
||||||
|
extern FILEREF *sim_log_ref, *sim_deb_ref;
|
||||||
extern DEVICE *sim_devices[];
|
extern DEVICE *sim_devices[];
|
||||||
|
|
||||||
/* Set/show data structures */
|
/* Set/show data structures */
|
||||||
|
@ -129,9 +157,19 @@ static SHTAB show_con_tab[] = {
|
||||||
{ "BRK", &sim_show_kmap, KMAP_BRK },
|
{ "BRK", &sim_show_kmap, KMAP_BRK },
|
||||||
{ "DEL", &sim_show_kmap, KMAP_DEL },
|
{ "DEL", &sim_show_kmap, KMAP_DEL },
|
||||||
{ "PCHAR", &sim_show_pchar, 0 },
|
{ "PCHAR", &sim_show_pchar, 0 },
|
||||||
{ "LOG", &sim_show_log, 0 },
|
{ "LOG", &sim_show_cons_log, 0 },
|
||||||
{ "TELNET", &sim_show_telnet, 0 },
|
{ "TELNET", &sim_show_telnet, 0 },
|
||||||
{ "DEBUG", &sim_show_debug, 0 },
|
{ "DEBUG", &sim_show_debug, 0 },
|
||||||
|
{ "BUFFERED", &sim_show_cons_buff, 0 },
|
||||||
|
{ NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static CTAB set_con_telnet_tab[] = {
|
||||||
|
{ "LOG", &sim_set_cons_log, 0 },
|
||||||
|
{ "NOLOG", &sim_set_cons_nolog, 0 },
|
||||||
|
{ "BUFFERED", &sim_set_cons_buff, 0 },
|
||||||
|
{ "NOBUFFERED", &sim_set_cons_unbuff, 0 },
|
||||||
|
{ "UNBUFFERED", &sim_set_cons_unbuff, 0 },
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -261,6 +299,7 @@ return SCPE_OK;
|
||||||
t_stat sim_set_logon (int32 flag, char *cptr)
|
t_stat sim_set_logon (int32 flag, char *cptr)
|
||||||
{
|
{
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
if ((cptr == NULL) || (*cptr == 0)) /* need arg */
|
if ((cptr == NULL) || (*cptr == 0)) /* need arg */
|
||||||
return SCPE_2FARG;
|
return SCPE_2FARG;
|
||||||
|
@ -268,12 +307,14 @@ cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
|
||||||
if (*cptr != 0) /* now eol? */
|
if (*cptr != 0) /* now eol? */
|
||||||
return SCPE_2MARG;
|
return SCPE_2MARG;
|
||||||
sim_set_logoff (0, NULL); /* close cur log */
|
sim_set_logoff (0, NULL); /* close cur log */
|
||||||
sim_log = sim_fopen (gbuf, "a"); /* open log */
|
r = sim_open_logfile (gbuf, FALSE, &sim_log, &sim_log_ref); /* open log */
|
||||||
if (sim_log == NULL) /* error? */
|
if (r != SCPE_OK) /* error? */
|
||||||
return SCPE_OPENERR;
|
return r;
|
||||||
if (!sim_quiet)
|
if (!sim_quiet)
|
||||||
printf ("Logging to file \"%s\"\n", gbuf);
|
printf ("Logging to file \"%s\"\n",
|
||||||
fprintf (sim_log, "Logging to file \"%s\"\n", gbuf); /* start of log */
|
sim_logfile_name (sim_log, sim_log_ref));
|
||||||
|
fprintf (sim_log, "Logging to file \"%s\"\n",
|
||||||
|
sim_logfile_name (sim_log, sim_log_ref)); /* start of log */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,8 +328,8 @@ if (sim_log == NULL) /* no log? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
if (!sim_quiet)
|
if (!sim_quiet)
|
||||||
printf ("Log file closed\n");
|
printf ("Log file closed\n");
|
||||||
fprintf (sim_log, "Log file closed\n"); /* close log */
|
fprintf (sim_log, "Log file closed\n");
|
||||||
fclose (sim_log);
|
sim_close_logfile (&sim_log_ref); /* close log */
|
||||||
sim_log = NULL;
|
sim_log = NULL;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -300,8 +341,8 @@ t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
||||||
if (cptr && (*cptr != 0))
|
if (cptr && (*cptr != 0))
|
||||||
return SCPE_2MARG;
|
return SCPE_2MARG;
|
||||||
if (sim_log)
|
if (sim_log)
|
||||||
fputs ("Logging enabled\n", st);
|
fprintf (st, "Logging enabled to %s\n", sim_logfile_name (sim_log, sim_log_ref));
|
||||||
else fputs ("Logging disabled\n", st);
|
else fprintf (st, "Logging disabled\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,34 +350,24 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat sim_set_debon (int32 flag, char *cptr)
|
t_stat sim_set_debon (int32 flag, char *cptr)
|
||||||
{
|
{
|
||||||
char *tptr, gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
if ((cptr == NULL) || (*cptr == 0)) /* too few arguments? */
|
if ((cptr == NULL) || (*cptr == 0)) /* need arg */
|
||||||
return SCPE_2FARG;
|
return SCPE_2FARG;
|
||||||
tptr = get_glyph (cptr, gbuf, 0); /* get file name */
|
cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
|
||||||
if (*tptr != 0) /* now eol? */
|
if (*cptr != 0) /* now eol? */
|
||||||
return SCPE_2MARG;
|
return SCPE_2MARG;
|
||||||
sim_set_deboff (0, NULL); /* close cur debug */
|
r = sim_open_logfile (gbuf, FALSE, &sim_deb, &sim_deb_ref);
|
||||||
if (strcmp (gbuf, "LOG") == 0) { /* debug to log? */
|
|
||||||
if (sim_log == NULL) /* any log? */
|
if (r != SCPE_OK)
|
||||||
return SCPE_ARG;
|
return r;
|
||||||
sim_deb = sim_log;
|
|
||||||
}
|
|
||||||
else if (strcmp (gbuf, "STDOUT") == 0) /* debug to stdout? */
|
|
||||||
sim_deb = stdout;
|
|
||||||
else if (strcmp (gbuf, "STDERR") == 0) /* debug to stderr? */
|
|
||||||
sim_deb = stderr;
|
|
||||||
else {
|
|
||||||
cptr = get_glyph_nc (cptr, gbuf, 0); /* reparse */
|
|
||||||
sim_deb = sim_fopen (gbuf, "a"); /* open debug */
|
|
||||||
if (sim_deb == NULL) /* error? */
|
|
||||||
return SCPE_OPENERR;
|
|
||||||
sim_deb_close = 1; /* need close */
|
|
||||||
}
|
|
||||||
if (!sim_quiet)
|
if (!sim_quiet)
|
||||||
printf ("Debug output to \"%s\"\n", gbuf);
|
printf ("Debug output to \"%s\"\n",
|
||||||
|
sim_logfile_name (sim_deb, sim_deb_ref));
|
||||||
if (sim_log)
|
if (sim_log)
|
||||||
fprintf (sim_log, "Debug output to \"%s\"\n", gbuf);
|
fprintf (sim_log, "Debug output to \"%s\"\n",
|
||||||
|
sim_logfile_name (sim_deb, sim_deb_ref));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,18 +375,18 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat sim_set_deboff (int32 flag, char *cptr)
|
t_stat sim_set_deboff (int32 flag, char *cptr)
|
||||||
{
|
{
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
if (cptr && (*cptr != 0)) /* now eol? */
|
if (cptr && (*cptr != 0)) /* now eol? */
|
||||||
return SCPE_2MARG;
|
return SCPE_2MARG;
|
||||||
if (sim_deb == NULL) /* no log? */
|
if (sim_deb == NULL) /* no log? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
r = sim_close_logfile (&sim_deb_ref);
|
||||||
|
sim_deb = NULL;
|
||||||
if (!sim_quiet)
|
if (!sim_quiet)
|
||||||
printf ("Debug output disabled\n");
|
printf ("Debug output disabled\n");
|
||||||
if (sim_log)
|
if (sim_log)
|
||||||
fprintf (sim_log, "Debug output disabled\n");
|
fprintf (sim_log, "Debug output disabled\n");
|
||||||
if (sim_deb_close) /* close if needed */
|
|
||||||
fclose (sim_deb);
|
|
||||||
sim_deb_close = 0;
|
|
||||||
sim_deb = NULL;
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,20 +397,41 @@ t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cpt
|
||||||
if (cptr && (*cptr != 0))
|
if (cptr && (*cptr != 0))
|
||||||
return SCPE_2MARG;
|
return SCPE_2MARG;
|
||||||
if (sim_deb)
|
if (sim_deb)
|
||||||
fputs ("Debug output enabled\n", st);
|
fprintf (st, "Debug output enabled\n", sim_logfile_name (sim_deb, sim_deb_ref));
|
||||||
else fputs ("Debug output disabled\n", st);
|
else fprintf (st, "Debug output disabled\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set console to Telnet port */
|
/* SET CONSOLE command */
|
||||||
|
|
||||||
t_stat sim_set_telnet (int32 flg, char *cptr)
|
/* Set console to Telnet port (and parameters) */
|
||||||
|
|
||||||
|
t_stat sim_set_telnet (int32 flag, char *cptr)
|
||||||
{
|
{
|
||||||
if ((cptr == NULL) || (*cptr == 0)) /* too few arguments? */
|
char *cvptr, gbuf[CBUFSIZE];
|
||||||
|
CTAB *ctptr;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if ((cptr == NULL) || (*cptr == 0))
|
||||||
return SCPE_2FARG;
|
return SCPE_2FARG;
|
||||||
if (sim_con_tmxr.master) /* already open? */
|
while (*cptr != 0) { /* do all mods */
|
||||||
return SCPE_ALATT;
|
cptr = get_glyph_nc (cptr, gbuf, ','); /* get modifier */
|
||||||
return tmxr_open_master (&sim_con_tmxr, cptr); /* open master socket */
|
if (cvptr = strchr (gbuf, '=')) /* = value? */
|
||||||
|
*cvptr++ = 0;
|
||||||
|
get_glyph (gbuf, gbuf, 0); /* modifier to UC */
|
||||||
|
if (isdigit (*gbuf)) {
|
||||||
|
if (sim_con_tmxr.master) return SCPE_ALATT; /* already open? */
|
||||||
|
return tmxr_open_master (&sim_con_tmxr, gbuf); /* open master socket */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (ctptr = find_ctab (set_con_telnet_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close console Telnet port */
|
/* Close console Telnet port */
|
||||||
|
@ -401,17 +453,167 @@ if (cptr && (*cptr != 0))
|
||||||
return SCPE_2MARG;
|
return SCPE_2MARG;
|
||||||
if (sim_con_tmxr.master == 0)
|
if (sim_con_tmxr.master == 0)
|
||||||
fprintf (st, "Connected to console window\n");
|
fprintf (st, "Connected to console window\n");
|
||||||
else if (sim_con_ldsc.conn == 0)
|
|
||||||
fprintf (st, "Listening on port %d\n", sim_con_tmxr.port);
|
|
||||||
else {
|
else {
|
||||||
|
if (sim_con_ldsc.conn == 0)
|
||||||
|
fprintf (st, "Listening on port %d\n", sim_con_tmxr.port);
|
||||||
|
else {
|
||||||
fprintf (st, "Listening on port %d, connected to socket %d\n",
|
fprintf (st, "Listening on port %d, connected to socket %d\n",
|
||||||
sim_con_tmxr.port, sim_con_ldsc.conn);
|
sim_con_tmxr.port, sim_con_ldsc.conn);
|
||||||
tmxr_fconns (st, &sim_con_ldsc, -1);
|
tmxr_fconns (st, &sim_con_ldsc, -1);
|
||||||
|
}
|
||||||
tmxr_fstats (st, &sim_con_ldsc, -1);
|
tmxr_fstats (st, &sim_con_ldsc, -1);
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set console to Buffering */
|
||||||
|
|
||||||
|
t_stat sim_set_cons_buff (int32 flg, char *cptr)
|
||||||
|
{
|
||||||
|
char cmdbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
sprintf(cmdbuf, "BUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
|
||||||
|
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set console to NoBuffering */
|
||||||
|
|
||||||
|
t_stat sim_set_cons_unbuff (int32 flg, char *cptr)
|
||||||
|
{
|
||||||
|
char cmdbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
sprintf(cmdbuf, "UNBUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
|
||||||
|
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set console to Logging */
|
||||||
|
|
||||||
|
t_stat sim_set_cons_log (int32 flg, char *cptr)
|
||||||
|
{
|
||||||
|
char cmdbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
sprintf(cmdbuf, "LOG%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
|
||||||
|
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set console to NoLogging */
|
||||||
|
|
||||||
|
t_stat sim_set_cons_nolog (int32 flg, char *cptr)
|
||||||
|
{
|
||||||
|
char cmdbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
sprintf(cmdbuf, "NOLOG%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
|
||||||
|
return tmxr_open_master (&sim_con_tmxr, cmdbuf); /* open master socket */
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat sim_show_cons_log (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, char *cptr)
|
||||||
|
{
|
||||||
|
if (cptr && (*cptr != 0))
|
||||||
|
return SCPE_2MARG;
|
||||||
|
if (sim_con_tmxr.ldsc->txlog)
|
||||||
|
fprintf (st, "Log File being written to %s\n", sim_con_tmxr.ldsc->txlogname);
|
||||||
|
else
|
||||||
|
fprintf (st, "No Logging\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat sim_show_cons_buff (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, char *cptr)
|
||||||
|
{
|
||||||
|
if (cptr && (*cptr != 0))
|
||||||
|
return SCPE_2MARG;
|
||||||
|
if (!sim_con_tmxr.buffered)
|
||||||
|
fprintf (st, "Unbuffered\n");
|
||||||
|
else
|
||||||
|
fprintf (st, "Buffer Size = %d\n", sim_con_tmxr.buffered);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Log File Open/Close/Show Support */
|
||||||
|
|
||||||
|
/* Open log file */
|
||||||
|
|
||||||
|
t_stat sim_open_logfile (char *filename, t_bool binary, FILE **pf, FILEREF **pref)
|
||||||
|
{
|
||||||
|
char *tptr, gbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
*pref = NULL;
|
||||||
|
if ((filename == NULL) || (*filename == 0)) /* too few arguments? */
|
||||||
|
return SCPE_2FARG;
|
||||||
|
tptr = get_glyph (filename, gbuf, 0);
|
||||||
|
if (*tptr != 0) /* now eol? */
|
||||||
|
return SCPE_2MARG;
|
||||||
|
sim_close_logfile (pref);
|
||||||
|
*pf = NULL;
|
||||||
|
if (strcmp (gbuf, "LOG") == 0) { /* output to log? */
|
||||||
|
if (sim_log == NULL) /* any log? */
|
||||||
|
return SCPE_ARG;
|
||||||
|
*pf = sim_log;
|
||||||
|
*pref = sim_log_ref;
|
||||||
|
if (*pref)
|
||||||
|
++(*pref)->refcount;
|
||||||
|
}
|
||||||
|
else if (strcmp (gbuf, "DEBUG") == 0) { /* output to debug? */
|
||||||
|
if (sim_debug == NULL) /* any debug? */
|
||||||
|
return SCPE_ARG;
|
||||||
|
*pf = sim_deb;
|
||||||
|
*pref = sim_deb_ref;
|
||||||
|
if (*pref)
|
||||||
|
++(*pref)->refcount;
|
||||||
|
}
|
||||||
|
else if (strcmp (gbuf, "STDOUT") == 0) /* output to stdout? */
|
||||||
|
*pf = stdout;
|
||||||
|
else if (strcmp (gbuf, "STDERR") == 0) /* output to stderr? */
|
||||||
|
*pf = stderr;
|
||||||
|
else {
|
||||||
|
*pref = calloc (1, sizeof(**pref));
|
||||||
|
if (!*pref)
|
||||||
|
return SCPE_MEM;
|
||||||
|
get_glyph_nc (filename, gbuf, 0); /* reparse */
|
||||||
|
strncpy ((*pref)->name, gbuf, sizeof((*pref)->name)-1);
|
||||||
|
*pf = sim_fopen (gbuf, (binary ? "ab" : "a")); /* open file */
|
||||||
|
if (*pf == NULL) { /* error? */
|
||||||
|
free (*pref);
|
||||||
|
*pref = NULL;
|
||||||
|
return SCPE_OPENERR;
|
||||||
|
}
|
||||||
|
(*pref)->file = *pf;
|
||||||
|
(*pref)->refcount = 1; /* need close */
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close log file */
|
||||||
|
|
||||||
|
t_stat sim_close_logfile (FILEREF **pref)
|
||||||
|
{
|
||||||
|
if (NULL == *pref)
|
||||||
|
return SCPE_OK;
|
||||||
|
(*pref)->refcount = (*pref)->refcount - 1;
|
||||||
|
if ((*pref)->refcount > 0)
|
||||||
|
return SCPE_OK;
|
||||||
|
fclose ((*pref)->file);
|
||||||
|
free (*pref);
|
||||||
|
*pref = NULL;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show logfile support routine */
|
||||||
|
|
||||||
|
const char *sim_logfile_name (FILE *st, FILEREF *ref)
|
||||||
|
{
|
||||||
|
if (!st)
|
||||||
|
return "";
|
||||||
|
if (st == stdout)
|
||||||
|
return "STDOUT";
|
||||||
|
if (st == stderr)
|
||||||
|
return "STDERR";
|
||||||
|
if (!ref)
|
||||||
|
return "";
|
||||||
|
return ref->name;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check connection before executing */
|
/* Check connection before executing */
|
||||||
|
|
||||||
t_stat sim_check_console (int32 sec)
|
t_stat sim_check_console (int32 sec)
|
||||||
|
@ -420,11 +622,16 @@ int32 c, i;
|
||||||
|
|
||||||
if (sim_con_tmxr.master == 0) /* not Telnet? done */
|
if (sim_con_tmxr.master == 0) /* not Telnet? done */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
if (sim_con_ldsc.conn) { /* connected? */
|
if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* connected or buffered ? */
|
||||||
tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */
|
tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */
|
||||||
if (sim_con_ldsc.conn) /* still connected? */
|
if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* still connected? */
|
||||||
|
if (!sim_con_ldsc.conn) {
|
||||||
|
printf ("Running with Buffered Console\n"); /* print transition */
|
||||||
|
fflush (stdout);
|
||||||
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (i = 0; i < sec; i++) { /* loop */
|
for (i = 0; i < sec; i++) { /* loop */
|
||||||
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */
|
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */
|
||||||
sim_con_ldsc.rcve = 1; /* rcv enabled */
|
sim_con_ldsc.rcve = 1; /* rcv enabled */
|
||||||
|
@ -455,8 +662,14 @@ int32 c;
|
||||||
c = sim_os_poll_kbd (); /* get character */
|
c = sim_os_poll_kbd (); /* get character */
|
||||||
if ((c == SCPE_STOP) || (sim_con_tmxr.master == 0)) /* ^E or not Telnet? */
|
if ((c == SCPE_STOP) || (sim_con_tmxr.master == 0)) /* ^E or not Telnet? */
|
||||||
return c; /* in-window */
|
return c; /* in-window */
|
||||||
if (sim_con_ldsc.conn == 0) /* no Telnet conn? */
|
if (sim_con_ldsc.conn == 0) { /* no Telnet conn? */
|
||||||
return SCPE_LOST;
|
if (!sim_con_ldsc.txbfd) /* unbuffered? */
|
||||||
|
return SCPE_LOST; /* connection lost */
|
||||||
|
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */
|
||||||
|
sim_con_ldsc.rcve = 1; /* rcv enabled */
|
||||||
|
else /* fall through to poll reception */
|
||||||
|
return SCPE_OK; /* unconnected and buffered - nothing to receive */
|
||||||
|
}
|
||||||
tmxr_poll_rx (&sim_con_tmxr); /* poll for input */
|
tmxr_poll_rx (&sim_con_tmxr); /* poll for input */
|
||||||
if (c = tmxr_getc_ln (&sim_con_ldsc)) /* any char? */
|
if (c = tmxr_getc_ln (&sim_con_ldsc)) /* any char? */
|
||||||
return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG;
|
return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG;
|
||||||
|
@ -467,12 +680,19 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat sim_putchar (int32 c)
|
t_stat sim_putchar (int32 c)
|
||||||
{
|
{
|
||||||
if (sim_log) /* log file? */
|
if (sim_con_tmxr.master == 0) { /* not Telnet? */
|
||||||
|
if (sim_log) /* log file? */
|
||||||
fputc (c, sim_log);
|
fputc (c, sim_log);
|
||||||
if (sim_con_tmxr.master == 0) /* not Telnet? */
|
|
||||||
return sim_os_putchar (c); /* in-window version */
|
return sim_os_putchar (c); /* in-window version */
|
||||||
if (sim_con_ldsc.conn == 0) /* no Telnet conn? */
|
}
|
||||||
return SCPE_LOST;
|
if (sim_log && !sim_con_ldsc.txlog) /* log file, but no line log? */
|
||||||
|
fputc (c, sim_log);
|
||||||
|
if (sim_con_ldsc.conn == 0) { /* no Telnet conn? */
|
||||||
|
if (!sim_con_ldsc.txbfd) /* unbuffered? */
|
||||||
|
return SCPE_LOST; /* connection lost */
|
||||||
|
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */
|
||||||
|
sim_con_ldsc.rcve = 1; /* rcv enabled */
|
||||||
|
}
|
||||||
tmxr_putc_ln (&sim_con_ldsc, c); /* output char */
|
tmxr_putc_ln (&sim_con_ldsc, c); /* output char */
|
||||||
tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */
|
tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -485,8 +705,12 @@ t_stat r;
|
||||||
if (sim_log) fputc (c, sim_log); /* log file? */
|
if (sim_log) fputc (c, sim_log); /* log file? */
|
||||||
if (sim_con_tmxr.master == 0) /* not Telnet? */
|
if (sim_con_tmxr.master == 0) /* not Telnet? */
|
||||||
return sim_os_putchar (c); /* in-window version */
|
return sim_os_putchar (c); /* in-window version */
|
||||||
if (sim_con_ldsc.conn == 0) /* no Telnet conn? */
|
if (sim_con_ldsc.conn == 0) { /* no Telnet conn? */
|
||||||
return SCPE_LOST;
|
if (!sim_con_ldsc.txbfd) /* non-buffered Telnet conn? */
|
||||||
|
return SCPE_LOST; /* lost */
|
||||||
|
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) /* poll connect */
|
||||||
|
sim_con_ldsc.rcve = 1; /* rcv enabled */
|
||||||
|
}
|
||||||
if (sim_con_ldsc.xmte == 0) /* xmt disabled? */
|
if (sim_con_ldsc.xmte == 0) /* xmt disabled? */
|
||||||
r = SCPE_STALL;
|
r = SCPE_STALL;
|
||||||
else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */
|
else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */
|
||||||
|
@ -662,17 +886,42 @@ return SCPE_OK;
|
||||||
|
|
||||||
#elif defined (_WIN32)
|
#elif defined (_WIN32)
|
||||||
|
|
||||||
#include <conio.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#define RAW_MODE 0
|
#define RAW_MODE 0
|
||||||
static HANDLE std_input;
|
static HANDLE std_input;
|
||||||
|
static HANDLE std_output;
|
||||||
static DWORD saved_mode;
|
static DWORD saved_mode;
|
||||||
|
|
||||||
|
static BOOL WINAPI
|
||||||
|
ControlHandler(DWORD dwCtrlType)
|
||||||
|
{
|
||||||
|
DWORD Mode;
|
||||||
|
extern void int_handler (int sig);
|
||||||
|
|
||||||
|
switch (dwCtrlType)
|
||||||
|
{
|
||||||
|
case CTRL_BREAK_EVENT: // Use CTRL-Break or CTRL-C to simulate
|
||||||
|
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
|
||||||
|
int_handler(0);
|
||||||
|
return TRUE;
|
||||||
|
case CTRL_CLOSE_EVENT: // Window is Closing
|
||||||
|
case CTRL_LOGOFF_EVENT: // User is logging off
|
||||||
|
if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &Mode))
|
||||||
|
return TRUE; // Not our User, so ignore
|
||||||
|
case CTRL_SHUTDOWN_EVENT: // System is shutting down
|
||||||
|
int_handler(0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat sim_ttinit (void)
|
t_stat sim_ttinit (void)
|
||||||
{
|
{
|
||||||
|
SetConsoleCtrlHandler( ControlHandler, TRUE );
|
||||||
std_input = GetStdHandle (STD_INPUT_HANDLE);
|
std_input = GetStdHandle (STD_INPUT_HANDLE);
|
||||||
|
std_output = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||||
if ((std_input == INVALID_HANDLE_VALUE) ||
|
if ((std_input == INVALID_HANDLE_VALUE) ||
|
||||||
!GetConsoleMode (std_input, &saved_mode))
|
!GetConsoleMode (std_input, &saved_mode))
|
||||||
return SCPE_TTYERR;
|
return SCPE_TTYERR;
|
||||||
|
@ -710,24 +959,49 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat sim_os_poll_kbd (void)
|
t_stat sim_os_poll_kbd (void)
|
||||||
{
|
{
|
||||||
int c;
|
int c = -1;
|
||||||
|
DWORD nkbevents, nkbevent;
|
||||||
|
INPUT_RECORD rec;
|
||||||
|
extern int32 sim_switches;
|
||||||
|
|
||||||
if (!_kbhit ())
|
if (!GetNumberOfConsoleInputEvents(std_input, &nkbevents))
|
||||||
|
return SCPE_TTYERR;
|
||||||
|
while (c == -1) {
|
||||||
|
if (0 == nkbevents)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
c = _getch ();
|
if (!ReadConsoleInput(std_input, &rec, 1, &nkbevent))
|
||||||
|
return SCPE_TTYERR;
|
||||||
|
if (0 == nkbevent)
|
||||||
|
return SCPE_OK;
|
||||||
|
--nkbevents;
|
||||||
|
if (rec.EventType == KEY_EVENT) {
|
||||||
|
if (rec.Event.KeyEvent.bKeyDown) {
|
||||||
|
if (0 == rec.Event.KeyEvent.uChar.UnicodeChar) { /* Special Character/Keys? */
|
||||||
|
if (rec.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) /* Pause/Break Key */
|
||||||
|
c = sim_brk_char | SCPE_BREAK;
|
||||||
|
else
|
||||||
|
if (rec.Event.KeyEvent.wVirtualKeyCode == '2') /* ^@ */
|
||||||
|
c = 0; /* return NUL */
|
||||||
|
} else
|
||||||
|
c = rec.Event.KeyEvent.uChar.AsciiChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if ((c & 0177) == sim_del_char)
|
if ((c & 0177) == sim_del_char)
|
||||||
c = 0177;
|
c = 0177;
|
||||||
if ((c & 0177) == sim_int_char)
|
if ((c & 0177) == sim_int_char)
|
||||||
return SCPE_STOP;
|
return SCPE_STOP;
|
||||||
if (sim_brk_char && ((c & 0177) == sim_brk_char))
|
if ((sim_brk_char && ((c & 0177) == sim_brk_char)) || (c & SCPE_BREAK))
|
||||||
return SCPE_BREAK;
|
return SCPE_BREAK;
|
||||||
return c | SCPE_KFLAG;
|
return c | SCPE_KFLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat sim_os_putchar (int32 c)
|
t_stat sim_os_putchar (int32 c)
|
||||||
{
|
{
|
||||||
|
DWORD unused;
|
||||||
|
|
||||||
if (c != 0177)
|
if (c != 0177)
|
||||||
_putch (c);
|
WriteConsoleA(std_output, &c, 1, &unused, NULL);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
17-Jan-11 MP Added buffered line capabilities
|
||||||
22-Jun-06 RMS Implemented SET/SHOW PCHAR
|
22-Jun-06 RMS Implemented SET/SHOW PCHAR
|
||||||
22-Nov-05 RMS Added central input/output conversion support
|
22-Nov-05 RMS Added central input/output conversion support
|
||||||
05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy
|
05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy
|
||||||
|
@ -57,6 +58,10 @@ t_stat sim_set_notelnet (int32 flag, char *cptr);
|
||||||
t_stat sim_set_logon (int32 flag, char *cptr);
|
t_stat sim_set_logon (int32 flag, char *cptr);
|
||||||
t_stat sim_set_logoff (int32 flag, char *cptr);
|
t_stat sim_set_logoff (int32 flag, char *cptr);
|
||||||
t_stat sim_set_debon (int32 flag, char *cptr);
|
t_stat sim_set_debon (int32 flag, char *cptr);
|
||||||
|
t_stat sim_set_cons_buff (int32 flg, char *cptr);
|
||||||
|
t_stat sim_set_cons_unbuff (int32 flg, char *cptr);
|
||||||
|
t_stat sim_set_cons_log (int32 flg, char *cptr);
|
||||||
|
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);
|
||||||
|
@ -65,7 +70,12 @@ t_stat sim_show_telnet (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cp
|
||||||
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);
|
||||||
t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||||
t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||||
|
t_stat sim_show_cons_buff (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||||
|
t_stat sim_show_cons_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||||
t_stat sim_check_console (int32 sec);
|
t_stat sim_check_console (int32 sec);
|
||||||
|
t_stat sim_open_logfile (char *filename, t_bool binary, FILE **pf, FILEREF **pref);
|
||||||
|
t_stat sim_close_logfile (FILEREF **pref);
|
||||||
|
const char *sim_logfile_name (FILE *st, FILEREF *ref);
|
||||||
t_stat sim_poll_kbd (void);
|
t_stat sim_poll_kbd (void);
|
||||||
t_stat sim_putchar (int32 c);
|
t_stat sim_putchar (int32 c);
|
||||||
t_stat sim_putchar_s (int32 c);
|
t_stat sim_putchar_s (int32 c);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
18-Jan-11 MP Added log file reference count support
|
||||||
21-Jul-08 RMS Removed inlining support
|
21-Jul-08 RMS Removed inlining support
|
||||||
28-May-08 RMS Added inlining support
|
28-May-08 RMS Added inlining support
|
||||||
28-Jun-07 RMS Added IA64 VMS support (from Norm Lastovica)
|
28-Jun-07 RMS Added IA64 VMS support (from Norm Lastovica)
|
||||||
|
@ -484,6 +485,13 @@ struct sim_debtab {
|
||||||
#define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m)))
|
#define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m)))
|
||||||
#define DEBUG_PRJ(d,m) (sim_deb && (d->dctrl & (m)))
|
#define DEBUG_PRJ(d,m) (sim_deb && (d->dctrl & (m)))
|
||||||
|
|
||||||
|
/* File Reference */
|
||||||
|
struct sim_fileref {
|
||||||
|
char name[CBUFSIZE]; /* file name */
|
||||||
|
FILE *file; /* file handle */
|
||||||
|
int32 refcount; /* reference count */
|
||||||
|
};
|
||||||
|
|
||||||
/* The following macros define structure contents */
|
/* The following macros define structure contents */
|
||||||
|
|
||||||
#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0
|
#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0
|
||||||
|
@ -520,6 +528,7 @@ typedef struct sim_mtab MTAB;
|
||||||
typedef struct sim_schtab SCHTAB;
|
typedef struct sim_schtab SCHTAB;
|
||||||
typedef struct sim_brktab BRKTAB;
|
typedef struct sim_brktab BRKTAB;
|
||||||
typedef struct sim_debtab DEBTAB;
|
typedef struct sim_debtab DEBTAB;
|
||||||
|
typedef struct sim_fileref FILEREF;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
|
|
||||||
|
|
223
sim_tmxr.c
223
sim_tmxr.c
|
@ -26,6 +26,7 @@
|
||||||
Based on the original DZ11 simulator by Thord Nilson, as updated by
|
Based on the original DZ11 simulator by Thord Nilson, as updated by
|
||||||
Arthur Krewat.
|
Arthur Krewat.
|
||||||
|
|
||||||
|
17-Jan-11 MP Added Buffered line capabilities
|
||||||
20-Nov-08 RMS Added three new standardized SHOW routines
|
20-Nov-08 RMS Added three new standardized SHOW routines
|
||||||
30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation
|
30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation
|
||||||
27-May-08 JDB Added line connection order to tmxr_poll_conn,
|
27-May-08 JDB Added line connection order to tmxr_poll_conn,
|
||||||
|
@ -137,8 +138,12 @@ int32 tmxr_poll_conn (TMXR *mp)
|
||||||
SOCKET newsock;
|
SOCKET newsock;
|
||||||
TMLN *lp;
|
TMLN *lp;
|
||||||
int32 *op;
|
int32 *op;
|
||||||
int32 i, j;
|
int32 i, j, psave;
|
||||||
uint32 ipaddr;
|
uint32 ipaddr;
|
||||||
|
char cmsg[80];
|
||||||
|
char dmsg[80] = "";
|
||||||
|
char lmsg[80] = "";
|
||||||
|
char msgbuf[256];
|
||||||
static char mantra[] = {
|
static char mantra[] = {
|
||||||
TN_IAC, TN_WILL, TN_LINE,
|
TN_IAC, TN_WILL, TN_LINE,
|
||||||
TN_IAC, TN_WILL, TN_SGA,
|
TN_IAC, TN_WILL, TN_SGA,
|
||||||
|
@ -171,34 +176,38 @@ if (newsock != INVALID_SOCKET) { /* got a live one? */
|
||||||
lp = mp->ldsc + i; /* get line desc */
|
lp = mp->ldsc + i; /* get line desc */
|
||||||
lp->conn = newsock; /* record connection */
|
lp->conn = newsock; /* record connection */
|
||||||
lp->ipad = ipaddr; /* ip address */
|
lp->ipad = ipaddr; /* ip address */
|
||||||
|
sim_write_sock (newsock, mantra, sizeof(mantra));
|
||||||
|
sprintf (cmsg, "\n\r\nConnected to the %s simulator ", sim_name);
|
||||||
|
|
||||||
|
if (mp->dptr) { /* device defined? */
|
||||||
|
sprintf (dmsg, "%s device", /* report device name */
|
||||||
|
sim_dname (mp->dptr));
|
||||||
|
|
||||||
|
if (mp->lines > 1) /* more than one line? */
|
||||||
|
sprintf (lmsg, ", line %d", i); /* report the line number */
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf (msgbuf, "%s%s%s\r\n\n", cmsg, dmsg, lmsg);
|
||||||
lp->cnms = sim_os_msec (); /* time of conn */
|
lp->cnms = sim_os_msec (); /* time of conn */
|
||||||
lp->rxbpr = lp->rxbpi = 0; /* init buf pointers */
|
if (!mp->buffered) {
|
||||||
lp->txbpr = lp->txbpi = 0;
|
lp->txbpi = 0; /* init buf pointers */
|
||||||
lp->rxcnt = lp->txcnt = 0; /* init counters */
|
lp->txbpr = lp->txbsz - strlen (msgbuf);
|
||||||
|
lp->rxcnt = lp->txcnt = lp->txdrp = 0; /* init counters */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (lp->txcnt > lp->txbsz)
|
||||||
|
lp->txbpr = (lp->txbpi + 1) % lp->txbsz;
|
||||||
|
else
|
||||||
|
lp->txbpr = lp->txbsz - strlen (msgbuf);
|
||||||
lp->tsta = 0; /* init telnet state */
|
lp->tsta = 0; /* init telnet state */
|
||||||
lp->xmte = 1; /* enable transmit */
|
lp->xmte = 1; /* enable transmit */
|
||||||
lp->dstb = 0; /* default bin mode */
|
lp->dstb = 0; /* default bin mode */
|
||||||
sim_write_sock (newsock, mantra, 15);
|
psave = lp->txbpi; /* save insertion pointer */
|
||||||
tmxr_linemsg (lp, "\n\r\nConnected to the ");
|
lp->txbpi = lp->txbpr; /* insert connection message */
|
||||||
tmxr_linemsg (lp, sim_name);
|
tmxr_linemsg (lp, msgbuf); /* beginning of buffer */
|
||||||
tmxr_linemsg (lp, " simulator ");
|
lp->txbpi = psave; /* restore insertion pointer */
|
||||||
|
|
||||||
if (mp->dptr) { /* device defined? */
|
|
||||||
tmxr_linemsg (lp, sim_dname (mp->dptr)); /* report device name */
|
|
||||||
tmxr_linemsg (lp, " device");
|
|
||||||
|
|
||||||
if (mp->lines > 1) { /* more than one line? */
|
|
||||||
char line[20];
|
|
||||||
|
|
||||||
tmxr_linemsg (lp, ", line "); /* report the line number */
|
|
||||||
sprintf (line, "%i", i);
|
|
||||||
tmxr_linemsg (lp, line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmxr_linemsg (lp, "\r\n\n");
|
|
||||||
|
|
||||||
tmxr_poll_tx (mp); /* flush output */
|
tmxr_poll_tx (mp); /* flush output */
|
||||||
|
lp->txcnt -= strlen (msgbuf); /* adjust statistics */
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
} /* end if newsock */
|
} /* end if newsock */
|
||||||
|
@ -215,7 +224,8 @@ tmxr_send_buffered_data (lp); /* send buffered data */
|
||||||
sim_close_sock (lp->conn, 0); /* reset conn */
|
sim_close_sock (lp->conn, 0); /* reset conn */
|
||||||
lp->conn = lp->tsta = 0; /* reset state */
|
lp->conn = lp->tsta = 0; /* reset state */
|
||||||
lp->rxbpr = lp->rxbpi = 0;
|
lp->rxbpr = lp->rxbpi = 0;
|
||||||
lp->txbpr = lp->txbpi = 0;
|
if (!lp->txbfd)
|
||||||
|
lp->txbpr = lp->txbpi = 0;
|
||||||
lp->xmte = 1;
|
lp->xmte = 1;
|
||||||
lp->dstb = 0;
|
lp->dstb = 0;
|
||||||
return;
|
return;
|
||||||
|
@ -369,7 +379,7 @@ return;
|
||||||
|
|
||||||
int32 tmxr_rqln (TMLN *lp)
|
int32 tmxr_rqln (TMLN *lp)
|
||||||
{
|
{
|
||||||
return (lp->rxbpi - lp->rxbpr);
|
return (lp->rxbpi - lp->rxbpr + ((lp->rxbpi < lp->rxbpr)? TMXR_MAXBUF: 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove character p (and matching status) from line l input buffer */
|
/* Remove character p (and matching status) from line l input buffer */
|
||||||
|
@ -397,24 +407,29 @@ t_stat tmxr_putc_ln (TMLN *lp, int32 chr)
|
||||||
{
|
{
|
||||||
if (lp->txlog) /* log if available */
|
if (lp->txlog) /* log if available */
|
||||||
fputc (chr, lp->txlog);
|
fputc (chr, lp->txlog);
|
||||||
if (lp->conn == 0) /* no conn? lost */
|
if ((lp->conn == 0) && (!lp->txbfd)) /* no conn & not buffered? */
|
||||||
|
if (lp->txlog) /* if it was logged, we got it */
|
||||||
|
return SCPE_OK;
|
||||||
|
else {
|
||||||
|
++lp->txdrp; /* lost */
|
||||||
return SCPE_LOST;
|
return SCPE_LOST;
|
||||||
if (tmxr_tqln (lp) < (TMXR_MAXBUF - 1)) { /* room for char (+ IAC)? */
|
|
||||||
lp->txb[lp->txbpi] = (char) chr; /* buffer char */
|
|
||||||
lp->txbpi = lp->txbpi + 1; /* adv pointer */
|
|
||||||
if (lp->txbpi >= TMXR_MAXBUF) /* wrap? */
|
|
||||||
lp->txbpi = 0;
|
|
||||||
if ((char) chr == TN_IAC) { /* IAC? */
|
|
||||||
lp->txb[lp->txbpi] = (char) chr; /* IAC + IAC */
|
|
||||||
lp->txbpi = lp->txbpi + 1; /* adv pointer */
|
|
||||||
if (lp->txbpi >= TMXR_MAXBUF) /* wrap? */
|
|
||||||
lp->txbpi = 0;
|
|
||||||
}
|
}
|
||||||
if (tmxr_tqln (lp) > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */
|
#define TXBUF_AVAIL(lp) (lp->txbsz - tmxr_tqln (lp))
|
||||||
|
#define TXBUF_CHAR(lp, c) { \
|
||||||
|
lp->txb[lp->txbpi++] = (char)(c); \
|
||||||
|
lp->txbpi %= lp->txbsz; \
|
||||||
|
if (lp->txbpi == lp->txbpr) \
|
||||||
|
lp->txbpr = (1+lp->txbpr)%lp->txbsz, ++lp->txdrp; \
|
||||||
|
}
|
||||||
|
if ((lp->txbfd) || (TXBUF_AVAIL(lp) > 1)) { /* room for char (+ IAC)? */
|
||||||
|
if (TN_IAC == (char) chr) /* char == IAC ? */
|
||||||
|
TXBUF_CHAR (lp, TN_IAC); /* stuff extra IAC char */
|
||||||
|
TXBUF_CHAR (lp, chr); /* buffer char & adv pointer */
|
||||||
|
if ((!lp->txbfd) && (TXBUF_AVAIL (lp) <= TMXR_GUARD))/* near full? */
|
||||||
lp->xmte = 0; /* disable line */
|
lp->xmte = 0; /* disable line */
|
||||||
return SCPE_OK; /* char sent */
|
return SCPE_OK; /* char sent */
|
||||||
}
|
}
|
||||||
lp->xmte = 0; /* no room, dsbl line */
|
++lp->txdrp; lp->xmte = 0; /* no room, dsbl line */
|
||||||
return SCPE_STALL; /* char not sent */
|
return SCPE_STALL; /* char not sent */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,10 +475,10 @@ if (nbytes) { /* >0? write */
|
||||||
sbytes = sim_write_sock (lp->conn, /* write all data */
|
sbytes = sim_write_sock (lp->conn, /* write all data */
|
||||||
&(lp->txb[lp->txbpr]), nbytes);
|
&(lp->txb[lp->txbpr]), nbytes);
|
||||||
else sbytes = sim_write_sock (lp->conn, /* write to end buf */
|
else sbytes = sim_write_sock (lp->conn, /* write to end buf */
|
||||||
&(lp->txb[lp->txbpr]), TMXR_MAXBUF - lp->txbpr);
|
&(lp->txb[lp->txbpr]), lp->txbsz - lp->txbpr);
|
||||||
if (sbytes != SOCKET_ERROR) { /* ok? */
|
if (sbytes != SOCKET_ERROR) { /* ok? */
|
||||||
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
|
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
|
||||||
if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */
|
if (lp->txbpr >= lp->txbsz) /* wrap? */
|
||||||
lp->txbpr = 0;
|
lp->txbpr = 0;
|
||||||
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
||||||
nbytes = nbytes - sbytes;
|
nbytes = nbytes - sbytes;
|
||||||
|
@ -472,7 +487,7 @@ if (nbytes) { /* >0? write */
|
||||||
sbytes = sim_write_sock (lp->conn, lp->txb, nbytes);
|
sbytes = sim_write_sock (lp->conn, lp->txb, nbytes);
|
||||||
if (sbytes != SOCKET_ERROR) { /* ok */
|
if (sbytes != SOCKET_ERROR) { /* ok */
|
||||||
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
|
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
|
||||||
if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */
|
if (lp->txbpr >= lp->txbsz) /* wrap? */
|
||||||
lp->txbpr = 0;
|
lp->txbpr = 0;
|
||||||
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
||||||
nbytes = nbytes - sbytes;
|
nbytes = nbytes - sbytes;
|
||||||
|
@ -486,7 +501,7 @@ return nbytes;
|
||||||
|
|
||||||
int32 tmxr_tqln (TMLN *lp)
|
int32 tmxr_tqln (TMLN *lp)
|
||||||
{
|
{
|
||||||
return (lp->txbpi - lp->txbpr + ((lp->txbpi < lp->txbpr)? TMXR_MAXBUF: 0));
|
return (lp->txbpi - lp->txbpr + ((lp->txbpi < lp->txbpr)? lp->txbsz: 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open master socket */
|
/* Open master socket */
|
||||||
|
@ -498,6 +513,81 @@ SOCKET sock;
|
||||||
TMLN *lp;
|
TMLN *lp;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
|
if (!isdigit(*cptr)) {
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
cptr = get_glyph (cptr, gbuf, '=');
|
||||||
|
if (0 == MATCH_CMD (gbuf, "LOG")) {
|
||||||
|
if ((NULL == cptr) || ('\0' == *cptr))
|
||||||
|
return SCPE_2FARG;
|
||||||
|
strncpy(mp->logfiletmpl, cptr, sizeof(mp->logfiletmpl)-1);
|
||||||
|
for (i = 0; i < mp->lines; i++) {
|
||||||
|
lp = mp->ldsc + i;
|
||||||
|
sim_close_logfile (&lp->txlogref);
|
||||||
|
lp->txlog = NULL;
|
||||||
|
lp->txlogname = realloc(lp->txlogname, CBUFSIZE);
|
||||||
|
if (mp->lines > 1)
|
||||||
|
sprintf(lp->txlogname, "%s_%d", mp->logfiletmpl, i);
|
||||||
|
else
|
||||||
|
strcpy(lp->txlogname, mp->logfiletmpl);
|
||||||
|
r = sim_open_logfile (lp->txlogname, TRUE, &lp->txlog, &lp->txlogref);
|
||||||
|
if (r == SCPE_OK)
|
||||||
|
setvbuf(lp->txlog, NULL, _IOFBF, 65536);
|
||||||
|
else {
|
||||||
|
free (lp->txlogname);
|
||||||
|
lp->txlogname = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if ((0 == MATCH_CMD (gbuf, "NOBUFFERED")) ||
|
||||||
|
(0 == MATCH_CMD (gbuf, "UNBUFFERED"))) {
|
||||||
|
if (mp->buffered) {
|
||||||
|
mp->buffered = 0;
|
||||||
|
for (i = 0; i < mp->lines; i++) { /* default line buffers */
|
||||||
|
lp = mp->ldsc + i;
|
||||||
|
lp->txbsz = TMXR_MAXBUF;
|
||||||
|
lp->txb = (char *)realloc(lp->txb, lp->txbsz);
|
||||||
|
lp->txbfd = lp->txbpi = lp->txbpr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (0 == MATCH_CMD (gbuf, "BUFFERED")) {
|
||||||
|
if ((NULL == cptr) || ('\0' == *cptr))
|
||||||
|
mp->buffered = 32768;
|
||||||
|
else {
|
||||||
|
i = (int32) get_uint (cptr, 10, 1024*1024, &r);
|
||||||
|
if ((r != SCPE_OK) || (i == 0))
|
||||||
|
return SCPE_ARG;
|
||||||
|
mp->buffered = i;
|
||||||
|
}
|
||||||
|
for (i = 0; i < mp->lines; i++) { /* initialize line buffers */
|
||||||
|
lp = mp->ldsc + i;
|
||||||
|
lp->txbsz = mp->buffered;
|
||||||
|
lp->txbfd = 1;
|
||||||
|
lp->txb = (char *)realloc(lp->txb, lp->txbsz);
|
||||||
|
lp->txbpi = lp->txbpr = 0;
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (0 == MATCH_CMD (gbuf, "NOLOG")) {
|
||||||
|
if ((NULL != cptr) && ('\0' != *cptr))
|
||||||
|
return SCPE_2MARG;
|
||||||
|
mp->logfiletmpl[0] = '\0';
|
||||||
|
for (i = 0; i < mp->lines; i++) { /* close line logs */
|
||||||
|
lp = mp->ldsc + i;
|
||||||
|
free(lp->txlogname);
|
||||||
|
lp->txlogname = NULL;
|
||||||
|
if (lp->txlog) {
|
||||||
|
sim_close_logfile (&lp->txlogref);
|
||||||
|
lp->txlog = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */
|
port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */
|
||||||
if ((r != SCPE_OK) || (port == 0))
|
if ((r != SCPE_OK) || (port == 0))
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
|
@ -514,7 +604,12 @@ for (i = 0; i < mp->lines; i++) { /* initialize lines */
|
||||||
lp->conn = lp->tsta = 0;
|
lp->conn = lp->tsta = 0;
|
||||||
lp->rxbpi = lp->rxbpr = 0;
|
lp->rxbpi = lp->rxbpr = 0;
|
||||||
lp->txbpi = lp->txbpr = 0;
|
lp->txbpi = lp->txbpr = 0;
|
||||||
lp->rxcnt = lp->txcnt = 0;
|
if (!mp->buffered) {
|
||||||
|
lp->txbfd = lp->txbpi = lp->txbpr = 0;
|
||||||
|
lp->txbsz = TMXR_MAXBUF;
|
||||||
|
lp->txb = (char *)realloc(lp->txb, lp->txbsz);
|
||||||
|
}
|
||||||
|
lp->rxcnt = lp->txcnt = lp->txdrp = 0;
|
||||||
lp->xmte = 1;
|
lp->xmte = 1;
|
||||||
lp->dstb = 0;
|
lp->dstb = 0;
|
||||||
}
|
}
|
||||||
|
@ -527,8 +622,11 @@ t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
char* tptr;
|
char* tptr;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
char pmsg[20], bmsg[32] = "", lmsg[64+PATH_MAX] = "";
|
||||||
|
|
||||||
tptr = (char *) malloc (strlen (cptr) + 1); /* get string buf */
|
tptr = (char *) malloc (strlen (cptr) + /* get string buf */
|
||||||
|
sizeof(pmsg) +
|
||||||
|
sizeof(bmsg) + sizeof(lmsg));
|
||||||
if (tptr == NULL) /* no more mem? */
|
if (tptr == NULL) /* no more mem? */
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
r = tmxr_open_master (mp, cptr); /* open master socket */
|
r = tmxr_open_master (mp, cptr); /* open master socket */
|
||||||
|
@ -536,7 +634,12 @@ if (r != SCPE_OK) { /* error? */
|
||||||
free (tptr); /* release buf */
|
free (tptr); /* release buf */
|
||||||
return SCPE_OPENERR;
|
return SCPE_OPENERR;
|
||||||
}
|
}
|
||||||
strcpy (tptr, cptr); /* copy port */
|
sprintf (pmsg, "%d", mp->port); /* copy port */
|
||||||
|
if (mp->buffered)
|
||||||
|
sprintf (bmsg, ", buffered=%d", mp->buffered); /* buffer info */
|
||||||
|
if (mp->logfiletmpl[0])
|
||||||
|
sprintf (lmsg, ", log=%s", mp->logfiletmpl); /* logfile info */
|
||||||
|
sprintf (tptr, "%s%s%s", pmsg, bmsg, lmsg); /* assemble all */
|
||||||
uptr->filename = tptr; /* save */
|
uptr->filename = tptr; /* save */
|
||||||
uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */
|
uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */
|
||||||
|
|
||||||
|
@ -646,16 +749,24 @@ static const char *enab = "on";
|
||||||
static const char *dsab = "off";
|
static const char *dsab = "off";
|
||||||
|
|
||||||
if (ln >= 0)
|
if (ln >= 0)
|
||||||
fprintf (st, "line %d: ", ln);
|
fprintf (st, "line %d:\b", ln);
|
||||||
if (lp->conn) {
|
if (!lp->conn)
|
||||||
fprintf (st, "input (%s) queued/total = %d/%d, ",
|
fprintf (st, "line disconnected\n");
|
||||||
|
if (lp->rxcnt)
|
||||||
|
fprintf (st, " input (%s) queued/total = %d/%d\n",
|
||||||
(lp->rcve? enab: dsab),
|
(lp->rcve? enab: dsab),
|
||||||
lp->rxbpi - lp->rxbpr, lp->rxcnt);
|
tmxr_rqln (lp), lp->rxcnt);
|
||||||
fprintf (st, "output (%s) queued/total = %d/%d\n",
|
if (lp->txcnt || lp->txbpi)
|
||||||
|
fprintf (st, " output (%s) queued/total = %d/%d\n",
|
||||||
(lp->xmte? enab: dsab),
|
(lp->xmte? enab: dsab),
|
||||||
lp->txbpi - lp->txbpr, lp->txcnt);
|
tmxr_tqln (lp), lp->txcnt);
|
||||||
}
|
if (lp->txbfd)
|
||||||
else fprintf (st, "line disconnected\n");
|
fprintf (st, " output buffer size = %d\n", lp->txbsz);
|
||||||
|
if (lp->txcnt || lp->txbpi)
|
||||||
|
fprintf (st, " bytes in buffer = %d\n",
|
||||||
|
((lp->txcnt > 0) && (lp->txcnt > lp->txbsz)) ? lp->txbsz : lp->txbpi);
|
||||||
|
if (lp->txdrp)
|
||||||
|
fprintf (st, " dropped = %d\n", lp->txdrp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,7 +819,7 @@ lp->txlogname = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc namebuf */
|
||||||
if (lp->txlogname == NULL) /* can't? */
|
if (lp->txlogname == NULL) /* can't? */
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */
|
strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */
|
||||||
lp->txlog = fopen (cptr, "ab"); /* open log */
|
sim_open_logfile (cptr, TRUE, &lp->txlog, &lp->txlogref);/* open log */
|
||||||
if (lp->txlog == NULL) { /* error? */
|
if (lp->txlog == NULL) { /* error? */
|
||||||
free (lp->txlogname); /* free buffer */
|
free (lp->txlogname); /* free buffer */
|
||||||
return SCPE_OPENERR;
|
return SCPE_OPENERR;
|
||||||
|
@ -729,7 +840,7 @@ lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */
|
||||||
if (lp == NULL)
|
if (lp == NULL)
|
||||||
return SCPE_IERR;
|
return SCPE_IERR;
|
||||||
if (lp->txlog) { /* logging? */
|
if (lp->txlog) { /* logging? */
|
||||||
fclose (lp->txlog); /* close log */
|
sim_close_logfile (&lp->txlogref); /* close log */
|
||||||
free (lp->txlogname); /* free namebuf */
|
free (lp->txlogname); /* free namebuf */
|
||||||
lp->txlog = NULL;
|
lp->txlog = NULL;
|
||||||
lp->txlogname = NULL;
|
lp->txlogname = NULL;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
Based on the original DZ11 simulator by Thord Nilson, as updated by
|
Based on the original DZ11 simulator by Thord Nilson, as updated by
|
||||||
Arthur Krewat.
|
Arthur Krewat.
|
||||||
|
|
||||||
|
17-Jan-11 MP Added buffered line capabilities
|
||||||
20-Nov-08 RMS Added three new standardized SHOW routines
|
20-Nov-08 RMS Added three new standardized SHOW routines
|
||||||
27-May-08 JDB Added lnorder to TMXR structure,
|
27-May-08 JDB Added lnorder to TMXR structure,
|
||||||
added tmxr_set_lnorder and tmxr_set_lnorder
|
added tmxr_set_lnorder and tmxr_set_lnorder
|
||||||
|
@ -62,11 +63,15 @@ struct tmln {
|
||||||
int32 txbpr; /* xmt buf remove */
|
int32 txbpr; /* xmt buf remove */
|
||||||
int32 txbpi; /* xmt buf insert */
|
int32 txbpi; /* xmt buf insert */
|
||||||
int32 txcnt; /* xmt count */
|
int32 txcnt; /* xmt count */
|
||||||
|
int32 txdrp; /* xmt drop count */
|
||||||
|
int32 txbsz; /* xmt buffer size */
|
||||||
|
int32 txbfd; /* xmt buffered flag */
|
||||||
FILE *txlog; /* xmt log file */
|
FILE *txlog; /* xmt log file */
|
||||||
|
FILEREF *txlogref; /* xmt log file reference */
|
||||||
char *txlogname; /* xmt log file name */
|
char *txlogname; /* xmt log file name */
|
||||||
char rxb[TMXR_MAXBUF]; /* rcv buffer */
|
char rxb[TMXR_MAXBUF]; /* rcv buffer */
|
||||||
char rbr[TMXR_MAXBUF]; /* rcv break */
|
char rbr[TMXR_MAXBUF]; /* rcv break */
|
||||||
char txb[TMXR_MAXBUF]; /* xmt buffer */
|
char *txb; /* xmt buffer */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct tmln TMLN;
|
typedef struct tmln TMLN;
|
||||||
|
@ -78,6 +83,8 @@ struct tmxr {
|
||||||
TMLN *ldsc; /* line descriptors */
|
TMLN *ldsc; /* line descriptors */
|
||||||
int32 *lnorder; /* line connection order */
|
int32 *lnorder; /* line connection order */
|
||||||
DEVICE *dptr; /* multiplexer device */
|
DEVICE *dptr; /* multiplexer device */
|
||||||
|
char logfiletmpl[FILENAME_MAX]; /* template logfile name */
|
||||||
|
int32 buffered; /* Buffered Line Behavior and Buffer Size Flag */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct tmxr TMXR;
|
typedef struct tmxr TMXR;
|
||||||
|
|
Loading…
Add table
Reference in a new issue