This source file includes following definitions.
- sim_con_poll_svc
- sim_con_reset
- sim_set_console
- sim_show_console
- sim_set_remote_console
- sim_show_remote_console
- sim_rem_con_poll_svc
- x_continue_cmd
- x_step_cmd
- x_run_cmd
- x_help_cmd
- _sim_rem_message
- _sim_rem_log_out
- sim_remote_process_command
- sim_rem_con_data_svc
- sim_rem_con_reset
- sim_set_rem_telnet
- sim_set_rem_connections
- sim_set_rem_timeout
- sim_set_kmap
- sim_show_kmap
- sim_set_pchar
- sim_set_cons_speed
- sim_show_cons_speed
- sim_set_logon
- sim_set_logoff
- sim_show_log
- sim_set_debon
- sim_debug_flush
- sim_set_deboff
- sim_show_debug
- sim_set_telnet
- sim_set_notelnet
- sim_show_telnet
- sim_set_cons_buff
- sim_set_cons_unbuff
- sim_set_cons_log
- sim_set_cons_nolog
- sim_show_cons_log
- sim_show_cons_buff
- sim_show_cons_expect
- sim_open_logfile
- sim_close_logfile
- sim_logfile_name
- sim_check_console
- sim_cons_get_send
- sim_cons_get_expect
- sim_show_cons_send_input
- sim_poll_kbd
- sim_putchar
- sim_ttinit
- sim_ttrun
- sim_ttcmd
- sim_ttclose
- sim_ttisatty
- ControlHandler
- sim_os_ttinit
- sim_os_ttrun
- sim_os_ttcmd
- sim_os_ttclose
- sim_os_ttisatty
- sim_os_poll_kbd
- sim_os_putchar
- sim_os_ttinit
- sim_os_ttrun
- sim_os_ttcmd
- sim_os_ttclose
- sim_os_ttisatty
- sim_os_poll_kbd
- sim_os_putchar
- sim_os_ttinit
- sim_os_ttrun
- sim_os_ttcmd
- sim_os_ttclose
- sim_os_ttisatty
- sim_os_poll_kbd
- sim_os_putchar
- decode
- sim_set_halt
- sim_set_response
- sim_set_delay
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 #include "sim_defs.h"
79 #include "sim_tmxr.h"
80 #include "sim_timer.h"
81 #include <ctype.h>
82 #include <signal.h>
83 #include <math.h>
84
85 #define DBG_CTR 0
86
87 #include "../dps8/dps8.h"
88
89 #ifdef __HAIKU__
90 # define nice(n) ({})
91 #endif
92
93 #ifdef TESTING
94 # include "../dps8/dps8_cpu.h"
95 # undef realloc
96 # undef FREE
97 # define FREE(p) free(p)
98 # define realloc trealloc
99 #endif
100
101
102
103 static t_stat sim_os_poll_kbd (void);
104 static t_stat sim_os_putchar (int32 out);
105 static t_stat sim_os_ttinit (void);
106 static t_stat sim_os_ttrun (void);
107 static t_stat sim_os_ttcmd (void);
108 static t_stat sim_os_ttclose (void);
109 static t_bool sim_os_ttisatty (void);
110
111 static t_stat sim_set_rem_telnet (int32 flag, CONST char *cptr);
112 static t_stat sim_set_rem_connections (int32 flag, CONST char *cptr);
113 static t_stat sim_set_rem_timeout (int32 flag, CONST char *cptr);
114
115
116 static t_stat sim_set_halt (int32 flag, CONST char *cptr);
117 static t_stat sim_set_response (int32 flag, CONST char *cptr);
118 static t_stat sim_set_delay (int32 flag, CONST char *cptr);
119
120 #define KMAP_WRU 0
121 #define KMAP_BRK 1
122 #define KMAP_DEL 2
123 #define KMAP_MASK 0377
124 #define KMAP_NZ 0400
125
126 int32 sim_int_char = 005;
127 int32 sim_brk_char = 000;
128 int32 sim_tt_pchar = 0x00002780;
129 #if defined (_WIN32)
130 int32 sim_del_char = '\b';
131 #else
132 int32 sim_del_char = 0177;
133 #endif
134
135 static t_stat sim_con_poll_svc (UNIT *uptr);
136 static t_stat sim_con_reset (DEVICE *dptr);
137 UNIT sim_con_unit = { UDATA (&sim_con_poll_svc, 0, 0) };
138
139
140 #define DBG_TRC TMXR_DBG_TRC
141 #define DBG_XMT TMXR_DBG_XMT
142 #define DBG_RCV TMXR_DBG_RCV
143 #define DBG_RET TMXR_DBG_RET
144 #define DBG_ASY TMXR_DBG_ASY
145 #define DBG_EXP 0x00000001
146 #define DBG_SND 0x00000002
147
148 static DEBTAB sim_con_debug[] = {
149 {"TRC", DBG_TRC},
150 {"XMT", DBG_XMT},
151 {"RCV", DBG_RCV},
152 {"RET", DBG_RET},
153 {"ASY", DBG_ASY},
154 {"EXP", DBG_EXP},
155 {"SND", DBG_SND},
156 {0}
157 };
158
159 static REG sim_con_reg[] = {
160 { ORDATAD (WRU, sim_int_char, 8, "interrupt character") },
161 { ORDATAD (BRK, sim_brk_char, 8, "break character") },
162 { ORDATAD (DEL, sim_del_char, 8, "delete character ") },
163 { ORDATAD (PCHAR, sim_tt_pchar, 32, "printable character mask") },
164 { 0 },
165 };
166
167 static MTAB sim_con_mod[] = {
168 { 0 },
169 };
170
171 DEVICE sim_con_telnet = {
172 "CON-TEL", &sim_con_unit, sim_con_reg, sim_con_mod,
173 1, 0, 0, 0, 0, 0,
174 NULL, NULL, sim_con_reset, NULL, NULL, NULL,
175 NULL, DEV_DEBUG, 0, sim_con_debug};
176 TMLN sim_con_ldsc = { 0 };
177 TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc, NULL, &sim_con_telnet };
178
179 SEND sim_con_send = {SEND_DEFAULT_DELAY, &sim_con_telnet, DBG_SND};
180 EXPECT sim_con_expect = {&sim_con_telnet, DBG_EXP};
181
182 static t_bool sim_con_console_port = TRUE;
183
184
185
186 static t_stat sim_con_poll_svc (UNIT *uptr)
187 {
188 if ((sim_con_tmxr.master == 0) &&
189 (sim_con_ldsc.serport == 0) &&
190
191 (sim_con_console_port))
192 return SCPE_OK;
193 if (tmxr_poll_conn (&sim_con_tmxr) >= 0)
194 sim_con_ldsc.rcve = 1;
195 sim_activate_after(uptr, 1000000);
196
197 if (!sim_con_console_port)
198 sim_poll_kbd();
199 if (sim_con_ldsc.conn)
200 tmxr_send_buffered_data (&sim_con_ldsc);
201 return SCPE_OK;
202 }
203
204 static t_stat sim_con_reset (DEVICE *dptr)
205 {
206 return sim_con_poll_svc (&dptr->units[0]);
207 }
208
209
210
211 static CTAB set_con_tab[] = {
212 { "WRU", &sim_set_kmap, KMAP_WRU | KMAP_NZ },
213 { "BRK", &sim_set_kmap, KMAP_BRK },
214 { "DEL", &sim_set_kmap, KMAP_DEL |KMAP_NZ },
215 { "PCHAR", &sim_set_pchar, 0 },
216 { "SPEED", &sim_set_cons_speed, 0 },
217 { "TELNET", &sim_set_telnet, 0 },
218 { "NOTELNET", &sim_set_notelnet, 0 },
219 { "LOG", &sim_set_logon, 0 },
220 { "NOLOG", &sim_set_logoff, 0 },
221 { "DEBUG", &sim_set_debon, 0 },
222 { "NODEBUG", &sim_set_deboff, 0 },
223 #define CMD_WANTSTR 0100000
224 { "HALT", &sim_set_halt, 1 | CMD_WANTSTR },
225 { "NOHALT", &sim_set_halt, 0 },
226 { "DELAY", &sim_set_delay, 0 },
227 { "RESPONSE", &sim_set_response, 1 | CMD_WANTSTR },
228 { "NORESPONSE", &sim_set_response, 0 },
229 { NULL, NULL, 0 }
230 };
231
232 static CTAB set_rem_con_tab[] = {
233 { "CONNECTIONS", &sim_set_rem_connections, 0 },
234 { "TELNET", &sim_set_rem_telnet, 1 },
235 { "NOTELNET", &sim_set_rem_telnet, 0 },
236 { "TIMEOUT", &sim_set_rem_timeout, 0 },
237 { NULL, NULL, 0 }
238 };
239
240 static SHTAB show_con_tab[] = {
241 { "WRU", &sim_show_kmap, KMAP_WRU },
242 { "BRK", &sim_show_kmap, KMAP_BRK },
243 { "DEL", &sim_show_kmap, KMAP_DEL },
244 { "SPEED", &sim_show_cons_speed, 0 },
245 { "LOG", &sim_show_cons_log, 0 },
246 { "TELNET", &sim_show_telnet, 0 },
247 { "BUFFERED", &sim_show_cons_buff, 0 },
248 { "EXPECT", &sim_show_cons_expect, 0 },
249 { "HALT", &sim_show_cons_expect, 0 },
250 { "INPUT", &sim_show_cons_send_input, 0 },
251 { "RESPONSE", &sim_show_cons_send_input, 0 },
252 { "DELAY", &sim_show_cons_expect, 0 },
253 { NULL, NULL, 0 }
254 };
255
256 static CTAB set_con_telnet_tab[] = {
257 { "LOG", &sim_set_cons_log, 0 },
258 { "NOLOG", &sim_set_cons_nolog, 0 },
259 { "BUFFERED", &sim_set_cons_buff, 0 },
260 { "NOBUFFERED", &sim_set_cons_unbuff, 0 },
261 { "UNBUFFERED", &sim_set_cons_unbuff, 0 },
262 { NULL, NULL, 0 }
263 };
264
265 static int32 *cons_kmap[] = {
266 &sim_int_char,
267 &sim_brk_char,
268 &sim_del_char
269 };
270
271
272
273
274
275
276
277
278
279
280
281 t_stat sim_set_console (int32 flag, CONST char *cptr)
282 {
283 char *cvptr, gbuf[CBUFSIZE];
284 CTAB *ctptr;
285 t_stat r;
286
287 if ((cptr == NULL) || (*cptr == 0))
288 return SCPE_2FARG;
289 while (*cptr != 0) {
290 cptr = get_glyph_nc (cptr, gbuf, ',');
291 if ((cvptr = strchr (gbuf, '=')))
292 *cvptr++ = 0;
293 (void)get_glyph (gbuf, gbuf, 0);
294 if ((ctptr = find_ctab (set_con_tab, gbuf))) {
295 r = ctptr->action (ctptr->arg, cvptr);
296 if (r != SCPE_OK)
297 return r;
298 }
299 else return SCPE_NOPARAM;
300 }
301 return SCPE_OK;
302 }
303
304
305
306 t_stat sim_show_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
307 {
308 char gbuf[CBUFSIZE];
309 SHTAB *shptr;
310 int32 i;
311
312 if (*cptr == 0) {
313 for (i = 0; show_con_tab[i].name; i++)
314 show_con_tab[i].action (st, dptr, uptr, show_con_tab[i].arg, cptr);
315 return SCPE_OK;
316 }
317 while (*cptr != 0) {
318 cptr = get_glyph (cptr, gbuf, ',');
319 if ((shptr = find_shtab (show_con_tab, gbuf)))
320 shptr->action (st, dptr, uptr, shptr->arg, NULL);
321 else return SCPE_NOPARAM;
322 }
323 return SCPE_OK;
324 }
325
326 t_stat sim_rem_con_poll_svc (UNIT *uptr);
327 t_stat sim_rem_con_data_svc (UNIT *uptr);
328 t_stat sim_rem_con_reset (DEVICE *dptr);
329 UNIT sim_rem_con_unit[2] = {
330 { UDATA (&sim_rem_con_poll_svc, UNIT_IDLE, 0) },
331 { UDATA (&sim_rem_con_data_svc, UNIT_IDLE, 0) }};
332
333 DEBTAB sim_rem_con_debug[] = {
334 {"TRC", DBG_TRC},
335 {"XMT", DBG_XMT},
336 {"RCV", DBG_RCV},
337 {0}
338 };
339
340 MTAB sim_rem_con_mod[] = {
341 { 0 },
342 };
343
344 DEVICE sim_remote_console = {
345 "REM-CON", sim_rem_con_unit, NULL, sim_rem_con_mod,
346 2, 0, 0, 0, 0, 0,
347 NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL,
348 NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug};
349 #define MAX_REMOTE_SESSIONS 40
350 static int32 *sim_rem_buf_size = NULL;
351 static int32 *sim_rem_buf_ptr = NULL;
352 static char **sim_rem_buf = NULL;
353 static t_bool *sim_rem_single_mode = NULL;
354 static TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };
355 static uint32 sim_rem_read_timeout = 30;
356 static uint32 *sim_rem_read_timeouts = NULL;
357 static int32 sim_rem_active_number = -1;
358 int32 sim_rem_cmd_active_line = -1;
359 static CTAB *sim_rem_active_command = NULL;
360 static char *sim_rem_command_buf;
361 static t_bool sim_log_temp = FALSE;
362 static char sim_rem_con_temp_name[PATH_MAX+1];
363 static t_bool sim_rem_master_mode = FALSE;
364 static t_bool sim_rem_master_was_enabled = FALSE;
365 static t_bool sim_rem_master_was_connected = FALSE;
366 static t_offset sim_rem_cmd_log_start = 0;
367
368
369
370 t_stat sim_set_remote_console (int32 flag, CONST char *cptr)
371 {
372 char *cvptr, gbuf[CBUFSIZE];
373 CTAB *ctptr;
374 t_stat r;
375
376 if ((cptr == NULL) || (*cptr == 0))
377 return SCPE_2FARG;
378 while (*cptr != 0) {
379 cptr = get_glyph_nc (cptr, gbuf, ',');
380 if ((cvptr = strchr (gbuf, '=')))
381 *cvptr++ = 0;
382 (void)get_glyph (gbuf, gbuf, 0);
383 if ((ctptr = find_ctab (set_rem_con_tab, gbuf))) {
384 r = ctptr->action (ctptr->arg, cvptr);
385 if (r != SCPE_OK)
386 return r;
387 }
388 else return SCPE_NOPARAM;
389 }
390 return SCPE_OK;
391 }
392
393
394
395 t_stat sim_show_remote_console (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
396 {
397 int32 i, connections;
398 TMLN *lp;
399
400 if (*cptr != 0)
401 return SCPE_NOPARAM;
402 if (sim_rem_active_number >= 0) {
403 if (sim_rem_master_mode && (sim_rem_active_number == 0))
404 fprintf (st, "Running from Master Mode Remote Console Connection\n");
405 else
406 fprintf (st, "Running from Remote Console Connection %lu\n", (unsigned long)sim_rem_active_number);
407 }
408 if (sim_rem_con_tmxr.lines > 1)
409 fprintf (st, "Remote Console Input Connections from %lu sources are supported concurrently\n", (unsigned long)sim_rem_con_tmxr.lines);
410 if (sim_rem_read_timeout)
411 fprintf (st, "Remote Console Input automatically continues after %lu seconds\n", (unsigned long)sim_rem_read_timeout);
412 if (!sim_rem_con_tmxr.master)
413 fprintf (st, "Remote Console Command input is disabled\n");
414 else
415 fprintf (st, "Remote Console Command Input listening on TCP port: %s\n", sim_rem_con_unit[0].filename);
416 for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
417 lp = &sim_rem_con_tmxr.ldsc[i];
418 if (!lp->conn)
419 continue;
420 ++connections;
421 if (connections == 1)
422 fprintf (st, "Remote Console Connections:\n");
423 tmxr_fconns (st, lp, i);
424 if (sim_rem_read_timeouts[i] != sim_rem_read_timeout) {
425 if (sim_rem_read_timeouts[i])
426 fprintf (st, "Remote Console Input on connection %lu automatically continues after %lu seconds\n", (unsigned long)i, (unsigned long)sim_rem_read_timeouts[i]);
427 else
428 fprintf (st, "Remote Console Input on connection %lu does not continue automatically\n", (unsigned long)i);
429 }
430 }
431 return SCPE_OK;
432 }
433
434
435
436 t_stat sim_rem_con_poll_svc (UNIT *uptr)
437 {
438 int32 c;
439
440 c = tmxr_poll_conn (&sim_rem_con_tmxr);
441 if (c >= 0) {
442 TMLN *lp = &sim_rem_con_tmxr.ldsc[c];
443 char wru_name[8];
444
445 sim_activate_after(uptr+1, 1000000);
446 lp->rcve = 1;
447 sim_rem_buf_ptr[c] = 0;
448 sim_rem_single_mode[c] = TRUE;
449 sim_rem_read_timeouts[c] = sim_rem_read_timeout;
450 if (isprint(sim_int_char&0xFF))
451 sprintf(wru_name, "'%c'", sim_int_char&0xFF);
452 else
453 if (sim_int_char <= 26)
454 sprintf(wru_name, "^%c", '@' + (sim_int_char&0xFF));
455 else
456 sprintf(wru_name, "'\\%03o'", sim_int_char&0xFF);
457 tmxr_linemsgf (lp, "%s Remote Console\r\n"
458 "Enter single commands or to enter multiple command mode enter the %s character\r"
459 "%s",
460 sim_name, wru_name,
461 ((sim_rem_master_mode && (c == 0)) ? "" : "\nSimulator Running..."));
462 if (sim_rem_master_mode && (c == 0))
463 sim_rem_single_mode[c] = FALSE;
464 tmxr_send_buffered_data (lp);
465 }
466 sim_activate_after(uptr, 1000000);
467 if (sim_con_ldsc.conn)
468 tmxr_send_buffered_data (&sim_con_ldsc);
469 return SCPE_OK;
470 }
471
472 static t_stat x_continue_cmd (int32 flag, CONST char *cptr)
473 {
474 return SCPE_IERR;
475 }
476
477 static t_stat x_step_cmd (int32 flag, CONST char *cptr)
478 {
479 return SCPE_IERR;
480 }
481
482 static t_stat x_run_cmd (int32 flag, CONST char *cptr)
483 {
484 return SCPE_IERR;
485 }
486
487 static t_stat x_help_cmd (int32 flag, CONST char *cptr);
488
489 static CTAB allowed_remote_cmds[] = {
490 { "EXAMINE", &exdep_cmd, EX_E },
491 { "DEPOSIT", &exdep_cmd, EX_D },
492 { "EVALUATE", &eval_cmd, 0 },
493 { "ATTACH", &attach_cmd, 0 },
494 { "DETACH", &detach_cmd, 0 },
495
496
497
498
499 { "CONTINUE", &x_continue_cmd, 0 },
500 { "STEP", &x_step_cmd, 0 },
501 { "ECHO", &echo_cmd, 0 },
502 { "SET", &set_cmd, 0 },
503 { "SHOW", &show_cmd, 0 },
504 { "HELP", &x_help_cmd, 0 },
505 { NULL, NULL }
506 };
507
508 static CTAB allowed_master_remote_cmds[] = {
509 { "EXAMINE", &exdep_cmd, EX_E },
510 { "DEPOSIT", &exdep_cmd, EX_D },
511 { "EVALUATE", &eval_cmd, 0 },
512 { "ATTACH", &attach_cmd, 0 },
513 { "DETACH", &detach_cmd, 0 },
514
515
516
517
518 { "CONTINUE", &x_continue_cmd, 0 },
519 { "STEP", &x_step_cmd, 0 },
520 { "ECHO", &echo_cmd, 0 },
521 { "SET", &set_cmd, 0 },
522 { "SHOW", &show_cmd, 0 },
523 { "HELP", &x_help_cmd, 0 },
524 { "EXIT", &exit_cmd, 0 },
525 { "QUIT", &exit_cmd, 0 },
526 { "RUN", &x_run_cmd, RU_RUN },
527 { "GO", &x_run_cmd, RU_GO },
528 { "BOOT", &x_run_cmd, RU_BOOT },
529 { "BREAK", &brk_cmd, SSH_ST },
530 { "NOBREAK", &brk_cmd, SSH_CL },
531 { NULL, NULL }
532 };
533
534 static CTAB allowed_single_remote_cmds[] = {
535 { "ATTACH", &attach_cmd, 0 },
536 { "DETACH", &detach_cmd, 0 },
537 { "EXAMINE", &exdep_cmd, EX_E },
538 { "EVALUATE", &eval_cmd, 0 },
539 { "ECHO", &echo_cmd, 0 },
540 { "SHOW", &show_cmd, 0 },
541 { "HELP", &x_help_cmd, 0 },
542 { NULL, NULL }
543 };
544
545 static t_stat x_help_cmd (int32 flag, CONST char *cptr)
546 {
547 CTAB *cmdp, *cmdph;
548
549 if (*cptr) {
550 int32 saved_switches = sim_switches;
551 t_stat r;
552
553 sim_switches |= SWMASK ('F');
554 r = help_cmd (flag, cptr);
555 sim_switches = saved_switches;
556 return r;
557 }
558 sim_printf ("Help is available for the following Remote Console commands:\r\n");
559 for (cmdp=allowed_remote_cmds; cmdp->name != NULL; ++cmdp) {
560 cmdph = find_cmd (cmdp->name);
561 if (cmdph && cmdph->help)
562 sim_printf (" %s\r\n", cmdp->name);
563 }
564 sim_printf ("Enter \"HELP cmd\" for detailed help on a command\r\n");
565 return SCPE_OK;
566 }
567
568 static t_stat _sim_rem_message (const char *cmd, t_stat stat)
569 {
570 CTAB *cmdp = NULL;
571 t_stat stat_nomessage = stat & SCPE_NOMESSAGE;
572
573 cmdp = find_cmd (cmd);
574 stat = SCPE_BARE_STATUS(stat);
575 if (!stat_nomessage) {
576 if (cmdp && (cmdp->message))
577 cmdp->message (NULL, stat);
578 else {
579 if (stat >= SCPE_BASE)
580 sim_printf ("%s\r\n", sim_error_text (stat));
581 }
582 }
583 return stat;
584 }
585
586 static void _sim_rem_log_out (TMLN *lp)
587 {
588 char cbuf[4*CBUFSIZE];
589
590 if (sim_log) {
591 int32 unwritten;
592
593 fflush (sim_log);
594 (void)sim_fseeko (sim_log, sim_rem_cmd_log_start, SEEK_SET);
595 cbuf[sizeof(cbuf)-1] = '\0';
596 while (fgets (cbuf, sizeof(cbuf)-1, sim_log))
597 tmxr_linemsgf (lp, "%s", cbuf);
598 if (!tmxr_input_pending_ln (lp)) {
599 do {
600 unwritten = tmxr_send_buffered_data (lp);
601 if (unwritten == lp->txbsz)
602 sim_os_ms_sleep (100);
603 } while (unwritten == lp->txbsz);
604 }
605 }
606 }
607
608 void sim_remote_process_command (void)
609 {
610 char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *argv[1] = {NULL};
611 CONST char *cptr;
612 int32 saved_switches = sim_switches;
613 t_stat stat;
614
615 strcpy (cbuf, sim_rem_command_buf);
616 while (isspace((unsigned char)cbuf[0]))
617 memmove (cbuf, cbuf+1, strlen(cbuf+1)+1);
618 sim_sub_args (cbuf, sizeof(cbuf), argv);
619 cptr = cbuf;
620 cptr = get_glyph (cptr, gbuf, 0);
621 sim_rem_active_command = find_cmd (gbuf);
622
623 sim_ttcmd ();
624 stat = sim_rem_active_command->action (sim_rem_active_command->arg, cptr);
625 if (stat != SCPE_OK)
626 stat = _sim_rem_message (gbuf, stat);
627 sim_last_cmd_stat = SCPE_BARE_STATUS(stat);
628 sim_ttrun ();
629 sim_cancel (&sim_rem_con_unit[1]);
630 sim_activate (&sim_rem_con_unit[1], -1);
631 sim_switches = saved_switches;
632 }
633
634
635
636 t_stat sim_rem_con_data_svc (UNIT *uptr)
637 {
638 int32 i, j, c = 0;
639 t_stat stat = SCPE_OK;
640 int32 steps = 0;
641 t_bool was_active_command = (sim_rem_cmd_active_line != -1);
642 t_bool got_command;
643 t_bool close_session = FALSE;
644 TMLN *lp;
645 char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *argv[1] = {NULL};
646 CONST char *cptr;
647 CTAB *cmdp = NULL;
648 CTAB *basecmdp = NULL;
649 uint32 read_start_time = 0;
650
651 tmxr_poll_rx (&sim_rem_con_tmxr);
652 for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
653 (i < sim_rem_con_tmxr.lines);
654 i++) {
655 t_bool master_session = (sim_rem_master_mode && (i == 0));
656
657 lp = &sim_rem_con_tmxr.ldsc[i];
658 if (!lp->conn)
659 continue;
660 if (master_session && !sim_rem_master_was_connected) {
661 tmxr_linemsgf (lp, "\nMaster Mode Session\r\n");
662 tmxr_send_buffered_data (lp);
663 }
664 sim_rem_master_was_connected |= master_session;
665 stat = SCPE_OK;
666 if ((was_active_command) ||
667 (master_session && !sim_rem_single_mode[i])) {
668 if (was_active_command) {
669 sim_rem_cmd_active_line = -1;
670 if (!sim_rem_active_command) {
671 stat = SCPE_STEP;
672 _sim_rem_message ("STEP", stat);
673 }
674 _sim_rem_log_out (lp);
675 sim_rem_active_command = NULL;
676 was_active_command = FALSE;
677 i = -1;
678 continue;
679 }
680 else {
681 sim_is_running = 0;
682 sim_stop_timer_services ();
683 for (j=0; j < sim_rem_con_tmxr.lines; j++) {
684 TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
685 if ((i == j) || (!lpj->conn))
686 continue;
687 tmxr_linemsgf (lpj, "\nRemote Master Console(%s) Entering Commands\n", lp->ipad);
688 tmxr_send_buffered_data (lpj);
689 }
690 lp = &sim_rem_con_tmxr.ldsc[i];
691 }
692 }
693 else {
694 c = tmxr_getc_ln (lp);
695 if (!(TMXR_VALID & c))
696 continue;
697 c = c & ~TMXR_VALID;
698 if (sim_rem_single_mode[i]) {
699 if (c == sim_int_char) {
700 sim_rem_single_mode[i] = FALSE;
701 sim_is_running = 0;
702 sim_stop_timer_services ();
703 stat = SCPE_STOP;
704 _sim_rem_message ("RUN", stat);
705 _sim_rem_log_out (lp);
706 for (j=0; j < sim_rem_con_tmxr.lines; j++) {
707 TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
708 if ((i == j) || (!lpj->conn))
709 continue;
710 tmxr_linemsgf (lpj, "\nRemote Console %lu(%s) Entering Commands\n", (unsigned long)i, lp->ipad);
711 tmxr_send_buffered_data (lpj);
712 }
713 lp = &sim_rem_con_tmxr.ldsc[i];
714 if (!master_session)
715 tmxr_linemsg (lp, "\r\nSimulator paused.\r\n");
716 if (!master_session && sim_rem_read_timeouts[i]) {
717 tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %lu seconds\n", (unsigned long)sim_rem_read_timeouts[i]);
718 tmxr_linemsgf (lp, "\r\n");
719 tmxr_send_buffered_data (lp);
720 }
721 }
722 else {
723 if ((sim_rem_buf_ptr[i] == 0) &&
724 ((c == '\n') ||
725 (c == '\r')))
726 continue;
727 if ((c == '\004') || (c == '\032')) {
728 tmxr_linemsgf (lp, "\r\nGoodbye\r\n");
729 tmxr_send_buffered_data (lp);
730 tmxr_reset_ln (lp);
731 continue;
732 }
733 if (sim_rem_buf_ptr[i] == 0) {
734
735 if (!master_session)
736 tmxr_linemsgf (lp, "\r\n%s", sim_prompt);
737 else
738 tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> ");
739 sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> ");
740 if (!tmxr_input_pending_ln (lp))
741 tmxr_send_buffered_data (lp);
742 }
743 }
744 }
745 }
746 got_command = FALSE;
747 while (1) {
748 if (stat == SCPE_EXIT)
749 return stat|SCPE_NOMESSAGE;
750 if (!sim_rem_single_mode[i]) {
751 read_start_time = sim_os_msec();
752 if (master_session)
753 tmxr_linemsg (lp, "sim> ");
754 else
755 tmxr_linemsg (lp, sim_prompt);
756 tmxr_send_buffered_data (lp);
757 }
758 do {
759 if (!sim_rem_single_mode[i]) {
760 c = tmxr_getc_ln (lp);
761 if (!(TMXR_VALID & c)) {
762 tmxr_send_buffered_data (lp);
763 if (!master_session &&
764 sim_rem_read_timeouts[i] &&
765 ((sim_os_msec() - read_start_time)/1000 >= sim_rem_read_timeouts[i])) {
766 while (sim_rem_buf_ptr[i] > 0) {
767 tmxr_linemsg (lp, "\b \b");
768 --sim_rem_buf_ptr[i];
769 }
770 if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) {
771 sim_rem_buf_size[i] += 1024;
772 sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
773 }
774 strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue due to timeout");
775 tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]);
776 got_command = TRUE;
777 break;
778 }
779 sim_os_ms_sleep (50);
780 tmxr_poll_rx (&sim_rem_con_tmxr);
781 if (!lp->conn) {
782 sim_rem_single_mode[i] = TRUE;
783 break;
784 }
785 continue;
786 }
787 read_start_time = sim_os_msec();
788 c = c & ~TMXR_VALID;
789 }
790 switch (c) {
791 case 0:
792 break;
793 case '\b':
794 case 127:
795 if (sim_rem_buf_ptr[i] > 0) {
796 tmxr_linemsg (lp, "\b \b");
797 --sim_rem_buf_ptr[i];
798 }
799 break;
800 case 27:
801 case 21:
802 while (sim_rem_buf_ptr[i] > 0) {
803 tmxr_linemsg (lp, "\b \b");
804 --sim_rem_buf_ptr[i];
805 }
806 break;
807 case '\n':
808 if (sim_rem_buf_ptr[i] == 0)
809 break;
810
811 case '\r':
812 tmxr_linemsg (lp, "\r\n");
813 if (sim_rem_buf_ptr[i]+1 >= sim_rem_buf_size[i]) {
814 sim_rem_buf_size[i] += 1024;
815 sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
816 }
817 sim_rem_buf[i][sim_rem_buf_ptr[i]++] = '\0';
818 sim_debug (DBG_RCV, &sim_remote_console, "Got Command (%lu bytes still in buffer): %s\n", (unsigned long)tmxr_input_pending_ln (lp), sim_rem_buf[i]);
819 got_command = TRUE;
820 break;
821 case '\004':
822 case '\032':
823 while (sim_rem_buf_ptr[i] > 0) {
824 tmxr_linemsg (lp, "\b \b");
825 --sim_rem_buf_ptr[i];
826 }
827 if (!sim_rem_single_mode[i]) {
828 if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) {
829 sim_rem_buf_size[i] += 1024;
830 sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
831 }
832 strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue before close");
833 tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]);
834 got_command = TRUE;
835 }
836 close_session = TRUE;
837 break;
838 default:
839 tmxr_putc_ln (lp, c);
840 if (sim_rem_buf_ptr[i]+2 >= sim_rem_buf_size[i]) {
841 sim_rem_buf_size[i] += 1024;
842 sim_rem_buf[i] = (char *)realloc (sim_rem_buf[i], sim_rem_buf_size[i]);
843 }
844 sim_rem_buf[i][sim_rem_buf_ptr[i]++] = (char)c;
845 sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0';
846 if (((size_t)sim_rem_buf_ptr[i]) >= sizeof(cbuf))
847 got_command = TRUE;
848 break;
849 }
850 c = 0;
851 if ((!got_command) && (sim_rem_single_mode[i]) && (tmxr_input_pending_ln (lp))) {
852 c = tmxr_getc_ln (lp);
853 c = c & ~TMXR_VALID;
854 }
855 } while ((!got_command) && ((!sim_rem_single_mode[i]) || c));
856 if (!tmxr_input_pending_ln (lp))
857 tmxr_send_buffered_data (lp);
858 if ((sim_rem_single_mode[i]) && !got_command) {
859 break;
860 }
861 sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]);
862 got_command = FALSE;
863 if (strlen(sim_rem_buf[i]) >= sizeof(cbuf)) {
864 sim_printf ("\r\nLine too long. Ignored. Continuing Simulator execution\r\n");
865 tmxr_linemsgf (lp, "\nLine too long. Ignored. Continuing Simulator execution\n");
866 tmxr_send_buffered_data (lp);
867 break;
868 }
869 strcpy (cbuf, sim_rem_buf[i]);
870 sim_rem_buf_ptr[i] = 0;
871 sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0';
872 while (isspace((unsigned char)cbuf[0]))
873 memmove (cbuf, cbuf+1, strlen(cbuf+1)+1);
874 if (cbuf[0] == '\0') {
875 if (sim_rem_single_mode[i]) {
876 sim_rem_single_mode[i] = FALSE;
877 break;
878 }
879 else
880 continue;
881 }
882 strcpy (sim_rem_command_buf, cbuf);
883 sim_sub_args (cbuf, sizeof(cbuf), argv);
884 cptr = cbuf;
885 cptr = get_glyph (cptr, gbuf, 0);
886 sim_switches = 0;
887 sim_rem_active_number = i;
888 if (!sim_log) {
889 int32 save_quiet = sim_quiet;
890
891 sim_quiet = 1;
892 sprintf (sim_rem_con_temp_name, "sim_remote_console_%d.temporary_log", (int)getpid());
893 sim_set_logon (0, sim_rem_con_temp_name);
894 sim_quiet = save_quiet;
895 sim_log_temp = TRUE;
896 }
897 sim_rem_cmd_log_start = sim_ftell (sim_log);
898 basecmdp = find_cmd (gbuf);
899 if (basecmdp == NULL) {
900 if ((gbuf[0] == ';') || (gbuf[0] == '#')) {
901 sim_rem_cmd_active_line = i;
902 was_active_command = TRUE;
903 sim_rem_active_command = &allowed_single_remote_cmds[0];
904 i = i - 1;
905 break;
906 }
907 else
908 stat = SCPE_UNK;
909 }
910 else {
911 if ((cmdp = find_ctab (sim_rem_single_mode[i] ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {
912 if (cmdp->action == &x_continue_cmd)
913 stat = SCPE_OK;
914 else {
915 if (cmdp->action == &exit_cmd)
916 return SCPE_EXIT;
917 if (cmdp->action == &x_step_cmd) {
918 steps = 1;
919 stat = SCPE_OK;
920 if (*cptr != 0) {
921 cptr = get_glyph (cptr, gbuf, 0);
922 if (*cptr != 0)
923 stat = SCPE_2MARG;
924 else {
925 steps = (int32) get_uint (gbuf, 10, INT_MAX, &stat);
926 if ((stat != SCPE_OK) || (steps <= 0))
927 stat = SCPE_ARG;
928 }
929 }
930 if (stat != SCPE_OK)
931 cmdp = NULL;
932 }
933 else {
934 if (cmdp->action == &x_run_cmd) {
935 sim_switches |= SIM_SW_HIDE;
936 stat = basecmdp->action (cmdp->arg, cptr);
937 sim_switches &= ~SIM_SW_HIDE;
938 if (stat == SCPE_OK) {
939
940 cmdp = find_ctab (allowed_master_remote_cmds, "CONTINUE");
941 }
942 }
943 else
944 stat = SCPE_REMOTE;
945 }
946 }
947 }
948 else
949 stat = SCPE_INVREM;
950 }
951 sim_rem_active_number = -1;
952 if ((stat != SCPE_OK) && (stat != SCPE_REMOTE))
953 stat = _sim_rem_message (gbuf, stat);
954 _sim_rem_log_out (lp);
955 if (master_session && !sim_rem_master_mode) {
956 sim_rem_single_mode[i] = TRUE;
957 return SCPE_STOP;
958 }
959 if (cmdp && (cmdp->action == &x_continue_cmd)) {
960 sim_rem_cmd_active_line = -1;
961 if (sim_log_temp &&
962 (!sim_rem_master_mode)) {
963 int32 save_quiet = sim_quiet;
964
965 sim_quiet = 1;
966 sim_set_logoff (0, NULL);
967 sim_quiet = save_quiet;
968 remove (sim_rem_con_temp_name);
969 sim_log_temp = FALSE;
970 }
971 else {
972 fflush (sim_log);
973 sim_rem_cmd_log_start = sim_ftell (sim_log);
974 }
975 if (!sim_rem_single_mode[i]) {
976 tmxr_linemsg (lp, "Simulator Running...");
977 tmxr_send_buffered_data (lp);
978 for (j=0; j < sim_rem_con_tmxr.lines; j++) {
979 TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
980 if ((i == j) || (!lpj->conn))
981 continue;
982 tmxr_linemsg (lpj, "Simulator Running...");
983 tmxr_send_buffered_data (lpj);
984 }
985 sim_is_running = 1;
986 sim_start_timer_services ();
987 }
988
989 if (cmdp && (cmdp->action == &x_continue_cmd))
990 sim_rem_single_mode[i] = TRUE;
991 else {
992 if (!sim_rem_single_mode[i]) {
993 if (master_session)
994 tmxr_linemsgf (lp, "%s", "sim> ");
995 else
996 tmxr_linemsgf (lp, "%s", sim_prompt);
997 tmxr_send_buffered_data (lp);
998 }
999 }
1000 break;
1001 }
1002 if ((cmdp && (cmdp->action == &x_step_cmd)) ||
1003 (stat == SCPE_REMOTE)) {
1004 sim_rem_cmd_active_line = i;
1005 break;
1006 }
1007 }
1008 if (close_session) {
1009 tmxr_linemsgf (lp, "\r\nGoodbye\r\n");
1010 tmxr_send_buffered_data (lp);
1011 tmxr_reset_ln (lp);
1012 sim_rem_single_mode[i] = FALSE;
1013 }
1014 }
1015 if (sim_rem_master_was_connected &&
1016 !sim_rem_con_tmxr.ldsc[0].sock)
1017 return SCPE_EXIT;
1018 if (sim_rem_cmd_active_line != -1) {
1019 if (steps)
1020 sim_activate(uptr, steps);
1021 else
1022 return SCPE_REMOTE;
1023 }
1024 else
1025 sim_activate_after(uptr, 100000);
1026 if (sim_rem_master_was_enabled && !sim_rem_master_mode) {
1027 lp = &sim_rem_con_tmxr.ldsc[0];
1028 tmxr_linemsgf (lp, "Non Master Mode Session...");
1029 tmxr_send_buffered_data (lp);
1030 return SCPE_STOP|SCPE_NOMESSAGE;
1031 }
1032 else
1033 return SCPE_OK;
1034 }
1035
1036 t_stat sim_rem_con_reset (DEVICE *dptr)
1037 {
1038 if (sim_rem_con_tmxr.lines) {
1039 int32 i;
1040
1041 for (i=0; i<sim_rem_con_tmxr.lines; i++)
1042 if (sim_rem_con_tmxr.ldsc[i].conn)
1043 break;
1044 if (i != sim_rem_con_tmxr.lines)
1045 sim_activate_after (&dptr->units[1], 100000);
1046 return sim_rem_con_poll_svc (&dptr->units[0]);
1047 }
1048 return SCPE_OK;
1049 }
1050
1051 static t_stat sim_set_rem_telnet (int32 flag, CONST char *cptr)
1052 {
1053 t_stat r;
1054
1055 if (flag) {
1056 r = sim_parse_addr (cptr, NULL, 0, NULL, NULL, 0, NULL, NULL);
1057 if (r == SCPE_OK) {
1058 if (sim_rem_con_tmxr.master)
1059 sim_set_rem_telnet (0, NULL);
1060 if (sim_rem_con_tmxr.lines == 0)
1061 sim_set_rem_connections (0, "1");
1062 sim_rem_con_tmxr.buffered = 1400;
1063 sim_register_internal_device (&sim_remote_console);
1064 r = tmxr_attach (&sim_rem_con_tmxr, &sim_rem_con_unit[0], cptr);
1065 if (r == SCPE_OK)
1066 sim_activate_after(&sim_rem_con_unit[0], 1000000);
1067 return r;
1068 }
1069 return SCPE_NOPARAM;
1070 }
1071 else {
1072 if (sim_rem_con_tmxr.master) {
1073 int32 i;
1074
1075 tmxr_detach (&sim_rem_con_tmxr, &sim_rem_con_unit[0]);
1076 for (i=0; i<sim_rem_con_tmxr.lines; i++) {
1077 FREE (sim_rem_buf[i]);
1078 sim_rem_buf[i] = NULL;
1079 sim_rem_buf_size[i] = 0;
1080 sim_rem_buf_ptr[i] = 0;
1081 sim_rem_single_mode[i] = TRUE;
1082 }
1083 }
1084 }
1085 return SCPE_OK;
1086 }
1087
1088 static t_stat sim_set_rem_connections (int32 flag, CONST char *cptr)
1089 {
1090 int32 lines;
1091 t_stat r;
1092 int32 i;
1093
1094 if (cptr == NULL)
1095 return SCPE_ARG;
1096 lines = (int32) get_uint (cptr, 10, MAX_REMOTE_SESSIONS, &r);
1097 if (r != SCPE_OK)
1098 return r;
1099 if (sim_rem_con_tmxr.master)
1100 return SCPE_ARG;
1101 for (i=0; i<sim_rem_con_tmxr.lines; i++)
1102 FREE (sim_rem_buf[i]);
1103 sim_rem_con_tmxr.lines = lines;
1104 sim_rem_con_tmxr.ldsc = (TMLN *)realloc (sim_rem_con_tmxr.ldsc, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
1105 if (!sim_rem_con_tmxr.ldsc)
1106 {
1107 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1108 __func__, __FILE__, __LINE__);
1109 #if defined(USE_BACKTRACE)
1110 # ifdef SIGUSR2
1111 (void)raise(SIGUSR2);
1112
1113 # endif
1114 #endif
1115 abort();
1116 }
1117 memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
1118 sim_rem_buf = (char **)realloc (sim_rem_buf, sizeof(*sim_rem_buf)*lines);
1119 if (!sim_rem_buf)
1120 {
1121 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1122 __func__, __FILE__, __LINE__);
1123 #if defined(USE_BACKTRACE)
1124 # ifdef SIGUSR2
1125 (void)raise(SIGUSR2);
1126
1127 # endif
1128 #endif
1129 abort();
1130 }
1131 memset (sim_rem_buf, 0, sizeof(*sim_rem_buf)*lines);
1132 sim_rem_buf_size = (int32 *)realloc (sim_rem_buf_size, sizeof(*sim_rem_buf_size)*lines);
1133 if (!sim_rem_buf_size)
1134 {
1135 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1136 __func__, __FILE__, __LINE__);
1137 #if defined(USE_BACKTRACE)
1138 # ifdef SIGUSR2
1139 (void)raise(SIGUSR2);
1140
1141 # endif
1142 #endif
1143 abort();
1144 }
1145 memset (sim_rem_buf_size, 0, sizeof(*sim_rem_buf_size)*lines);
1146 sim_rem_buf_ptr = (int32 *)realloc (sim_rem_buf_ptr, sizeof(*sim_rem_buf_ptr)*lines);
1147 if (!sim_rem_buf_ptr)
1148 {
1149 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1150 __func__, __FILE__, __LINE__);
1151 #if defined(USE_BACKTRACE)
1152 # ifdef SIGUSR2
1153 (void)raise(SIGUSR2);
1154
1155 # endif
1156 #endif
1157 abort();
1158 }
1159 memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines);
1160 sim_rem_single_mode = (t_bool *)realloc (sim_rem_single_mode, sizeof(*sim_rem_single_mode)*lines);
1161 if (!sim_rem_single_mode)
1162 {
1163 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1164 __func__, __FILE__, __LINE__);
1165 #if defined(USE_BACKTRACE)
1166 # ifdef SIGUSR2
1167 (void)raise(SIGUSR2);
1168
1169 # endif
1170 #endif
1171 abort();
1172 }
1173 memset (sim_rem_single_mode, 0, sizeof(*sim_rem_single_mode)*lines);
1174 sim_rem_read_timeouts = (uint32 *)realloc (sim_rem_read_timeouts, sizeof(*sim_rem_read_timeouts)*lines);
1175 if (!sim_rem_read_timeouts)
1176 {
1177 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1178 __func__, __FILE__, __LINE__);
1179 #if defined(USE_BACKTRACE)
1180 # ifdef SIGUSR2
1181 (void)raise(SIGUSR2);
1182
1183 # endif
1184 #endif
1185 abort();
1186 }
1187 memset (sim_rem_read_timeouts, 0, sizeof(*sim_rem_read_timeouts)*lines);
1188 sim_rem_command_buf = (char *)realloc (sim_rem_command_buf, 4*CBUFSIZE+1);
1189 if (!sim_rem_command_buf)
1190 {
1191 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1192 __func__, __FILE__, __LINE__);
1193 #if defined(USE_BACKTRACE)
1194 # ifdef SIGUSR2
1195 (void)raise(SIGUSR2);
1196
1197 # endif
1198 #endif
1199 abort();
1200 }
1201 memset (sim_rem_command_buf, 0, 4*CBUFSIZE+1);
1202 return SCPE_OK;
1203 }
1204
1205 static t_stat sim_set_rem_timeout (int32 flag, CONST char *cptr)
1206 {
1207 int32 timeout;
1208 t_stat r;
1209
1210 if (cptr == NULL)
1211 return SCPE_ARG;
1212 timeout = (int32) get_uint (cptr, 10, 3600, &r);
1213 if (r != SCPE_OK)
1214 return r;
1215 if (sim_rem_active_number >= 0)
1216 sim_rem_read_timeouts[sim_rem_active_number] = timeout;
1217 else
1218 sim_rem_read_timeout = timeout;
1219 return SCPE_OK;
1220 }
1221
1222
1223
1224 t_stat sim_set_kmap (int32 flag, CONST char *cptr)
1225 {
1226 DEVICE *dptr = sim_devices[0];
1227 int32 val, rdx;
1228 t_stat r;
1229
1230 if ((cptr == NULL) || (*cptr == 0))
1231 return SCPE_2FARG;
1232 if (dptr->dradix == 16) rdx = 16;
1233 else rdx = 8;
1234 val = (int32) get_uint (cptr, rdx, 0177, &r);
1235 if ((r != SCPE_OK) ||
1236 ((val == 0) && (flag & KMAP_NZ)))
1237 return SCPE_ARG;
1238 *(cons_kmap[flag & KMAP_MASK]) = val;
1239 return SCPE_OK;
1240 }
1241
1242
1243
1244 t_stat sim_show_kmap (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
1245 {
1246 if (sim_devices[0]->dradix == 16)
1247 fprintf (st, "%s = %X\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
1248 else fprintf (st, "%s = %o\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
1249 return SCPE_OK;
1250 }
1251
1252
1253
1254 t_stat sim_set_pchar (int32 flag, CONST char *cptr)
1255 {
1256 DEVICE *dptr = sim_devices[0];
1257 uint32 val, rdx;
1258 t_stat r;
1259
1260 if ((cptr == NULL) || (*cptr == 0))
1261 return SCPE_2FARG;
1262 if (dptr->dradix == 16) rdx = 16;
1263 else rdx = 8;
1264 val = (uint32) get_uint (cptr, rdx, 0xFFFFFFFF, &r);
1265 if ((r != SCPE_OK) ||
1266 ((val & 0x00002400) == 0))
1267 return SCPE_ARG;
1268 sim_tt_pchar = val;
1269 return SCPE_OK;
1270 }
1271
1272
1273
1274 t_stat sim_set_cons_speed (int32 flag, CONST char *cptr)
1275 {
1276 return tmxr_set_line_speed (&sim_con_ldsc, cptr);
1277 }
1278
1279 t_stat sim_show_cons_speed (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
1280 {
1281 if (sim_con_ldsc.rxbps) {
1282 fprintf (st, "Speed = %ld", (long)sim_con_ldsc.rxbps);
1283 if (sim_con_ldsc.rxbpsfactor != TMXR_RX_BPS_UNIT_SCALE)
1284 fprintf (st, "*%.0f", sim_con_ldsc.rxbpsfactor/TMXR_RX_BPS_UNIT_SCALE);
1285 fprintf (st, " bps\n");
1286 }
1287 return SCPE_OK;
1288 }
1289
1290
1291
1292 t_stat sim_set_logon (int32 flag, CONST char *cptr)
1293 {
1294 char gbuf[CBUFSIZE];
1295 t_stat r;
1296 time_t now;
1297
1298 if ((cptr == NULL) || (*cptr == 0))
1299 return SCPE_2FARG;
1300 cptr = get_glyph_nc (cptr, gbuf, 0);
1301 if (*cptr != 0)
1302 return SCPE_2MARG;
1303 sim_set_logoff (0, NULL);
1304 r = sim_open_logfile (gbuf, (sim_switches & SWMASK ('B')) == SWMASK ('B'),
1305 &sim_log, &sim_log_ref);
1306 if (r != SCPE_OK)
1307 return r;
1308 if (!sim_quiet)
1309 printf ("Logging to file \"%s\"\n",
1310 sim_logfile_name (sim_log, sim_log_ref));
1311 fprintf (sim_log, "Logging to file \"%s\"\n",
1312 sim_logfile_name (sim_log, sim_log_ref));
1313 time(&now);
1314 fprintf (sim_log, "Logging to file \"%s\" at %s", sim_logfile_name (sim_log, sim_log_ref), ctime(&now));
1315 return SCPE_OK;
1316 }
1317
1318
1319
1320 t_stat sim_set_logoff (int32 flag, CONST char *cptr)
1321 {
1322 if (cptr && (*cptr != 0))
1323 return SCPE_2MARG;
1324 if (sim_log == NULL)
1325 return SCPE_OK;
1326 if (!sim_quiet)
1327 printf ("Log file closed\n");
1328 fprintf (sim_log, "Log file closed\n");
1329 sim_close_logfile (&sim_log_ref);
1330 sim_log = NULL;
1331 return SCPE_OK;
1332 }
1333
1334
1335
1336 t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
1337 {
1338 if (cptr && (*cptr != 0))
1339 return SCPE_2MARG;
1340 if (sim_log)
1341 fprintf (st, "Logging enabled to \"%s\"\n",
1342 sim_logfile_name (sim_log, sim_log_ref));
1343 else fprintf (st, "Logging disabled\n");
1344 return SCPE_OK;
1345 }
1346
1347
1348
1349 t_stat sim_set_debon (int32 flag, CONST char *cptr)
1350 {
1351 char gbuf[CBUFSIZE];
1352 t_stat r;
1353 time_t now;
1354
1355 #if defined(__MACH__) && defined(__APPLE__) && \
1356 ( defined(__PPC__) || defined(_ARCH_PPC) )
1357 # include <mach/clock.h>
1358 # include <mach/mach.h>
1359 # ifdef MACOSXPPC
1360 # undef MACOSXPPC
1361 # endif
1362 # define MACOSXPPC 1
1363 #endif
1364
1365
1366 sim_deb_switches = sim_switches;
1367 if ((cptr == NULL) || (*cptr == 0))
1368 return SCPE_2FARG;
1369 cptr = get_glyph_nc (cptr, gbuf, 0);
1370 if (*cptr != 0)
1371 return SCPE_2MARG;
1372 r = sim_open_logfile (gbuf, FALSE, &sim_deb, &sim_deb_ref);
1373
1374 if (r != SCPE_OK)
1375 return r;
1376
1377 if (sim_deb_switches & SWMASK ('R')) {
1378 #ifdef MACOSXPPC
1379 clock_serv_t cclock;
1380 mach_timespec_t mts;
1381 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
1382 clock_get_time(cclock, &mts);
1383 mach_port_deallocate(mach_task_self(), cclock);
1384 sim_deb_basetime.tv_sec = mts.tv_sec;
1385 sim_deb_basetime.tv_nsec = mts.tv_nsec;
1386 #else
1387 clock_gettime(CLOCK_REALTIME, &sim_deb_basetime);
1388 #endif
1389 if (!(sim_deb_switches & (SWMASK ('A') | SWMASK ('T'))))
1390 sim_deb_switches |= SWMASK ('T');
1391 }
1392 if (!sim_quiet) {
1393 sim_printf ("Debug output to \"%s\"\n", sim_logfile_name (sim_deb, sim_deb_ref));
1394 if (sim_deb_switches & SWMASK ('P'))
1395 sim_printf (" Debug messages contain current PC value\n");
1396 if (sim_deb_switches & SWMASK ('T'))
1397 sim_printf (" Debug messages display time of day as hh:mm:ss.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : "");
1398 if (sim_deb_switches & SWMASK ('A'))
1399 sim_printf (" Debug messages display time of day as seconds.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : "");
1400 time(&now);
1401 fprintf (sim_deb, "Debug output to \"%s\" at %s", sim_logfile_name (sim_deb, sim_deb_ref), ctime(&now));
1402 show_version (sim_deb, NULL, NULL, 0, NULL);
1403 }
1404 if (sim_deb_switches & SWMASK ('N'))
1405 sim_deb_switches &= ~SWMASK ('N');
1406
1407 return SCPE_OK;
1408 }
1409
1410 t_stat sim_debug_flush (void)
1411 {
1412 int32 saved_quiet = sim_quiet;
1413 int32 saved_sim_switches = sim_switches;
1414 int32 saved_deb_switches = sim_deb_switches;
1415 struct timespec saved_deb_basetime = sim_deb_basetime;
1416 char saved_debug_filename[CBUFSIZE];
1417
1418 if (sim_deb == NULL)
1419 return SCPE_OK;
1420
1421 if (sim_deb == sim_log) {
1422 fflush (sim_deb);
1423 return SCPE_OK;
1424 }
1425
1426 strcpy (saved_debug_filename, sim_logfile_name (sim_deb, sim_deb_ref));
1427
1428 sim_quiet = 1;
1429 sim_set_deboff (0, NULL);
1430 sim_switches = saved_deb_switches;
1431 sim_set_debon (0, saved_debug_filename);
1432 sim_deb_basetime = saved_deb_basetime;
1433 sim_switches = saved_sim_switches;
1434 sim_quiet = saved_quiet;
1435 return SCPE_OK;
1436 }
1437
1438
1439
1440 t_stat sim_set_deboff (int32 flag, CONST char *cptr)
1441 {
1442 if (cptr && (*cptr != 0))
1443 return SCPE_2MARG;
1444 if (sim_deb == NULL)
1445 return SCPE_OK;
1446 sim_close_logfile (&sim_deb_ref);
1447 sim_deb = NULL;
1448 sim_deb_switches = 0;
1449 if (!sim_quiet)
1450 sim_printf ("Debug output disabled\n");
1451 return SCPE_OK;
1452 }
1453
1454
1455
1456 t_stat sim_show_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
1457 {
1458 int32 i;
1459
1460 if (cptr && (*cptr != 0))
1461 return SCPE_2MARG;
1462 if (sim_deb) {
1463 fprintf (st, "Debug output enabled to \"%s\"\n",
1464 sim_logfile_name (sim_deb, sim_deb_ref));
1465 if (sim_deb_switches & SWMASK ('P'))
1466 fprintf (st, " Debug messages contain current PC value\n");
1467 if (sim_deb_switches & SWMASK ('T'))
1468 fprintf (st, " Debug messages display time of day as hh:mm:ss.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : "");
1469 if (sim_deb_switches & SWMASK ('A'))
1470 fprintf (st, " Debug messages display time of day as seconds.msec%s\n", sim_deb_switches & SWMASK ('R') ? " relative to the start of debugging" : "");
1471 for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
1472 if (!(dptr->flags & DEV_DIS) &&
1473 (dptr->flags & DEV_DEBUG) &&
1474 (dptr->dctrl)) {
1475 fprintf (st, "Device: %-6s ", dptr->name);
1476 show_dev_debug (st, dptr, NULL, 0, NULL);
1477 }
1478 }
1479 for (i = 0; sim_internal_device_count && (dptr = sim_internal_devices[i]); ++i) {
1480 if (!(dptr->flags & DEV_DIS) &&
1481 (dptr->flags & DEV_DEBUG) &&
1482 (dptr->dctrl)) {
1483 fprintf (st, "Device: %-6s ", dptr->name);
1484 show_dev_debug (st, dptr, NULL, 0, NULL);
1485 }
1486 }
1487 }
1488 else fprintf (st, "Debug output disabled\n");
1489 return SCPE_OK;
1490 }
1491
1492
1493
1494
1495
1496 t_stat sim_set_telnet (int32 flag, CONST char *cptr)
1497 {
1498 char *cvptr, gbuf[CBUFSIZE];
1499 CTAB *ctptr;
1500 t_stat r;
1501
1502 if ((cptr == NULL) || (*cptr == 0))
1503 return SCPE_2FARG;
1504 while (*cptr != 0) {
1505 cptr = get_glyph_nc (cptr, gbuf, ',');
1506 if ((cvptr = strchr (gbuf, '=')))
1507 *cvptr++ = 0;
1508 (void)get_glyph (gbuf, gbuf, 0);
1509 if ((ctptr = find_ctab (set_con_telnet_tab, gbuf))) {
1510 r = ctptr->action (ctptr->arg, cvptr);
1511 if (r != SCPE_OK)
1512 return r;
1513 }
1514 else {
1515 if (sim_con_tmxr.master)
1516 sim_set_notelnet (0, NULL);
1517 r = tmxr_attach (&sim_con_tmxr, &sim_con_unit, gbuf);
1518 if (r == SCPE_OK)
1519 sim_activate_after(&sim_con_unit, 1000000);
1520 else
1521 return r;
1522 }
1523 }
1524 return SCPE_OK;
1525 }
1526
1527
1528
1529 t_stat sim_set_notelnet (int32 flag, CONST char *cptr)
1530 {
1531 if (cptr && (*cptr != 0))
1532 return SCPE_2MARG;
1533 if (sim_con_tmxr.master == 0)
1534 return SCPE_OK;
1535 return tmxr_close_master (&sim_con_tmxr);
1536 }
1537
1538
1539
1540 t_stat sim_show_telnet (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr)
1541 {
1542 if (cptr && (*cptr != 0))
1543 return SCPE_2MARG;
1544 if ((sim_con_tmxr.master == 0) &&
1545 (sim_con_ldsc.serport == 0))
1546 fprintf (st, "Connected to console window\n");
1547 else {
1548 if (sim_con_ldsc.serport) {
1549 fprintf (st, "Connected to ");
1550 tmxr_fconns (st, &sim_con_ldsc, -1);
1551 }
1552 else
1553 if (sim_con_ldsc.sock == 0)
1554 fprintf (st, "Listening on port %s\n", sim_con_tmxr.port);
1555 else {
1556 fprintf (st, "Listening on port %s, connection from %s\n",
1557 sim_con_tmxr.port, sim_con_ldsc.ipad);
1558 tmxr_fconns (st, &sim_con_ldsc, -1);
1559 }
1560 tmxr_fstats (st, &sim_con_ldsc, -1);
1561 }
1562 return SCPE_OK;
1563 }
1564
1565
1566
1567 t_stat sim_set_cons_buff (int32 flg, CONST char *cptr)
1568 {
1569 char cmdbuf[CBUFSIZE];
1570
1571 sprintf(cmdbuf, "BUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
1572 return tmxr_open_master (&sim_con_tmxr, cmdbuf);
1573 }
1574
1575
1576
1577 t_stat sim_set_cons_unbuff (int32 flg, CONST char *cptr)
1578 {
1579 char cmdbuf[CBUFSIZE];
1580
1581 sprintf(cmdbuf, "UNBUFFERED%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
1582 return tmxr_open_master (&sim_con_tmxr, cmdbuf);
1583 }
1584
1585
1586
1587 t_stat sim_set_cons_log (int32 flg, CONST char *cptr)
1588 {
1589 char cmdbuf[CBUFSIZE];
1590
1591 sprintf(cmdbuf, "LOG%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
1592 return tmxr_open_master (&sim_con_tmxr, cmdbuf);
1593 }
1594
1595
1596
1597 t_stat sim_set_cons_nolog (int32 flg, CONST char *cptr)
1598 {
1599 char cmdbuf[CBUFSIZE];
1600
1601 sprintf(cmdbuf, "NOLOG%c%s", cptr ? '=' : '\0', cptr ? cptr : "");
1602 return tmxr_open_master (&sim_con_tmxr, cmdbuf);
1603 }
1604
1605 t_stat sim_show_cons_log (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr)
1606 {
1607 if (cptr && (*cptr != 0))
1608 return SCPE_2MARG;
1609 if (sim_con_tmxr.ldsc->txlog)
1610 fprintf (st, "Log File being written to %s\n", sim_con_tmxr.ldsc->txlogname);
1611 else
1612 fprintf (st, "No Logging\n");
1613 return SCPE_OK;
1614 }
1615
1616 t_stat sim_show_cons_buff (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr)
1617 {
1618 if (cptr && (*cptr != 0))
1619 return SCPE_2MARG;
1620 if (!sim_con_tmxr.ldsc->txbfd)
1621 fprintf (st, "Unbuffered\n");
1622 else
1623 fprintf (st, "Buffer Size = %d\n", sim_con_tmxr.ldsc->txbsz);
1624 return SCPE_OK;
1625 }
1626
1627
1628
1629
1630
1631 t_stat sim_show_cons_expect (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CONST char *cptr)
1632 {
1633 return sim_exp_show (st, &sim_con_expect, cptr);
1634 }
1635
1636
1637
1638
1639
1640 t_stat sim_open_logfile (const char *filename, t_bool binary, FILE **pf, FILEREF **pref)
1641 {
1642 char gbuf[CBUFSIZE];
1643 const char *tptr;
1644
1645 if ((filename == NULL) || (*filename == 0))
1646 return SCPE_2FARG;
1647 tptr = get_glyph (filename, gbuf, 0);
1648 if (*tptr != 0)
1649 return SCPE_2MARG;
1650 sim_close_logfile (pref);
1651 *pf = NULL;
1652 if (strcmp (gbuf, "LOG") == 0) {
1653 if (sim_log == NULL)
1654 return SCPE_ARG;
1655 *pf = sim_log;
1656 *pref = sim_log_ref;
1657 if (*pref)
1658 ++(*pref)->refcount;
1659 }
1660 else if (strcmp (gbuf, "DEBUG") == 0) {
1661 if (sim_deb == NULL)
1662 return SCPE_ARG;
1663 *pf = sim_deb;
1664 *pref = sim_deb_ref;
1665 if (*pref)
1666 ++(*pref)->refcount;
1667 }
1668 else if (strcmp (gbuf, "STDOUT") == 0) {
1669 *pf = stdout;
1670 *pref = NULL;
1671 }
1672 else if (strcmp (gbuf, "STDERR") == 0) {
1673 *pf = stderr;
1674 *pref = NULL;
1675 }
1676 else {
1677 *pref = (FILEREF *)calloc (1, sizeof(**pref));
1678 if (!*pref)
1679 return SCPE_MEM;
1680 (void)get_glyph_nc (filename, gbuf, 0);
1681 strncpy ((*pref)->name, gbuf, sizeof((*pref)->name));
1682 if (sim_switches & SWMASK ('N'))
1683 *pf = sim_fopen (gbuf, (binary ? "w+b" : "w+"));
1684 else
1685 *pf = sim_fopen (gbuf, (binary ? "a+b" : "a+"));
1686 if (*pf == NULL) {
1687 FREE (*pref);
1688 *pref = NULL;
1689 return SCPE_OPENERR;
1690 }
1691 (*pref)->file = *pf;
1692 (*pref)->refcount = 1;
1693 }
1694 return SCPE_OK;
1695 }
1696
1697
1698
1699 t_stat sim_close_logfile (FILEREF **pref)
1700 {
1701 if (NULL == *pref)
1702 return SCPE_OK;
1703 (*pref)->refcount = (*pref)->refcount - 1;
1704 if ((*pref)->refcount > 0) {
1705 *pref = NULL;
1706 return SCPE_OK;
1707 }
1708 fclose ((*pref)->file);
1709 FREE (*pref);
1710 *pref = NULL;
1711 return SCPE_OK;
1712 }
1713
1714
1715
1716 const char *sim_logfile_name (const FILE *st, FILEREF *ref)
1717 {
1718 if (!st)
1719 return "";
1720 if (st == stdout)
1721 return "STDOUT";
1722 if (st == stderr)
1723 return "STDERR";
1724 if (!ref)
1725 return "";
1726 return ref->name;
1727 }
1728
1729
1730
1731
1732 t_stat sim_check_console (int32 sec)
1733 {
1734 int32 c, trys = 0;
1735
1736 if (sim_rem_master_mode) {
1737 for (;trys < sec; ++trys) {
1738 sim_rem_con_poll_svc (&sim_rem_con_unit[0]);
1739 if (sim_rem_con_tmxr.ldsc[0].conn)
1740 break;
1741 if ((trys % 10) == 0) {
1742 sim_printf ("Waiting for Remote Console connection\r\n");
1743 fflush (stdout);
1744 if (sim_log)
1745 fflush (sim_log);
1746 }
1747 sim_os_sleep (1);
1748 }
1749 if ((sim_rem_con_tmxr.ldsc[0].conn) &&
1750 (!sim_con_ldsc.serport) &&
1751 (sim_con_tmxr.master == 0) &&
1752 (sim_con_console_port)) {
1753 tmxr_linemsgf (&sim_rem_con_tmxr.ldsc[0], "\r\nConsole port must be Telnet or Serial with Master Remote Console\r\n");
1754 tmxr_linemsgf (&sim_rem_con_tmxr.ldsc[0], "Goodbye\r\n");
1755 while (tmxr_send_buffered_data (&sim_rem_con_tmxr.ldsc[0]))
1756 sim_os_ms_sleep (100);
1757 sim_os_ms_sleep (100);
1758 tmxr_reset_ln (&sim_rem_con_tmxr.ldsc[0]);
1759 sim_printf ("Console port must be Telnet or Serial with Master Remote Console\r\n");
1760 return SCPE_EXIT;
1761 }
1762 }
1763 if (trys == sec) {
1764 return SCPE_TTMO;
1765 }
1766 if (sim_con_ldsc.serport)
1767 if (tmxr_poll_conn (&sim_con_tmxr) >= 0)
1768 sim_con_ldsc.rcve = 1;
1769 if ((sim_con_tmxr.master == 0) ||
1770 (sim_con_ldsc.serport))
1771 return SCPE_OK;
1772 if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) {
1773 tmxr_poll_rx (&sim_con_tmxr);
1774 if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) {
1775 if (!sim_con_ldsc.conn) {
1776 sim_printf ("Running with Buffered Console\r\n");
1777 fflush (stdout);
1778 if (sim_log)
1779 fflush (sim_log);
1780 }
1781 return SCPE_OK;
1782 }
1783 }
1784 for (; trys < sec; trys++) {
1785 if (tmxr_poll_conn (&sim_con_tmxr) >= 0) {
1786 sim_con_ldsc.rcve = 1;
1787 if (trys) {
1788 sim_printf ("Running\r\n");
1789 fflush (stdout);
1790 if (sim_log)
1791 fflush (sim_log);
1792 }
1793 return SCPE_OK;
1794 }
1795 c = sim_os_poll_kbd ();
1796 if ((c == SCPE_STOP) || stop_cpu)
1797 return SCPE_STOP;
1798 if ((trys % 10) == 0) {
1799 sim_printf ("Waiting for console Telnet connection\r\n");
1800 fflush (stdout);
1801 if (sim_log)
1802 fflush (sim_log);
1803 }
1804 sim_os_sleep (1);
1805 }
1806 return SCPE_TTMO;
1807 }
1808
1809
1810
1811 SEND *sim_cons_get_send (void)
1812 {
1813 return &sim_con_send;
1814 }
1815
1816
1817
1818 EXPECT *sim_cons_get_expect (void)
1819 {
1820 return &sim_con_expect;
1821 }
1822
1823
1824
1825 t_stat sim_show_cons_send_input (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr)
1826 {
1827 return sim_show_send_input (st, &sim_con_send);
1828 }
1829
1830
1831
1832 t_stat sim_poll_kbd (void)
1833 {
1834 t_stat c;
1835
1836 if (!sim_localopc)
1837 return SCPE_OK;
1838
1839 if (sim_send_poll_data (&sim_con_send, &c))
1840 return c;
1841 if (!sim_rem_master_mode) {
1842 if ((sim_con_ldsc.rxbps) &&
1843 (sim_gtime () < sim_con_ldsc.rxnexttime))
1844 return SCPE_OK;
1845 c = sim_os_poll_kbd ();
1846 if (c == SCPE_STOP) {
1847 stop_cpu = 1;
1848 return SCPE_OK;
1849 }
1850 if ((sim_con_tmxr.master == 0) &&
1851 (sim_con_ldsc.serport == 0)) {
1852 if (c && sim_con_ldsc.rxbps)
1853 sim_con_ldsc.rxnexttime =
1854 floor (sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ())/sim_con_ldsc.rxbpsfactor));
1855 return c;
1856 }
1857 if (!sim_con_ldsc.conn) {
1858 if (!sim_con_ldsc.txbfd)
1859 return SCPE_LOST;
1860 if (tmxr_poll_conn (&sim_con_tmxr) >= 0)
1861 sim_con_ldsc.rcve = 1;
1862 else
1863 return SCPE_OK;
1864 }
1865 }
1866 tmxr_poll_rx (&sim_con_tmxr);
1867 if ((c = (t_stat)tmxr_getc_ln (&sim_con_ldsc)))
1868 return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG;
1869 return SCPE_OK;
1870 }
1871
1872
1873
1874 t_stat sim_putchar (int32 c)
1875 {
1876 sim_exp_check (&sim_con_expect, c);
1877 if ((sim_con_tmxr.master == 0) &&
1878 (sim_con_ldsc.serport == 0)) {
1879 if (sim_log)
1880 fputc (c, sim_log);
1881 return sim_os_putchar (c);
1882 }
1883 if (!sim_con_ldsc.conn) {
1884 if (!sim_con_ldsc.txbfd)
1885 return SCPE_LOST;
1886 if (tmxr_poll_conn (&sim_con_tmxr) >= 0)
1887 sim_con_ldsc.rcve = 1;
1888 }
1889 tmxr_putc_ln (&sim_con_ldsc, c);
1890 tmxr_poll_tx (&sim_con_tmxr);
1891 return SCPE_OK;
1892 }
1893
1894
1895
1896
1897
1898
1899
1900 t_stat sim_ttinit (void)
1901 {
1902 sim_con_tmxr.ldsc->mp = &sim_con_tmxr;
1903 sim_register_internal_device (&sim_con_telnet);
1904 tmxr_startup ();
1905 return sim_os_ttinit ();
1906 }
1907
1908 t_stat sim_ttrun (void)
1909 {
1910 if (!sim_con_tmxr.ldsc->uptr) {
1911 sim_con_unit.dynflags &= ~UNIT_TM_POLL;
1912 sim_con_unit.dynflags |= TMUF_NOASYNCH;
1913 }
1914
1915
1916
1917
1918 tmxr_start_poll ();
1919 return sim_os_ttrun ();
1920 }
1921
1922 t_stat sim_ttcmd (void)
1923 {
1924 tmxr_stop_poll ();
1925 return sim_os_ttcmd ();
1926 }
1927
1928 t_stat sim_ttclose (void)
1929 {
1930 t_stat r1 = tmxr_shutdown ();
1931 t_stat r2 = sim_os_ttclose ();
1932
1933 if (r1 != SCPE_OK)
1934 return r1;
1935
1936 return r2;
1937 }
1938
1939 t_bool sim_ttisatty (void)
1940 {
1941 return sim_os_ttisatty ();
1942 }
1943
1944
1945
1946 #if defined (_WIN32)
1947
1948 # include <fcntl.h>
1949 # include <io.h>
1950 # include <windows.h>
1951 # define RAW_MODE 0
1952 static HANDLE std_input;
1953 static HANDLE std_output;
1954 static DWORD saved_mode;
1955
1956
1957
1958
1959
1960
1961
1962
1963 static BOOL WINAPI
1964 ControlHandler(DWORD dwCtrlType)
1965 {
1966 DWORD Mode;
1967 extern void int_handler (int sig);
1968
1969 switch (dwCtrlType)
1970 {
1971 case CTRL_BREAK_EVENT:
1972 case CTRL_C_EVENT:
1973 int_handler(0);
1974 return TRUE;
1975 case CTRL_CLOSE_EVENT:
1976 case CTRL_LOGOFF_EVENT:
1977 if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &Mode))
1978 return TRUE;
1979
1980 case CTRL_SHUTDOWN_EVENT:
1981 int_handler(0);
1982 return TRUE;
1983 }
1984 return FALSE;
1985 }
1986
1987 static t_stat sim_os_ttinit (void)
1988 {
1989 SetConsoleCtrlHandler( ControlHandler, TRUE );
1990 std_input = GetStdHandle (STD_INPUT_HANDLE);
1991 std_output = GetStdHandle (STD_OUTPUT_HANDLE);
1992 if ((std_input) &&
1993 (std_input != INVALID_HANDLE_VALUE))
1994 GetConsoleMode (std_input, &saved_mode);
1995 return SCPE_OK;
1996 }
1997
1998 static t_stat sim_os_ttrun (void)
1999 {
2000 if ((std_input) &&
2001 (std_input != INVALID_HANDLE_VALUE) &&
2002 (!GetConsoleMode(std_input, &saved_mode) ||
2003 !SetConsoleMode(std_input, RAW_MODE)))
2004 return SCPE_TTYERR;
2005 if (sim_log) {
2006 fflush (sim_log);
2007 _setmode (_fileno (sim_log), _O_BINARY);
2008 }
2009 sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL);
2010 return SCPE_OK;
2011 }
2012
2013 static t_stat sim_os_ttcmd (void)
2014 {
2015 if (sim_log) {
2016 fflush (sim_log);
2017 _setmode (_fileno (sim_log), _O_TEXT);
2018 }
2019 sim_os_set_thread_priority (PRIORITY_NORMAL);
2020 if ((std_input) &&
2021 (std_input != INVALID_HANDLE_VALUE) &&
2022 (!SetConsoleMode(std_input, saved_mode)))
2023 return SCPE_TTYERR;
2024 return SCPE_OK;
2025 }
2026
2027 static t_stat sim_os_ttclose (void)
2028 {
2029 return SCPE_OK;
2030 }
2031
2032 static t_bool sim_os_ttisatty (void)
2033 {
2034 DWORD Mode;
2035
2036 return (std_input) && (std_input != INVALID_HANDLE_VALUE) && GetConsoleMode (std_input, &Mode);
2037 }
2038
2039 static t_stat sim_os_poll_kbd (void)
2040 {
2041 int c = -1;
2042 DWORD nkbevents, nkbevent;
2043 INPUT_RECORD rec;
2044
2045 sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_poll_kbd()\n");
2046
2047 if ((std_input == NULL) ||
2048 (std_input == INVALID_HANDLE_VALUE))
2049 return SCPE_OK;
2050 if (!GetNumberOfConsoleInputEvents(std_input, &nkbevents))
2051 return SCPE_TTYERR;
2052 while (c == -1) {
2053 if (0 == nkbevents)
2054 return SCPE_OK;
2055 if (!ReadConsoleInput(std_input, &rec, 1, &nkbevent))
2056 return SCPE_TTYERR;
2057 if (0 == nkbevent)
2058 return SCPE_OK;
2059 --nkbevents;
2060 if (rec.EventType == KEY_EVENT) {
2061 if (rec.Event.KeyEvent.bKeyDown) {
2062 if (0 == rec.Event.KeyEvent.uChar.UnicodeChar) {
2063 if (rec.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE)
2064 c = sim_brk_char | SCPE_BREAK;
2065 else
2066 if (rec.Event.KeyEvent.wVirtualKeyCode == '2')
2067 c = 0;
2068 } else
2069 c = rec.Event.KeyEvent.uChar.AsciiChar;
2070 }
2071 }
2072 }
2073 if ((c & 0177) == sim_del_char)
2074 c = 0177;
2075 if ((c & 0177) == sim_int_char)
2076 return SCPE_STOP;
2077 if ((sim_brk_char && ((c & 0177) == sim_brk_char)) || (c & SCPE_BREAK))
2078 return SCPE_BREAK;
2079 return c | SCPE_KFLAG;
2080 }
2081
2082 # define BELL_CHAR 7
2083 # define BELL_INTERVAL_MS 500
2084 static t_stat sim_os_putchar (int32 c)
2085 {
2086 DWORD unused;
2087 static uint32 last_bell_time;
2088
2089 if (!sim_localopc)
2090 return SCPE_OK;
2091
2092 if (c != 0177) {
2093 if (c == BELL_CHAR) {
2094 uint32 now = sim_os_msec ();
2095
2096 if ((now - last_bell_time) > BELL_INTERVAL_MS) {
2097 WriteConsoleA(std_output, &c, 1, &unused, NULL);
2098 last_bell_time = now;
2099 }
2100 }
2101 else
2102 WriteConsoleA(std_output, &c, 1, &unused, NULL);
2103 }
2104 return SCPE_OK;
2105 }
2106
2107 #elif defined (BSDTTY)
2108
2109
2110
2111 # include <sgtty.h>
2112 # include <fcntl.h>
2113 # include <unistd.h>
2114
2115 struct sgttyb cmdtty, runtty;
2116 struct tchars cmdtchars, runtchars;
2117 struct ltchars cmdltchars, runltchars;
2118 int cmdfl,runfl;
2119
2120 static t_stat sim_os_ttinit (void)
2121 {
2122 cmdfl = fcntl (0, F_GETFL, 0);
2123 runfl = cmdfl | FNDELAY;
2124 if (ioctl (0, TIOCGETP, &cmdtty) < 0)
2125 return SCPE_TTIERR;
2126 if (ioctl (0, TIOCGETC, &cmdtchars) < 0)
2127 return SCPE_TTIERR;
2128 if (ioctl (0, TIOCGLTC, &cmdltchars) < 0)
2129 return SCPE_TTIERR;
2130 runtty = cmdtty;
2131 runtty.sg_flags = cmdtty.sg_flags & ~(ECHO|CRMOD) | CBREAK;
2132 runtchars.t_intrc = sim_int_char;
2133 runtchars.t_quitc = 0xFF;
2134 runtchars.t_startc = 0xFF;
2135 runtchars.t_stopc = 0xFF;
2136 runtchars.t_eofc = 0xFF;
2137 runtchars.t_brkc = 0xFF;
2138 runltchars.t_suspc = 0xFF;
2139 runltchars.t_dsuspc = 0xFF;
2140 runltchars.t_rprntc = 0xFF;
2141 runltchars.t_flushc = 0xFF;
2142 runltchars.t_werasc = 0xFF;
2143 runltchars.t_lnextc = 0xFF;
2144 return SCPE_OK;
2145 }
2146
2147 static t_stat sim_os_ttrun (void)
2148 {
2149 runtchars.t_intrc = sim_int_char;
2150 (void)fcntl (0, F_SETFL, runfl);
2151 if (ioctl (0, TIOCSETP, &runtty) < 0)
2152 return SCPE_TTIERR;
2153 if (ioctl (0, TIOCSETC, &runtchars) < 0)
2154 return SCPE_TTIERR;
2155 if (ioctl (0, TIOCSLTC, &runltchars) < 0)
2156 return SCPE_TTIERR;
2157 sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL);
2158 return SCPE_OK;
2159 }
2160
2161 static t_stat sim_os_ttcmd (void)
2162 {
2163 sim_os_set_thread_priority (PRIORITY_NORMAL);
2164 (void)fcntl (0, F_SETFL, cmdfl);
2165 if (ioctl (0, TIOCSETP, &cmdtty) < 0)
2166 return SCPE_TTIERR;
2167 if (ioctl (0, TIOCSETC, &cmdtchars) < 0)
2168 return SCPE_TTIERR;
2169 if (ioctl (0, TIOCSLTC, &cmdltchars) < 0)
2170 return SCPE_TTIERR;
2171 return SCPE_OK;
2172 }
2173
2174 static t_stat sim_os_ttclose (void)
2175 {
2176 return sim_ttcmd ();
2177 }
2178
2179 static t_bool sim_os_ttisatty (void)
2180 {
2181 return isatty (fileno (stdin));
2182 }
2183
2184 static t_stat sim_os_poll_kbd (void)
2185 {
2186 int status;
2187 unsigned char buf[1];
2188
2189 status = read (0, buf, 1);
2190 if (status != 1) return SCPE_OK;
2191 if (sim_brk_char && (buf[0] == sim_brk_char))
2192 return SCPE_BREAK;
2193 if (sim_int_char && (buf[0] == sim_int_char))
2194 return SCPE_STOP;
2195 return (buf[0] | SCPE_KFLAG);
2196 }
2197
2198 static t_stat sim_os_putchar (int32 out)
2199 {
2200 char c;
2201
2202 if (!sim_localopc)
2203 return SCPE_OK;
2204
2205 c = out;
2206 if (write (1, &c, 1)) {};
2207 return SCPE_OK;
2208 }
2209
2210
2211
2212 #else
2213
2214 # include <termios.h>
2215 # include <unistd.h>
2216
2217 struct termios cmdtty, runtty;
2218
2219 static t_stat sim_os_ttinit (void)
2220 {
2221 if (!isatty (fileno (stdin)))
2222 return SCPE_OK;
2223 if (tcgetattr (0, &cmdtty) < 0)
2224 return SCPE_TTIERR;
2225 runtty = cmdtty;
2226 runtty.c_lflag = runtty.c_lflag & ~(ECHO | ICANON);
2227 runtty.c_oflag = runtty.c_oflag & ~OPOST;
2228 runtty.c_iflag = runtty.c_iflag & ~ICRNL;
2229 runtty.c_cc[VINTR] = sim_int_char;
2230 runtty.c_cc[VQUIT] = 0;
2231 runtty.c_cc[VERASE] = 0;
2232 runtty.c_cc[VKILL] = 0;
2233 runtty.c_cc[VEOF] = 0;
2234 runtty.c_cc[VEOL] = 0;
2235 runtty.c_cc[VSTART] = 0;
2236 runtty.c_cc[VSUSP] = 0;
2237 runtty.c_cc[VSTOP] = 0;
2238 # if defined (VREPRINT)
2239 runtty.c_cc[VREPRINT] = 0;
2240 # endif
2241 # if defined (VDISCARD)
2242 runtty.c_cc[VDISCARD] = 0;
2243 # endif
2244 # if defined (VWERASE)
2245 runtty.c_cc[VWERASE] = 0;
2246 # endif
2247 # if defined (VLNEXT)
2248 runtty.c_cc[VLNEXT] = 0;
2249 # endif
2250 runtty.c_cc[VMIN] = 0;
2251 runtty.c_cc[VTIME] = 0;
2252 # if defined (VDSUSP)
2253 runtty.c_cc[VDSUSP] = 0;
2254 # endif
2255 # if defined (VSTATUS)
2256 runtty.c_cc[VSTATUS] = 0;
2257 # endif
2258 return SCPE_OK;
2259 }
2260
2261 static t_stat sim_os_ttrun (void)
2262 {
2263 if (!isatty (fileno (stdin)))
2264 return SCPE_OK;
2265 runtty.c_cc[VINTR] = sim_int_char;
2266 if (tcsetattr (0, TCSAFLUSH, &runtty) < 0)
2267 return SCPE_TTIERR;
2268 sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL);
2269 return SCPE_OK;
2270 }
2271
2272 static t_stat sim_os_ttcmd (void)
2273 {
2274 if (!isatty (fileno (stdin)))
2275 return SCPE_OK;
2276 sim_os_set_thread_priority (PRIORITY_NORMAL);
2277 if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0)
2278 return SCPE_TTIERR;
2279 return SCPE_OK;
2280 }
2281
2282 static t_stat sim_os_ttclose (void)
2283 {
2284 return sim_ttcmd ();
2285 }
2286
2287 static t_bool sim_os_ttisatty (void)
2288 {
2289 return isatty (fileno (stdin));
2290 }
2291
2292 static t_stat sim_os_poll_kbd (void)
2293 {
2294 int status;
2295 unsigned char buf[1];
2296
2297 status = read (0, buf, 1);
2298 if (status != 1) return SCPE_OK;
2299 if (sim_brk_char && (buf[0] == sim_brk_char))
2300 return SCPE_BREAK;
2301 if (sim_int_char && (buf[0] == sim_int_char))
2302 return SCPE_STOP;
2303 return (buf[0] | SCPE_KFLAG);
2304 }
2305
2306 static t_stat sim_os_putchar (int32 out)
2307 {
2308 char c;
2309
2310 if (!sim_localopc)
2311 return SCPE_OK;
2312
2313 c = out;
2314 (void)!write (1, &c, 1);
2315 return SCPE_OK;
2316 }
2317
2318 #endif
2319
2320
2321
2322
2323
2324
2325
2326 #define ESC_CHAR '~'
2327
2328 static void decode (char *decoded, const char *encoded)
2329 {
2330 char c;
2331
2332
2333 while ((c = *decoded++ = *encoded++))
2334 if (c == ESC_CHAR) {
2335 if ((isalpha ((unsigned char)*encoded)) ||
2336 (*encoded == '@') ||
2337 ((*encoded >= '[') && (*encoded <= '_')))
2338
2339 *(decoded - 1) = *encoded++ & 037;
2340 else {
2341 if ((*encoded == '\0') ||
2342 (*encoded++ != ESC_CHAR))
2343 decoded--;
2344 }
2345 }
2346 return;
2347 }
2348
2349
2350
2351 static t_stat sim_set_halt (int32 flag, CONST char *cptr)
2352 {
2353 if (flag == 0)
2354 sim_exp_clrall (&sim_con_expect);
2355 else {
2356 char *mbuf;
2357 char *mbuf2;
2358
2359 if (cptr == NULL || *cptr == 0)
2360 return SCPE_2FARG;
2361
2362 sim_exp_clrall (&sim_con_expect);
2363
2364 mbuf = (char *)malloc (1 + strlen (cptr));
2365 if (!mbuf)
2366 {
2367 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
2368 __func__, __FILE__, __LINE__);
2369 #if defined(USE_BACKTRACE)
2370 # ifdef SIGUSR2
2371 (void)raise(SIGUSR2);
2372
2373 # endif
2374 #endif
2375 abort();
2376 }
2377 decode (mbuf, cptr);
2378
2379 mbuf2 = (char *)malloc (3 + strlen(cptr));
2380 if (!mbuf2)
2381 {
2382 fprintf (stderr, "\rFATAL: Out out memory! Aborting at %s[%s:%d]\r\n",
2383 __func__, __FILE__, __LINE__);
2384 #if defined(USE_BACKTRACE)
2385 # ifdef SIGUSR2
2386 (void)raise(SIGUSR2);
2387
2388 # endif
2389 #endif
2390 abort();
2391 }
2392 sprintf (mbuf2, "%s%s%s", (sim_switches & SWMASK ('A')) ? "\n" : "",
2393 mbuf,
2394 (sim_switches & SWMASK ('I')) ? "" : "\n");
2395 FREE (mbuf);
2396 mbuf = sim_encode_quoted_string ((uint8 *)mbuf2, strlen (mbuf2));
2397 sim_exp_set (&sim_con_expect, mbuf, 0, sim_con_expect.after, EXP_TYP_PERSIST, NULL);
2398 FREE (mbuf);
2399 FREE (mbuf2);
2400 }
2401
2402 return SCPE_OK;
2403 }
2404
2405
2406
2407 static t_stat sim_set_response (int32 flag, CONST char *cptr)
2408 {
2409 if (flag == 0)
2410 sim_send_clear (&sim_con_send);
2411 else {
2412 uint8 *rbuf;
2413
2414 if (cptr == NULL || *cptr == 0)
2415 return SCPE_2FARG;
2416
2417 rbuf = (uint8 *)malloc (1 + strlen(cptr));
2418 if (!rbuf)
2419 {
2420 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
2421 __func__, __FILE__, __LINE__);
2422 #if defined(USE_BACKTRACE)
2423 # ifdef SIGUSR2
2424 (void)raise(SIGUSR2);
2425
2426 # endif
2427 #endif
2428 abort();
2429 }
2430
2431 decode ((char *)rbuf, cptr);
2432 sim_send_input (&sim_con_send, rbuf, strlen((char *)rbuf), 0, 0);
2433 FREE (rbuf);
2434 }
2435
2436 return SCPE_OK;
2437 }
2438
2439
2440
2441 static t_stat sim_set_delay (int32 flag, CONST char *cptr)
2442 {
2443 int32 val;
2444 t_stat r;
2445
2446 if (cptr == NULL || *cptr == 0)
2447 return SCPE_2FARG;
2448
2449 val = (int32) get_uint (cptr, 10, INT_MAX, &r);
2450
2451 if (r == SCPE_OK)
2452 sim_con_expect.after = val;
2453
2454 return r;
2455 }