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