void do_command(char c) { switch (c) { case '.': case '\004': /* ^D */ event_loopexit(NULL); break; case '\032': /* ^Z */ restore_termios(); kill(getpid(), SIGTSTP); set_termios(); break; case 'C': connect_command(); break; case 'D': ioctl(line_fd, TIOCCDTR, NULL); sleep(1); ioctl(line_fd, TIOCSDTR, NULL); break; case 'R': start_record(); break; case 'S': set_speed(); break; case 'X': send_xmodem(); break; case '$': pipe_command(); break; case '>': send_file(); break; case '#': ioctl(line_fd, TIOCSBRK, NULL); sleep(1); ioctl(line_fd, TIOCCBRK, NULL); break; case '~': bufferevent_write(line_ev, "~", 1); break; case '?': printf("\r\n" "~# send break\r\n" "~$ pipe local command to remote host\r\n" "~> send file to remote host\r\n" "~C connect program to remote host\r\n" "~D de-assert DTR line briefly\r\n" "~R start recording to file\r\n" "~S set speed\r\n" "~X send file with XMODEM\r\n" "~? get this summary\r\n" ); break; } }
void signal_event(int fd, short events, void *data) { restore_termios(); printf("\r\n[SIG%s]\n", sys_signame[fd]); exit(0); }
void connect_command(void) { const char *cmd; pid_t pid; /* * Fork a program with: * 0 <-> remote tty in * 1 <-> remote tty out * 2 <-> local tty stderr */ cmd = get_input("Local command?"); if (cmd == NULL || *cmd == '\0') return; restore_termios(); switch (pid = fork()) { case -1: cu_err(1, "fork"); case 0: if (signal(SIGINT, SIG_DFL) == SIG_ERR) _exit(1); if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) _exit(1); /* attach stdout and stdin to line */ if (dup2(line_fd, STDOUT_FILENO) == -1) _exit(1); if (dup2(line_fd, STDIN_FILENO) == -1) _exit(1); if (closefrom(STDERR_FILENO + 1) != 0) _exit(1); execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL); _exit(1); default: while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) /* nothing */; break; } set_termios(); }
void pipe_command(void) { const char *cmd; pid_t pid; int fd; cmd = get_input("Local command?"); if (cmd == NULL || *cmd == '\0') return; restore_termios(); switch (pid = fork()) { case -1: cu_err(1, "fork"); case 0: fd = open(_PATH_DEVNULL, O_RDWR); if (fd < 0 || dup2(fd, STDIN_FILENO) == -1) _exit(1); close(fd); if (signal(SIGINT, SIG_DFL) == SIG_ERR) _exit(1); if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) _exit(1); /* attach stdout to line */ if (dup2(line_fd, STDOUT_FILENO) == -1) _exit(1); if (closefrom(STDERR_FILENO + 1) != 0) _exit(1); execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL); _exit(1); default: while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) /* nothing */; break; } set_termios(); }
int main(int argc, char *argv[]) { int x; int diskn = 0; int gotox = 0; mon_out = stdout; mon_in = stdin; char *facts_name = "facts"; for (x = 1; x != argc; ++x) { if (argv[x][0] == '-') { if (!strcmp(argv[x], "--facts") && x + 1 != argc) { ++x; facts_name = argv[x]; } else if (!strcmp(argv[x], "--trace")) { trace = 1; } else if (!strcmp(argv[x], "--swtpc")) { swtpc = 1; } else if (!strcmp(argv[x], "--dtrace")) { trace_disk = 1; } else if (!strcmp(argv[x], "--mon")) { stop = 1; } else if (!strcmp(argv[x], "--skip") && x + 1 != argc) { ++x; skip = atoi(argv[x]); } else if (!strcmp(argv[x], "--exbug") && x + 1 != argc) { exbug_name = argv[++x]; } else if (!strcmp(argv[x], "-x")) { gotox = 1; } else if (!strcmp(argv[x], "--lower")) { lower = 1; } else { printf("EXORciser emulator\n"); printf("\n"); printf("exor [options] [disk0 [disk1 [disk2 [disk3]]]]\n"); printf("\n"); printf(" --trace Produce instruction trace on stderr\n"); printf(" --dtrace Produce disk access trace on stderr\n"); printf(" --skip nnn Skip first nnn insns in trace\n"); printf(" --swtpc Simulate SWTPC instead of EXORciser\n"); printf(" --exbug name Give name for ROM if not 'exbug.bin'\n"); printf(" -x Go into EXBUG/SWTBUG instead of MDOS/FLEX\n"); printf(" --facts file Process facts files for commented disassembly\n"); printf(" --lower Allow lowercase\n"); printf(" --mon Start at monitor prompt\n"); printf("\n"); printf("Default disk0 is mdos.dsk/flex.dsk\n"); printf("\n"); printf("Hints:\n"); printf(" To load MDOS from EXBUG, type MAID followed by E800;G\n"); printf("\n"); printf(" To load FLEX2 from SWTBUG, type D\n"); printf("\n"); exit(-1); } } else { if (diskn == 4) { printf("Only up to four disks allowed\n"); return -1; } else { drive[diskn++].name = argv[x]; } } } /* Default disk image name */ if (!drive[0].name) if (swtpc) drive[0].name = "flex.dsk"; else drive[0].name = "mdos.dsk"; /* Default memory image name */ if (!exbug_name) { if (swtpc) { exbug_name = "swtbug.bin"; } else { exbug_name = "exbug.bin"; } } /* Load facts file */ if (facts_name) { FILE *f; printf("Load facts file '%s'\n", facts_name); f = fopen(facts_name, "r"); if (f) { parse_facts(f); fclose(f); } else { printf("Couldn't load '%s'\n", facts_name); } } /* Load initial memory image */ if (load_exbug()) { /* Start halted if there is no ROM */ stop = 1; } /* Mount drives */ for (x = 0; x != 4; ++x) { if (drive[x].name) load_drive(x); } if (!drive[0].f) { /* Do not boot DOS if there is no disk */ gotox = 1; } /* Read starting address from reset vector */ pc = ((mem[0xFFFE] << 8) + mem[0xFFFF]); /* ...but jump right to OS load unless gotox is set */ if (!gotox) { if (swtpc) { /* Jump right into flex */ sp = 0xA042; pc = 0xE28F; } else { /* Jump right into MDOS */ sp = 0xFF8A; pc = 0xE800; } } /* system("stty cbreak -echo -icrnl"); */ save_termios(); sim_termios(); signal(SIGINT, ctrl_c); printf("\nHit Ctrl-C for simulator command line. Starting simulation...\n"); izexorterm(); sim(); // echo test of terminal emulator // while (!stop) term_out(term_in()); /* system("stty cooked echo icrnl"); */ restore_termios(); return 0; }
int main(int argc, char **argv) { const char *errstr; char *tmp, *s, *host; int opt, i; if (isatty(STDIN_FILENO) && tcgetattr(STDIN_FILENO, &saved_tio) != 0) err(1, "tcgetattr"); /* * Convert obsolescent -### speed to modern -s### syntax which getopt() * can handle. */ for (i = 1; i < argc; i++) { if (strcmp("--", argv[i]) == 0) break; if (argv[i][0] != '-' || !isdigit((unsigned char)argv[i][1])) continue; if (asprintf(&argv[i], "-s%s", &argv[i][1]) == -1) errx(1, "speed asprintf"); } while ((opt = getopt(argc, argv, "l:s:")) != -1) { switch (opt) { case 'l': line_path = optarg; break; case 's': line_speed = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) errx(1, "speed is %s: %s", errstr, optarg); break; default: usage(); } } argc -= optind; argv += optind; if (argc != 0 && argc != 1) usage(); if (argc == 1) host = argv[0]; else host = getenv("HOST"); if (host != NULL && *host != '\0') { if (*host == '/') line_path = host; else { s = getenv("REMOTE"); if (s != NULL && *s == '/') try_remote(host, s, NULL); else try_remote(host, NULL, s); } } if (line_path == NULL) line_path = "/dev/cua00"; if (line_speed == -1) line_speed = 9600; if (strchr(line_path, '/') == NULL) { if (asprintf(&tmp, "%s%s", _PATH_DEV, line_path) == -1) err(1, "asprintf"); line_path = tmp; } line_fd = open(line_path, O_RDWR); if (line_fd < 0) err(1, "open(\"%s\")", line_path); if (ioctl(line_fd, TIOCEXCL) != 0) err(1, "ioctl(TIOCEXCL)"); if (tcgetattr(line_fd, &line_tio) != 0) err(1, "tcgetattr"); if (set_line(line_speed) != 0) err(1, "tcsetattr"); event_init(); signal_set(&sigterm_ev, SIGTERM, signal_event, NULL); signal_add(&sigterm_ev, NULL); signal_set(&sighup_ev, SIGHUP, signal_event, NULL); signal_add(&sighup_ev, NULL); if (signal(SIGINT, SIG_IGN) == SIG_ERR) err(1, "signal"); if (signal(SIGQUIT, SIG_IGN) == SIG_ERR) err(1, "signal"); set_termios(); /* after this use cu_err and friends */ /* stdin and stdout get separate events */ input_ev = bufferevent_new(STDIN_FILENO, stream_read, NULL, stream_error, NULL); bufferevent_enable(input_ev, EV_READ); output_ev = bufferevent_new(STDOUT_FILENO, NULL, NULL, stream_error, NULL); bufferevent_enable(output_ev, EV_WRITE); line_ev = bufferevent_new(line_fd, line_read, NULL, line_error, NULL); bufferevent_enable(line_ev, EV_READ|EV_WRITE); printf("Connected to %s (speed %d)\r\n", line_path, line_speed); event_dispatch(); restore_termios(); printf("\r\n[EOT]\n"); exit(0); }