334 lines
8.5 KiB
C
334 lines
8.5 KiB
C
/*****************************************************************************
|
|
This program provides basic communication with a remote computer.
|
|
The remote machine is connected to /dev/tty01. It is assumed to be a VAX
|
|
running VMS. This program sends whatever is typed at the keyboard to the
|
|
remote machine and puts whatever the remote machine sends on the terminal
|
|
screen.
|
|
When this program is invoked, connections to the serial port and
|
|
the keyboard are made and the user is left in the communication state. To
|
|
terminate the program, use control-N, then period.
|
|
A special feature is the "trapping" of what the modem sends to one
|
|
or more files. Basically, the program was written to provide a way to
|
|
get a large number of files from the VAX to this machine (XENIX). The idea
|
|
is to log in to the VAX and execute a command like "TYPE *.C". When VAX/VMS
|
|
types out files which match the wildcard filename "*.C", it
|
|
precedes the text of each file with a header line containing the file name.
|
|
This program is sensitive to these headers, and uses them to name output
|
|
files. Thus, running this program and typing "TYPE *.C" to VMS on the
|
|
remote machine should produce one file in the current directory for each
|
|
file typed on the remote machine.
|
|
This program seems to be similar to the CU program provided by UNIX.
|
|
When I wrote the first version of this program, I didn't know about CU.
|
|
When I learned of CU, I had trouble getting it working, so I just decided
|
|
to use this program.
|
|
A feature of setting port characteristics with stty is that the port's
|
|
characteristics remain set after the program exits. This is inconvenient in
|
|
the case of the console, so this program tries to re-set the characteristics
|
|
before exiting.
|
|
*****************************************************************************/
|
|
#include <ctype.h>
|
|
#include <sgtty.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#define BOOLEAN char
|
|
#define CMPECHO 0777767 /* complement of ECHO in sgtty.h */
|
|
#define KEY "SD0:[PETE.TECO.TECOC]"
|
|
#define KEY_LEN 21
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
char buffer[100]; /* character buffer */
|
|
char chr; /* one character */
|
|
struct sgttyb cons_cb; /* console charactertistics block */
|
|
int cons_fd; /* console file descriptor */
|
|
int cons_flags_saved; /* saved value of cons_cb.sg_flags */
|
|
BOOLEAN cons_opened; /* console need to be closed? */
|
|
BOOLEAN cons_set; /* console characteristics changed? */
|
|
struct sgttyb modm_cb; /* modem characteristics block */
|
|
int modm_fd; /* modem file descriptor */
|
|
int modm_flags_saved; /* saved value of modm_cb.sg_flags */
|
|
char modm_ispeed_saved; /* saved value of modm_cb.sg_ispeed */
|
|
char modm_ospeed_saved; /* saved value of modm_cb.sg_ospeed */
|
|
BOOLEAN modm_opened; /* does the modem need to be closed? */
|
|
BOOLEAN modm_set; /* modem characteristics changed? */
|
|
int proc_id; /* process identification */
|
|
BOOLEAN trapping; /* trapping modem input to a file? */
|
|
FILE *splice_fp; /* splice file descriptor */
|
|
FILE *trap_fp; /* capture file descriptor */
|
|
reset_modm_port()
|
|
{
|
|
modm_cb.sg_ispeed = modm_ispeed_saved;
|
|
modm_cb.sg_ospeed = modm_ospeed_saved;
|
|
modm_cb.sg_flags = modm_flags_saved;
|
|
printf("Amodem: re-sttying the modem port\n");
|
|
if (stty(modm_fd, &modm_cb) != 0)
|
|
{
|
|
printf("Amodem: couldn't re-stty the modem port\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
close_modm_port()
|
|
{
|
|
printf("Amodem: closing the modem port\n");
|
|
if (close(modm_fd) == -1)
|
|
{
|
|
printf("Amodem: couldn't close the modem port\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
reset_cons_port()
|
|
{
|
|
cons_cb.sg_flags = cons_flags_saved;
|
|
printf("Amodem: re-sttying the console port\r\n");
|
|
if (stty(cons_fd, &cons_cb) != 0)
|
|
{
|
|
printf("Amodem: couldn't re-stty the console port\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
close_cons_port()
|
|
{
|
|
printf("Amodem: closing the console port\r\n");
|
|
if (close(cons_fd) == -1)
|
|
{
|
|
printf("Amodem: couldn't close the console port\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
cleanup_and_exit()
|
|
{
|
|
if (proc_id == 0)
|
|
{
|
|
if (trapping)
|
|
{
|
|
printf("Amodem: closing trap file\r\n");
|
|
if (fclose(trap_fp) == EOF)
|
|
printf("cleanup: unable to close trap file\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cons_set)
|
|
reset_cons_port();
|
|
if (cons_opened)
|
|
close_cons_port();
|
|
if (modm_set)
|
|
reset_modm_port();
|
|
if (modm_opened)
|
|
close_modm_port();
|
|
}
|
|
exit(1);
|
|
}
|
|
open_console() /* open console port */
|
|
{
|
|
cons_fd = open("/dev/tty",2);
|
|
if (cons_fd == -1)
|
|
{
|
|
printf ("Amodem: couldn't open the console port\n");
|
|
cleanup_and_exit();
|
|
}
|
|
cons_opened = TRUE;
|
|
if (gtty(cons_fd, &cons_cb) != 0)
|
|
{
|
|
printf("Amodem: couldn't gtty the console port\n");
|
|
cleanup_and_exit();
|
|
}
|
|
cons_flags_saved = cons_cb.sg_flags;
|
|
cons_cb.sg_flags = RAW;
|
|
if (stty(cons_fd, &cons_cb) != 0)
|
|
{
|
|
printf("Amodem: couldn't stty the console port\n");
|
|
cleanup_and_exit();
|
|
}
|
|
cons_set = TRUE;
|
|
}
|
|
open_modem() /* open modem port (serial port A, or /dev/tty01)*/
|
|
{
|
|
modm_fd = open("/dev/tty01",2);
|
|
if (modm_fd == -1)
|
|
{
|
|
printf ("Amodem: couldn't open the modem port\n");
|
|
cleanup_and_exit();
|
|
}
|
|
modm_opened = TRUE;
|
|
if (gtty(modm_fd, &modm_cb) != 0)
|
|
{
|
|
printf("Amodem: couldn't gtty the modem port\n");
|
|
cleanup_and_exit();
|
|
}
|
|
modm_ispeed_saved = modm_cb.sg_ispeed;
|
|
modm_ospeed_saved = modm_cb.sg_ospeed;
|
|
modm_cb.sg_ispeed = modm_cb.sg_ospeed = B1200;
|
|
modm_flags_saved = modm_cb.sg_flags;
|
|
modm_cb.sg_flags = RAW;
|
|
if (stty(modm_fd, &modm_cb) != 0)
|
|
{
|
|
printf("Amodem: couldn't stty the modem port\n");
|
|
cleanup_and_exit();
|
|
}
|
|
modm_set = TRUE;
|
|
}
|
|
cmd_char()
|
|
{
|
|
#define FBFSIZ 20
|
|
#define MAXLINE 132
|
|
int idx;
|
|
char FNamBuf[FBFSIZ];
|
|
char fline[MAXLINE];
|
|
char *line;
|
|
read(cons_fd, &chr, 1);
|
|
switch (chr){
|
|
case '.':
|
|
if (kill(proc_id, SIGTERM) != 0)
|
|
printf("cmd_char: kill failed\n");
|
|
cleanup_and_exit();
|
|
break;
|
|
case '\016':
|
|
break;
|
|
case 's':
|
|
case 'S':
|
|
printf("\r\nname of file to splice into output: ");
|
|
idx = 0;
|
|
while (chr != '\15')
|
|
{
|
|
read(cons_fd, &chr, 1);
|
|
write(cons_fd, &chr, 1);
|
|
if (chr == '\15')
|
|
{
|
|
FNamBuf[idx] = '\0';
|
|
write(cons_fd, "\n", 1);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
FNamBuf[idx] = chr;
|
|
if (idx++ > FBFSIZ)
|
|
{
|
|
printf("file name too long\r\n");
|
|
chr = '\15';
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (access(FNamBuf, 4) != 0)
|
|
{
|
|
printf("that file does not exist\r\n");
|
|
return;
|
|
}
|
|
if ((splice_fp = fopen(FNamBuf, "r")) == NULL)
|
|
{
|
|
printf("\tUnable to open %s\r\n", FNamBuf);
|
|
return;
|
|
}
|
|
line = &fline[0];
|
|
for (;;)
|
|
{
|
|
line = fgets(line, MAXLINE, splice_fp);
|
|
if (line == NULL)
|
|
break;
|
|
write(modm_fd, line, strlen(line) - 1);
|
|
write(modm_fd, "\r", 1);
|
|
}
|
|
if (fclose(splice_fp) == EOF)
|
|
{
|
|
printf("Unable to close %s\r\n", FNamBuf);
|
|
cleanup_and_exit();
|
|
}
|
|
break;
|
|
default:
|
|
printf("\r\n");
|
|
printf("\r\n");
|
|
printf("Control-N options are:");
|
|
printf("\r\n");
|
|
printf("\r\n");
|
|
printf("1.\t. to terminate this program");
|
|
printf("\r\n");
|
|
printf("2.\t^n to send a control-N");
|
|
printf("\r\n");
|
|
printf("3.\ts to splice a file into the output");
|
|
printf("\r\n");
|
|
printf("\r\n");
|
|
break;
|
|
}
|
|
}
|
|
tst_line() /* if line contains the key, trap to file */
|
|
{
|
|
char *index();
|
|
char *semi;
|
|
char *tmpptr;
|
|
if (strncmp(buffer, KEY, KEY_LEN) == 0)
|
|
{
|
|
if (trapping)
|
|
if (fclose(trap_fp) == EOF)
|
|
{
|
|
printf("Amodem: unable to close trap file\n");
|
|
cleanup_and_exit();
|
|
}
|
|
semi = index(buffer, ';');
|
|
*semi = '\0';
|
|
tmpptr = buffer;
|
|
while (*tmpptr != '\0')
|
|
{
|
|
if (isupper(*tmpptr))
|
|
*tmpptr = tolower(*tmpptr);
|
|
tmpptr++;
|
|
}
|
|
if ((trap_fp = fopen(&buffer[KEY_LEN], "w")) == NULL)
|
|
{
|
|
printf("Unable to create file AMODEM.OUT\r\n");
|
|
cleanup_and_exit();
|
|
}
|
|
trapping = TRUE;
|
|
}
|
|
}
|
|
parent_send() /* reads keyboard, sends to tty01 */
|
|
{
|
|
for (;;)
|
|
{
|
|
read(cons_fd, &chr, 1);
|
|
if (chr == '\016')
|
|
cmd_char();
|
|
write(modm_fd, &chr, 1);
|
|
}
|
|
}
|
|
child_receive() /* reads tty01, sends to terminal screen */
|
|
{
|
|
char *ptr;
|
|
ptr = &buffer[0];
|
|
for (;;)
|
|
{
|
|
read(modm_fd, &chr, 1);
|
|
write(cons_fd, &chr, 1);
|
|
if ((trapping) && (chr != '\r'))
|
|
putc(chr, trap_fp);
|
|
*ptr++ = chr;
|
|
if (chr == '\n')
|
|
{
|
|
tst_line();
|
|
ptr = &buffer[0];
|
|
}
|
|
}
|
|
}
|
|
main()
|
|
{
|
|
cons_opened = cons_set = modm_opened = modm_set = trapping = FALSE;
|
|
signal(SIGINT, cleanup_and_exit);
|
|
signal(SIGTERM, cleanup_and_exit);
|
|
open_console(),
|
|
open_modem();
|
|
printf("\r\n");
|
|
printf("\r\n");
|
|
printf("Communication established.");
|
|
printf("\r\n");
|
|
printf("\r\n");
|
|
proc_id = fork();
|
|
if (proc_id == -1)
|
|
{
|
|
printf("Amodem: fork failed\n");
|
|
cleanup_and_exit();
|
|
}
|
|
if (proc_id == 0)
|
|
child_receive();
|
|
else
|
|
parent_send();
|
|
}
|