This is terminal.c in view mode; [Download] [Up]
/*
* Start the terminal dialogue, fork the input routine, 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 "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 int pid = -1;
terminal(extra_dir, input_status)
char *extra_dir;
int input_status;
{
extern int fd;
int i, j, k, cr_lf, script;
char c, lf=10, *str_rep(), *keymac, *memset();
void help_screen(), line_set(), n_shell(), load_vs(), send_str();
void release_port(), do_input(), list_dir(), pexit(), zap_vs();
void st_line(), chg_dir(), screen_dump(), input_off(), suspend();
void info(), term_mode(), macro(), do_script();
/* if starting out in command mode */
if (!input_status) {
erase();
refresh();
st_line("");
}
/* put stdin/stdout in terminal mode */
resetterm();
term_mode();
cr_lf = !strcmp(param->cr_out, "CR/LF");
if (input_status) {
do_script(extra_dir);
do_input();
}
while (1) {
read(0, &c, 1);
c &= 0x7f;
/* is it the hot key? */
if (c == param->hot) {
/* suspend input */
input_status = 0;
suspend(TRUE);
script = 0;
/*
* 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)
i = -1;
keymac = "";
/* look for options */
k = -1;
switch (i) {
case -1: /* 2 "hots" means send 1 */
k = param->hot;
break;
case '0': /* help screen */
help_screen(param->ascii_hot);
break;
case 'd':
case 'D': /* dialing directory */
if (dial_menu())
input_status = dial_win();
script = input_status;
break;
case 'r':
case 'R': /* redial */
if (redial())
input_status = dial_win();
script = input_status;
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 'i':
case 'I': /* program info screen */
info(MANUAL_CLEAR);
break;
case 's': /* setup menu */
case 'S':
input_status = setup_menu();
break;
case 'c': /* clear the screen */
case 'C':
zap_vs();
erase();
#ifdef SHAREDMEM
if (pid == -1) {
for (j=0; j<LINES; j++)
memset(status->vs[j], ' ', COLS);
}
#endif /* SHAREDMEM */
break;
case 'b':
case 'B': /* change directory */
chg_dir();
break;
case 'e':
case 'E': /* toggle duplex */
if (dir->duplex[dir->d_cur] == 'F')
dir->duplex[dir->d_cur] = 'H';
else
dir->duplex[dir->d_cur] = 'F';
/* show changes */
st_line("");
k = wait_key(stdscr, 2);
break;
case 'h':
case 'H': /* hang up phone */
release_port(VERBOSE);
input_off();
break;
case 'l':
case 'L': /* toggle printer */
status->print = status->print ? 0 : 1;
#ifndef SHAREDMEM
if (pid != -1)
kill(pid, SIGUSR2);
#endif /* SHAREDMEM */
/* 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");
status->add_lf = 1;
}
else {
param->cr_in = str_rep(param->cr_in, "CR");
status->add_lf = 0;
}
#ifndef SHAREDMEM
input_off();
input_status++;
#endif /* SHAREDMEM */
/* 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 */
input_status = xfer_menu(UP_LOAD);
break;
#ifndef OLDCURSES
case KEY_DOWN:
case '\n':
#endif /* OLDCURSES */
case 'n':
case 'N': /* receive files */
input_status = xfer_menu(DOWN_LOAD);
break;
case 't':
case 'T':
input_status = 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 */
input_status = 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;
}
status->log = status->log ? 0 : 1;
#ifndef SHAREDMEM
if (pid != -1)
kill(pid, SIGUSR1);
#endif /* SHAREDMEM */
/* 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();
/*
* 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");
/* run the auto-login script */
if (script)
do_script(extra_dir);
/* re-start input routine */
if (input_status)
do_input();
else
suspend(FALSE);
/* 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)
continue;
c = k;
}
/* ignore errors if fd == -1 */
write(fd, &c, 1);
/* map cr to cr_lf? */
if (c == '\r' && cr_lf) {
write(fd, &lf, 1);
/*
* Since you didn't type it... it doesn't get echoed
* by the driver.
*/
if (dir->duplex[dir->d_cur] == 'H')
write(1, &lf, 1);
}
}
}
/*
* Fire up the input routine...
*/
void
do_input()
{
extern int fd;
void error_win();
char first[(sizeof(int)*8)+1];
#ifdef SHAREDMEM
extern int shm_id;
#else /* SHAREDMEM */
char add_lf[2], log[2], print[2], dup_fd[3];
#endif /* SHAREDMEM */
/* if no TTY, or already on */
if (pid != -1 || fd == -1)
return;
status->fd = fd;
status->add_lf = !strcmp(param->cr_in, "CR/LF");
#ifdef SHAREDMEM
sprintf(first, "%d", shm_id);
#else /* SHAREDMEM */
sprintf(first, "%d", status->fd);
sprintf(dup_fd, "%d", status->dup_fd);
sprintf(add_lf, "%d", status->add_lf);
sprintf(log, "%d", status->log);
sprintf(print, "%d", status->print);
#endif /* SHAREDMEM */
/* fork the input routine */
if (!(pid = fork())) {
#ifdef BSD
setpgrp(0, getpid());
#else /* BSD */
setpgrp();
#endif /* BSD */
#ifdef SETUGID
setuid(getuid());
setgid(getgid());
#endif /* SETUGID */
#ifdef SHAREDMEM
execlp("pcomm_input", "pcomm_input", first, (char *) 0);
#else /* SHAREDMEM */
execlp("pcomm_input", "pcomm_input", first, dup_fd, add_lf,
log, print, status->log_path, status->vs_path, (char *) 0);
#endif /* SHAREDMEM */
error_win(1, "Cannot find (or execute) the 'pcomm_input' program", "");
}
return;
}
/*
* shut it down...
*/
void
input_off()
{
SIG_TYPE (*cstat)();
if (pid != -1) {
/*
* This serves to periodically clean up the process table
*/
cstat = signal(SIGCLD, SIG_IGN);
kill(pid, SIGTERM);
pid = -1;
signal(SIGCLD, cstat);
}
return;
}
/*
* Hang up the phone but remain in the Pcomm command state. Uses the
* hang_up string only, does *not* drop the DTR!
*/
void
hang_up(verbose)
int verbose;
{
extern int fd;
int junk;
void send_str(), st_line(), line_set();
char buf[80];
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")) {
#ifdef UNIXPC
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();
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
#endif /* UNIXPC */
}
else {
send_str(modem->hang_up[modem->m_cur], SLOW);
/*
* Some modems do "damage" to the tty driver when they hang
* up by flashing the modem control lines on the port. The
* following is some witchcraft designed to put the driver
* back the way it was.
*/
sleep(1);
sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]);
junk = open(buf, O_RDWR);
close(junk);
}
if (verbose)
st_line("");
return;
}
/*
* Suspend or un-suspend the input routine. The argument is used in
* non-shared memory configurations to give the vs_path file a fighting
* chance of being written to disk before load_vs() reads it.
*/
/* ARGSUSED */
void
suspend(on)
int on;
{
void tty_restart();
unsigned int sleep();
if (pid == -1)
return;
kill(pid, SIGINT);
if (on) {
#ifndef SHAREDMEM
sleep(1);
#endif /* SHAREDMEM */
}
else /* restart if XOFF received */
tty_restart();
return;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.