📄 terminal.c
字号:
/* * Start the terminal dialogue, scan the TTY, keyboard, and the "script" * for input, watch for the hot key so we can execute an option. */#include <stdio.h>#include <curses.h>#include <signal.h>#include "config.h"#include "dial_dir.h"#include "ipc.h"#include "misc.h"#include "modem.h"#include "param.h"#include "status.h"#include "xmodem.h"#ifdef BSD#ifndef SIGCLD#define SIGCLD SIGCHLD#endif /* SIGCLD */#include <sys/file.h>#else /* BSD */#include <fcntl.h>#endif /* BSD */#ifdef UNIXPC#include <sys/phone.h>#endif /* UNIXPC */static void key_input();static int cr_lf;voidterminal(script)char *script;{ extern int fd; int ret_code; void tty_input(), st_line(), term_mode(), cmd_input(), do_script(); void is_active(), ipc_init(); ipc_init(fd, status->cmd_ipc); /* if not starting with -f option */ if (dir->q_num[0] == -1) { erase(); refresh(); st_line(""); } /* put stdin/stdout in terminal mode */ resetterm(); term_mode(); cr_lf = !strcmp(param->cr_out, "CR/LF"); /* play a script from command line */ if (script != NULL && *script != '\0') do_script(script); /* the main loop ! */ /* CONSTCOND */ while (1) { ret_code = ipc_poll(fd, status->cmd_ipc); if (ret_code & TTY_READY) tty_input(); if (ret_code & KEY_READY) key_input(); /* * This is the reason for the 1 sec "timeout" of the * poll/select call... to periodically check the status * of the "script" for input. */ if (status->dup_fd != -1) is_active(); /* do a command from a script */ if (ret_code & CMD_READY) cmd_input(); } /* NOTREACHED */}/* * There is something ready to be read from the keyboard. */static voidkey_input(){ extern int fd; int i, k; char c, lf=10, *str_rep(), *keymac, *script, *script_menu(); void help_screen(), line_set(), n_shell(), load_vs(), send_str(); void release_port(), list_dir(), pexit(), st_line(), chg_dir(); void screen_dump(), info(), term_mode(), macro(), stop_script(); void setup_menu(), xfer_menu(), data_logging(), pass_thru(); void half_duplex(), do_script(), vs_clear(), tty_restart(); void log_toggle(), lpr_toggle(); read(0, &c, 1); c &= 0x7f; /* stop the script? */ if (status->dup_fd != -1 && c == ESC) { stop_script(); return; } /* is it the hot key? */ if (c == param->hot_key) { script = NULL; /* * Put the terminal in the curses mode, load the * virtual screen and add the status line at the bottom. */ fixterm(); load_vs(); st_line("");#ifndef OLDCURSES keypad(stdscr, TRUE);#endif /* OLDCURSES */ i = wgetch(stdscr); /* map an additional hot key to -1 */ if (i == param->hot_key) i = -1; keymac = ""; /* look for options */ k = -1; switch (i) { case -1: /* 2 "hots" means send 1 */ k = param->hot_key; break; case '0': /* help screen */ help_screen(param->ascii_hot); break; case 'd': case 'D': /* dialing directory */ if (dial_menu()) { if (!dial_win(25)) script = dir->aux[0]; } break; case 'r': case 'R': /* redial */ if (redial()) { if (!dial_win(25)) script = dir->aux[0]; } break; case 'm': case 'M': /* keyboard macros */ macro(); break; case 'p': case 'P': /* line settings */ if (ls_menu()) line_set(); break; case 'x': case 'X': /* exit */ pexit(); break; case '4': /* Unix gateway */ n_shell(); break; case '5': /* Command files */ script = script_menu(); break; case 'i': case 'I': /* program info screen */ info(MANUAL_CLEAR); break; case 's': /* setup menu */ case 'S': setup_menu(); break; case 'c': /* clear the screen */ case 'C': erase(); vs_clear(0); break; case 'b': case 'B': /* change directory */ chg_dir(); break; case 'e': case 'E': /* toggle duplex */ if (dir->duplex[0] == 'F') dir->duplex[0] = 'H'; else dir->duplex[0] = 'F'; /* show changes */ st_line(""); k = wait_key(stdscr, 2); break; case 'h': case 'H': /* hang up phone */ release_port(VERBOSE); break; case 'l': case 'L': /* print toggle */ lpr_toggle(); /* show changes */ st_line(""); k = wait_key(stdscr, 2); break; case '3': /* toggle CR - CR/LF */ if (!strcmp(param->cr_in, "CR")) param->cr_in = str_rep(param->cr_in, "CR/LF"); else param->cr_in = str_rep(param->cr_in, "CR"); /* show changes */ st_line(""); k = wait_key(stdscr, 2); break; case '7': /* break key */ if (fd != -1) tty_break(fd); st_line(" break"); break;#ifndef OLDCURSES case KEY_UP:#endif /* OLDCURSES */ case 'u': case 'U': /* send files */ xfer_menu(UP_LOAD); break;#ifndef OLDCURSES case KEY_DOWN: case '\n':#endif /* OLDCURSES */ case 'n': case 'N': /* receive files */ xfer_menu(DOWN_LOAD); break; case 't': case 'T': pass_thru(); break; case 'f': case 'F': /* list directory */ list_dir(); break; case 'g': /* screen dump */ case 'G': screen_dump(); st_line(" screen dump"); k = wait_key(stdscr, 2); break; case '1': /* data logging */ data_logging(); break; case '2': /* toggle log */ if (!strcmp(status->log_path, "NOT_DEFINED")) { beep(); st_line(" no log file"); k = wait_key(stdscr, 2); break; } log_toggle(); /* show changes */ st_line(""); k = wait_key(stdscr, 2); break; /* * The following are the keyboard macros * corresponding to the shifted number keys. * (Too many keys... [control] [A] [shift] [1] * is hardly a shortcut!) */ case '!': keymac = param->mac_1; break; case '@': keymac = param->mac_2; break; case '#': keymac = param->mac_3; break; case '$': keymac = param->mac_4; break; case '%': keymac = param->mac_5; break; case '^': keymac = param->mac_6; break; case '&': keymac = param->mac_7; break; case '*': keymac = param->mac_8; break; case '(': keymac = param->mac_9; break; case ')': keymac = param->mac_0; break; default: fputc(BEL, stderr); break; } /* * Repaint the stdscr (if we are already talking), * get the stdin/stdout out of the curses mode and * into the terminal mode. */ if (fd != -1) { touchwin(stdscr); refresh(); } resetterm(); term_mode(); /* restart stopped flow control */ tty_restart(); /* * Some of the output processing options have to be * faked... Unfortunately, adding a LF to CR on * output is one of them. */ cr_lf = !strcmp(param->cr_out, "CR/LF"); /* play the script */ if (script != NULL && *script != '\0') do_script(script); /* send the macro */ if (*keymac != '\0') send_str(keymac, FAST); /* * If you pressed a key during one of the sleeping * periods (typically the delay to see the status * line change), let the keyboard value fall thru * to the write() below. */ if (k == -1) return; c = (char) k; } /* ignore errors if fd == -1 */ write(fd, &c, 1); /* * If you're using the half duplex mode, characters don't get * echoed by the driver (cause you don't type them!) */ if (dir->duplex[0] == 'H') half_duplex(c); /* map cr to cr_lf? */ if (c == '\r' && cr_lf) { write(fd, &lf, 1); if (dir->duplex[0] == 'H') { write(1, &lf, 1); half_duplex(lf); } } return;}/* * Hang up the phone but remain in the Pcomm command state. Uses the * hang_up string only, does *not* drop the DTR! */voidhang_up(verbose)int verbose;{ extern int fd; void send_str(), st_line(), tty_restart(); unsigned int sleep(); /* sanity checking */ if (modem == NULL) return; /* anything to hang up? */ if (modem->m_cur == -1 || fd == -1) return; if (verbose) st_line("disconnecting"); /* special case for OBM */ if (!strcmp(modem->mname[modem->m_cur], "OBM")) /* EMPTY */ {#ifdef UNIXPC char buf[80]; void line_set(); ioctl(fd, PIOCDISC); /* * The PIOCDISC ioctl screws up the file descriptor!!! * No other phone(7) ioctl can fix it. Whatever it does, * it seems to escape detection with PIOCGETA and TCGETA. * The best I can do is close the port and start over. */ sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]); close(fd); fd = open(buf, O_RDWR|O_NDELAY); line_set(); tty_noblock(fd, FALSE);#endif /* UNIXPC */ } else { tty_restart(); send_str(modem->hang_up[modem->m_cur], SLOW); sleep(1); } if (verbose) st_line(""); status->connected = 0; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -