xcomm 2.2, part 3 of 3 (second part of source)
Karl Kleinpaste
karl at triceratops.cis.ohio-state.edu
Wed Sep 28 07:25:32 AEST 1988
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# src
# This archive created: Tue Sep 27 17:13:53 1988
# By: Karl Kleinpaste (OSU)
export PATH; PATH=/bin:$PATH
if test ! -d 'src'
then
echo shar: creating directory "'src'"
mkdir 'src'
fi
echo shar: entering directory "'src'"
cd 'src'
echo shar: extracting "'xcport.c'" '(9678 characters)'
if test -f 'xcport.c'
then
echo shar: will not over-write existing file "'xcport.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xcport.c'
X/*
X Module: xcport.c XCOMM Modem Interface Routines
X
X This code is purely public domain!
X*/
X
X#include <stdio.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <termio.h>
X#include <string.h>
X#include <sys/types.h>
X#include <errno.h>
X
X#include "xcomm.h"
X
X/*
X The dial() routine uses these two defines.
X
X DIALSTR is a sprintf format string that assumes a HAYES-compatible
X modem.
X
X HAYSATT is the HAYES "attention" signal (used if DTR_DROPS_CARRIER
X is not set to 1).
X
X HAYSHUP is the HAYES "hangup" command (used if DTR_DROPS_CARRIER is not
X set to 1).
X
X MDELAY is the delay in the output because (on my modem) the command
X would be ignored if sent at full speed. Change for other setups.
X (This setting is for U.S. Robotics Password Modem).
X*/
X
X#define DIALSTR "\rATDT %s\r" /* format string for Hayes-type modem */
X#define HAYSATT "+++" /* Hayes "attention" signal */
X#define HAYSHUP "ATH\r" /* Hayes "hang up" command */
X#define MDELAY 20000 /* delay for output to modem itself */
X
X/* globals */
X
Xextern int tfp; /* TTY file pointer */
Xint bitmask = 0xFF; /* modem port i/o data mask */
Xint flowflag = 0; /* modem port i/o data mask */
X
Xstatic int mfd = -1; /* modem port file descriptor */
Xstatic struct termio pmode; /* modem device control string */
Xstatic char port[NMSIZE]; /* modem port device file string */
Xstatic int baudrate = B1200; /* baud rate */
X
Xint cpmode()
X{
X pmode.c_iflag |= IGNBRK;
X
X pmode.c_lflag = 0;
X#ifdef XCLUDE
X pmode.c_lflag |= XCLUDE;
X#endif
X pmode.c_oflag = 0; /* Transparent output */
X
X pmode.c_cflag = baudrate | CS8 | CREAD | CLOCAL;
X
X pmode.c_cc[VMIN] = 1; /* This many chars satisfies reads */
X pmode.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
X
X xc_setflow();
X}
X
Xint xc_setxon(mode)
X{
X cpmode();
X
X if (mode) {
X pmode.c_iflag |= IXON | IXOFF;
X pmode.c_iflag &= ~IXANY;
X } else
X pmode.c_iflag &= ~(IXON | IXOFF | IXANY);
X
X if(mfd != -1)
X ioctl(mfd, TCSETAW, &pmode);
X}
X
Xint xc_flowtoggle()
X{
X flowflag = 1 - flowflag;
X
X xc_setflow();
X}
X
Xxc_setflow()
X{
X if (flowflag) {
X pmode.c_iflag |= IXON | IXOFF;
X pmode.c_iflag &= ~IXANY;
X } else
X pmode.c_iflag &=~(IXON | IXOFF | IXANY);
X
X if (mfd != -1)
X ioctl(mfd, TCSETAW, &pmode);
X}
X
Xchar *mport(s) /* get/set port string */
Xchar *s;
X{
X if(s != NULL && mfd == -1)
X strcpy(port, s);
X return(port);
X}
X
X/* Get/set the baud rate of the modem port. If the port hasn't been opened yet,
X * just store in pmode for mopen() to use when it opens the port.
X */
Xint mbaud(s)
Xchar *s;
X{
X cpmode();
X
X if(s != NULL){
X /* this gives a more limited, realistic range than in sgtty.h */
X switch (atoi(s)) {
X case 300: baudrate = B300; break;
X case 1200: baudrate = B1200; break;
X case 2400: baudrate = B2400; break;
X case 9600: baudrate = B9600; break;
X default: return(-1);
X }
X pmode.c_cflag &= ~CBAUD;
X pmode.c_cflag |= baudrate;
X
X if(mfd != -1)
X ioctl(mfd, TCSETAW, &pmode);
X }
X
X switch(pmode.c_cflag & CBAUD){
X case B300: return(300);
X case B1200: return(1200);
X case B2400: return(2400);
X case B9600: return(9600);
X }
X
X fprintf(tfp,"Impossible error in baud rate.\n");
X return(0);
X}
X
X/*
X The following routine is used to hang up the modem. This is
X accomplished by setting the baud rate to 0. According to my
X documentation on termio, setting the baud rate to zero will
X result in DTR not being asserted. This hangs up some (most?)
X modems. If not, the second part of the routine sends the Hayes
X modem "escape" and then a hangup command.
X*/
X
Xvoid hangup()
X{
X if (mfd == -1)
X return;
X
X fprintf(tfp,"<< HANGUP >>\r\n");
X fflush(stdout);
X
X#if DTR_DROPS_CARRIER
X pmode.c_cflag &= ~CBAUD;
X pmode.c_cflag |= B0; /* set baud 0 (drop DTR) */
X ioctl(mfd, TCSETAW, &pmode);
X
X sleep(1); /* wait a minute */
X
X pmode.c_cflag &= ~CBAUD; /* reset baud rate */
X pmode.c_cflag |= baudrate;
X ioctl(mfd, TCSETAW, &pmode);
X#else /* use Hayes command */
X sleep(2); /* Allow for "escape guard time" */
X send_slowly(HAYSATT); /* Send modem escape command */
X
X sleep(3); /* More "escape guard time" */
X send_slowly(HAYSHUP); /* Send hangup command */
X#endif
X}
X
X/* Opens the modem port and configures it. If the port string is
X * already defined it will use that as the modem port; otherwise it
X * gets the environment variable MODEM. Returns 0 for success
X * or -1 on error.
X */
X
Xstatic int opened = 0;
X
Xint mopen()
X{
X char *p, *getenv();
X int oldflags;
X
X cpmode();
X
X if(port[0] == '\0'){
X if((p = getenv("MODEM")) == NULL)
X return(-1);
X strcpy(port, p);
X }
X
X if (lock_tty()) {
X fprintf(stderr, "Modem device is locked -- try later.\r\n");
X return -1;
X }
X
X /* Need O_NDELAY to get the file open before we have carrier */
X if((mfd = open(port, O_RDWR | O_NDELAY)) < 0) {
X perror("mopen()");
X unlock_tty();
X return -1;
X }
X
X /* Now, we must reset the O_NDELAY mode so that read() works correctly */
X if ( ((oldflags = fcntl(mfd, F_GETFL, 0)) == -1) ||
X (fcntl(mfd, F_SETFL, oldflags & ~O_NDELAY) == -1) ) {
X perror("mopen can not reset O_NDELAY");
X unlock_tty();
X return -1;
X }
X
X ioctl(mfd, TCFLSH, 2);
X ioctl(mfd, TCSETAW, &pmode);
X
X opened++;
X
X return(0);
X}
X
X#if !HAVE_DUP2 /* For those that do not have dup2()... */
Xint dup2(oldfd, newfd)
Xint oldfd, newfd;
X{
X if (fcntl(oldfd, F_GETFL, 0) == -1) /* Valid file descriptor? */
X return (-1); /* No, return an error. */
X close(newfd); /* Ensure newfd is closed */
X return (fcntl(oldfd, F_DUPFD, newfd)); /* Dup oldfd into newfd */
X}
X#endif /* !HAVE_DUP2 Thanks to Bill Allie CIS: 76703,2061 */
X
X/* Attach standard input and output to the modem port. This only gets called
X * after a fork by the child process; which then exec's a program that uses
X * standard i/o for some data transfer protocol. (To put this here is actually
X * a kludge, but I wanted to keep the modem-specific stuff in a black box.)
X */
Xmattach() /* attach standard i/o to port */
X{
X dup2(mfd, 0); /* close local stdin and connect to port */
X dup2(mfd, 1); /* close local stdout and connect to port */
X
X close(mfd); /* close the old port descriptor */
X}
X
Xint readbyte(seconds)
Xint seconds;
X{
X return trminp(mfd, seconds);
X}
X
X/*
X Read a byte using bitmask
X*/
X
Xread_mbyte(secs)
X{
X int c;
X
X return (c = readbyte(secs)) == -1 ? -1 : c & bitmask;
X}
X
X/* Output a byte to the modem port.
X * All data sent to the modem is output through this routine.
X */
Xsendbyte(ch)
Xint ch;
X{
X char c = ch & 0xff;
X
X write(mfd, &c, 1);
X}
X
Xsend_mbyte(ch)
X{
X sendbyte(ch & bitmask);
X}
X
X/* Dial a phone number, using proper format and delay.
X */
X
Xstatic char *last_nbr = NULL;
Xchar *strdup();
X
Xdial(s)
Xchar *s;
X{
X char buffer[WBSIZE];
X
X if (last_nbr)
X free(last_nbr);
X
X last_nbr = strdup(s);
X
X sprintf(buffer, DIALSTR, s);
X send_slowly(buffer);
X}
X
Xredial(last_nbr)
X char *last_nbr;
X{
X char *s;
X
X if (last_nbr == NULL) {
X fprintf(tfp,"REDIAL FAILURE\r\n");
X return 1;
X }
X
X s = strdup(last_nbr);
X dial(s);
X free(s);
X return 0;
X}
X
Xsend_slowly(s)
X char *s;
X{
X int i;
X
X/*
X This busy-waiting, normally a bad idea on a multi-tasking system,
X was used because sleep(1) is way too much of a delay.
X*/
X while(*s){
X send_mbyte(*s++);
X for(i = 0; i < MDELAY; i++)
X ;
X }
X}
X
X/*
X I have had requests to support the LCK..ttyxx files that CU and UUCP
X tend to support. I do not have any need for such code, and am not
X exactly sure how the code should work. I have therefore placed these
X two entry points for some enterprising coder to code so that the lock
X files may be created and destroyed.
X
X lock_tty() returns non-zero if the lock file exists (prevents XCOMM from
X running).
X
X unlock_tty() deletes the lock file.
X
X Simple, eh?
X*/
X
Xchar lckf[40] = "/usr/spool/locks/LCK..";
Xchar ltmp[40] = "/usr/spool/locks/LTMP.";
X
Xlock_tty()
X{
X int pid, lckpid, lfd;
X char pidstr[20];
X char lckpidstr[20];
X char *modemname;
X extern int errno;
X
X /*
X * Get our PID, and initialize the filename strings.
X */
X pid = getpid();
X sprintf(pidstr, "%d", pid);
X modemname = strrchr(port, '/');
X strcat(lckf, (modemname ? (modemname+1) : port));
X strcat(ltmp, pidstr);
X
X /*
X * Create the LTMP.<pid> file and scribble our PID in it.
X */
X unlink(ltmp);
X if ((lfd = creat(ltmp, 0444)) == -1) {
X fprintf(stderr, "Can't creat(2) LTMP?\r\n");
X return -1;
X }
X sprintf(pidstr, "%10d\n", pid);
X write(lfd, pidstr, 11);
X close(lfd);
X
X /*
X * Attempt to link directly - if it works, we're done.
X */
X relink:
X if (link(ltmp, lckf) == 0) {
X unlink(ltmp);
X return 0;
X }
X
X /*
X * Oh, bother, there's a LCK..* file already; we must
X * now expend effort to learn if it's stale or not.
X */
X if ((lfd = open(lckf, O_RDONLY)) != -1) {
X if (read(lfd, lckpidstr, 11) == 11) {
X lckpid = atol(lckpidstr);
X if (kill(lckpid, 0) == 0) {
X fprintf(stderr, "%s locked by process %d.\r\n", port, lckpid);
X unlink(ltmp);
X return -1;
X }
X }
X }
X
X /*
X * The LCK..* file was stale. Remove and retry.
X */
X if (unlink(lckf)) {
X fprintf(stderr, "Can't unlink(2) stale LCK?\r\n");
X unlink(ltmp);
X return -1;
X }
X goto relink;
X /*NOTREACHED*/
X}
X
Xunlock_tty()
X{
X unlink(lckf);
X}
SHAR_EOF
if test 9678 -ne "`wc -c < 'xcport.c'`"
then
echo shar: error transmitting "'xcport.c'" '(should have been 9678 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcscrpt.c'" '(7366 characters)'
if test -f 'xcscrpt.c'
then
echo shar: will not over-write existing file "'xcscrpt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xcscrpt.c'
X/*
X Program xcscrpt.c Script handler for xcomm
X Author larry gensch, ESQ December 4, 1987
X
X This code is released to the public domain
X*/
X
X#include <stdio.h>
X#include <time.h>
X#include <ctype.h>
X#include <signal.h>
X
X#include "xcomm.h"
X
X#define MAX_PATH 256
X#define MAX_LINE 128
X
Xextern char *getenv();
Xextern FILE *tfp;
X
Xstatic FILE *script_file, *cf;
Xstatic int waitfor_time = 0;
Xstatic int tty_flag = 1;
Xstatic int echo_flag = 0;
Xstatic int if_flag = 0;
Xstatic int waitflag = 0;
Xstatic int captflag = 0;
Xstatic jmp_buf here;
X
Xstatic void k_waitfor(), k_transmit(), k_pause(), k_exit(), k_quit();
Xstatic void k_if(), k_goto(), k_else(), k_endif(), k_redial();
Xstatic void k_dial(), s_set(), hangup(), k_echo(), k_tty(), k_capture();
X
X/* globals */
X
Xint linkflag = 0;
Xint scriptflag = 0;
X
Xstatic struct kw kw[] = {
X { "waitfor", k_waitfor },
X { "transmit", k_transmit },
X { "pause", k_pause },
X { "exit", k_exit },
X { "if", k_if },
X { "else", k_else },
X { "endif", k_endif },
X { "hangup", hangup },
X { "goto", k_goto },
X { "dial", k_dial },
X { "redial", k_redial },
X { "quit", k_quit },
X { "set", s_set },
X { "echo", k_echo },
X { "capture", k_capture },
X { "tty", k_tty },
X { NULL, NULL }};
X
Xstatic void newsigint();
X
Xdo_script(file)
X char *file;
X{
X int quiet = 0;
X
X if (open_script(file)) {
X fprintf(tfp, "Cannot find script file %s\r\n", file);
X return;
X }
X
X if (linkflag == 2) {
X quiet = 1;
X linkflag = 0;
X }
X
X if (!quiet)
X fprintf(tfp, "<<< RUNNING SCRIPT >>>\r\n");
X
X if_flag = 0;
X echo_flag = 0;
X captflag = 0;
X tty_flag = 1;
X scriptflag = 1;
X
X if (setjmp(here) == 0) {
X signal(SIGINT, newsigint);
X intdel(1);
X
X for (eof_flag = 0; !eof_flag; )
X get_line();
X }
X
X fclose(script_file);
X if (captflag)
X fclose(cf);
X
X if (!quiet)
X fprintf(tfp, "<< SCRIPT COMPLETE >>\r\n");
X
X linkflag = 0;
X scriptflag = 0;
X
X signal(SIGINT, SIG_IGN);
X intdel(0);
X
X return;
X}
X
Xstatic void newsigint()
X{
X signal(SIGINT, SIG_IGN);
X
X eof_flag = 1;
X fprintf(tfp, "\r\nUser Abort...\r\n");
X longjmp(here);
X}
X
Xstatic char path[MAX_PATH];
X
Xstatic open_script(file)
X char *file;
X{
X char *home;
X
X eof_flag = 0;
X
X if (script_file = fopen(file, "r"))
X return 0;
X
X if ((home = getenv("HOME")) == NULL)
X return 1;
X
X sprintf(path, "%s/%s", home, file);
X
X if (script_file = fopen(path, "r"))
X return 0;
X
X return 1;
X}
X
Xstatic char wf[MAX_LINE];
X
Xstatic get_line()
X{
X int i;
X
X getline(script_file);
X
X if (eof_flag)
X return;
X
X getword();
X lc_word(word);
X
X if (echo_flag) {
X if (strcmp(word, "transmit"))
X fprintf(tfp, "%s\r\n", line);
X else
X fprintf(tfp, "TRANSMIT...\r\n");
X }
X
X if (word[0] == '\0') /* Ignore blank lines */
X return;
X if (word[0] == '#') /* Ignore comments */
X return;
X
X if (word[strlen(word) - 1] == ':') /* Ignore labels */
X return;
X
X if (if_flag == -1) {
X if (strcmp(word, "else") && strcmp(word, "endif"))
X return;
X }
X
X for (i = 0; kw[i].keyword != NULL; i++)
X if (strcmp(kw[i].keyword, word) == 0) {
X (*kw[i].rtn)();
X return;
X }
X
X fprintf(tfp, "UNDEFINED COMMAND: \"%s\"\r\n", word);
X eof_flag = 1;
X return;
X}
X
Xstatic void k_waitfor()
X{
X long t;
X int c;
X char *ptr = wf;
X
X quote_flag = 1;
X getword();
X quote_flag = 0;
X if (eof_flag)
X return;
X
X if (word[0] == '\0') {
X fprintf(tfp, "No argument to WAITFOR command\r\n");
X eof_flag = 1;
X return;
X }
X
X strcpy(wf, word);
X lc_word(wf);
X
X getword();
X if (eof_flag)
X return;
X
X if (word[0])
X waitfor_time = atoi(word);
X else
X waitfor_time = 30;
X
X t = time(NULL) + waitfor_time;
X
X while (t != time(NULL) && !eof_flag) {
X if ((c = read_mbyte(1)) == -1)
X continue;
X
X if (cismode && c == ENQ) {
X fprintf(tfp,"B transfer in middle of script\r\n");
X cismode = 1;
X B_Transfer();
X
X t = time(NULL) + waitfor_time;
X
X if ((c = read_mbyte(1)) == -1)
X continue;
X }
X
X if (tty_flag)
X fputc(c, tfp);
X
X if (captflag)
X fputc(c, cf);
X
X if (tolower(c) != *ptr) {
X ptr = wf;
X continue;
X }
X
X if (*++ptr == '\0') {
X waitflag = 1;
X return;
X }
X }
X
X waitflag = 0;
X}
X
Xstatic void k_transmit()
X{
X char *ptr;
X
X quote_flag = 1;
X getword();
X quote_flag = 0;
X if (eof_flag)
X return;
X
X if (word[0] == '\0') {
X fprintf(tfp, "No argument to TRANSMIT command\r\n");
X eof_flag = 1;
X return;
X }
X
X send_slowly(word);
X}
X
Xstatic void k_pause()
X{
X int pause_time;
X
X getword();
X if (eof_flag)
X return;
X
X if (word[0] == '\0')
X pause_time = 5;
X else
X pause_time = atoi(word);
X
X sleep(pause_time);
X}
X
Xstatic void k_quit()
X{
X do_exit(0); /* Terminate XCOMM */
X}
X
Xstatic void k_exit()
X{
X eof_flag = 1;
X}
X
Xstatic char label[WBSIZE];
X
Xstatic void k_goto()
X{
X int found = 0, i;
X
X getword();
X if (word[0] == '\0') {
X fprintf(tfp, "No argument for GOTO: %s\r\n", line);
X eof_flag++;
X return;
X }
X
X strcpy(label, word);
X lc_word(label);
X
X rewind(script_file);
X while (!found) {
X getline(script_file);
X if (eof_flag)
X break;
X
X getword();
X if (word[0] == '\0' || word[0] == '#')
X continue;
X
X if (word[i = (strlen(word)-1)] != ':')
X continue;
X
X word[i] = '\0';
X
X lc_word(word);
X found = (strcmp(word, label) == 0);
X }
X
X if (eof_flag) {
X fprintf(tfp, "Label %s not found\r\n", label);
X eof_flag++;
X return;
X }
X
X if_flag = 0; /* reset IF flag */
X}
X
Xstatic if_negate = 0;
X
Xstatic void k_if()
X{
X char *ptr;
X
X if (if_flag) {
X fprintf(tfp, "Nested IF statements not allowed\r\n");
X eof_flag++;
X return;
X }
X
X if_negate = 0;
X getword();
X if (word[0] == '\0') {
X fprintf(tfp, "No condition on IF statement\r\n");
X eof_flag++;
X return;
X }
X
X lc_word(word);
X if (strcmp(word, "not") == 0) {
X if_negate = 1;
X getword();
X if (word[0] == '\0') {
X fprintf(tfp, "No condition on IF statement\r\n");
X eof_flag++;
X return;
X }
X }
X
X if (word[0] == '!') {
X if_negate = 1;
X ptr = word + 1;
X } else
X ptr = word;
X
X if (strcmp(ptr, "waitfor") == 0) {
X if_flag = if_test(waitflag);
X return;
X }
X
X if (strcmp(ptr, "linked") == 0) {
X if_flag = if_test(linkflag);
X return;
X }
X
X fprintf(tfp, "Undefined IF condition %s\r\n", ptr);
X eof_flag++;
X return;
X}
X
Xstatic if_test(cond)
X int cond;
X{
X if (if_negate)
X cond = !cond;
X
X if (cond)
X return 1;
X else
X return -1;
X}
X
Xstatic void k_else()
X{
X if (!if_flag) {
X fprintf(tfp, "ELSE not within IF\r\n");
X eof_flag++;
X return;
X }
X
X if_flag = -if_flag;
X}
X
Xstatic void k_endif()
X{
X if (!if_flag) {
X fprintf(tfp, "ENDIF not wihtin IF\r\n");
X eof_flag++;
X return;
X }
X
X if_flag = 0;
X}
X
Xstatic void k_dial()
X{
X getword();
X
X if (word[0] == '\0') {
X fprintf(tfp, "DIAL command must have an argument\r\n");
X eof_flag++;
X return;
X }
X
X dial(word);
X}
X
Xstatic void k_redial()
X{
X if (redial()) {
X eof_flag++;
X return;
X }
X}
X
Xstatic void k_echo()
X{
X set_onoff(&echo_flag);
X return;
X}
X
Xstatic void k_capture()
X{
X int val = captflag;
X
X set_onoff(&captflag);
X if (eof_flag)
X return;
X
X if (val == captflag)
X return;
X
X if (captflag == 0)
X fclose(cf);
X else {
X if ((cf = fopen(captfile, "a")) == NULL) {
X fprintf(tfp, "Cannot open capture file %s\r\n");
X eof_flag++;
X return;
X }
X }
X}
X
Xstatic void k_tty()
X{
X set_onoff(&tty_flag);
X return;
X}
X
SHAR_EOF
if test 7366 -ne "`wc -c < 'xcscrpt.c'`"
then
echo shar: error transmitting "'xcscrpt.c'" '(should have been 7366 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcsubs.c'" '(4386 characters)'
if test -f 'xcsubs.c'
then
echo shar: will not over-write existing file "'xcsubs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xcsubs.c'
X/*
X Module: xcsubs.c XCOMM Subroutines
X
X Revisions:
X
X 2.2 lg Now uses /dev/tty instead of stdin/stdout
X 2.2 lg Added command parser
X*/
X
X#include <stdio.h>
X#include <ctype.h>
X#include <signal.h>
X#include <termio.h>
X
X#include "xcomm.h"
X
Xextern struct termio newmode, sigmode;
Xextern FILE *tfp; /* Local terminal */
Xextern int tfd; /* Local terminal */
X
Xchar line[WBSIZE]; /* Input line */
Xchar word[WBSIZE]; /* Parsed word */
Xchar *wptr, *lptr; /* Word and line pointers */
Xint quote_flag = 0; /* Indicates special processing during parse */
Xint eof_flag = 0; /* Indicates EOF during getline() processing */
X
Xsendstr(p) /* send a string to the port */
Xregister char *p;
X{
X while(*p)
X send_mbyte(*p++);
X}
X
X/* Do the fork call, packaging the error return so that the caller
X * need not have code for it.
X */
X
Xforkem()
X{
X int i;
X
X if((i = fork()) < 0){
X fprintf(tfp,"XCOMM: Fork failed");
X longjmp(erret, 1);
X }
X return(i);
X}
X
X
X/* Convert uppercase characters to lowercase, (without
X * mangling non-uppercase characters), in a portable manner.
X */
Xmklow(c)
Xint c;
X{
X if(isupper(c))
X return(tolower(c));
X return(c);
X}
X
X/* This is an string input routine to be used
X * when the raw terminal mode is in effect.
X */
Xgetsome(s)
Xchar *s;
X{
X int c, i;
X
X if (s == line) {
X lptr = line;
X memset(line, 0, WBSIZE);
X }
X
X i = 0;
X while((c = coninp()) != '\r' && c != '\n') {
X if(c == '\b'){
X if(i > 0){
X i--;
X fprintf(tfp,"\b \b");
X } else
X putc(7, tfp);
X continue;
X }
X s[i++] = c;
X putc(c, tfp);
X }
X s[i] = '\0';
X putc(' ', tfp);
X}
X
X/*
X Erase current line without moving downwards
X*/
X
Xerasln()
X{
X int i;
X
X putc('\r', tfp);
X for(i = 0; i < 79; i++)
X putc(' ', tfp);
X putc('\r', tfp);
X}
X
X/*
X Throw away all input characters until no more are sent.
X*/
X
Xpurge()
X{
X while(readbyte(1) != -1)
X ;
X}
X
X/*
X Parse the "line" array for a word
X*/
X
Xgetword()
X{
X char *ptr = word;
X char quote = '\0';
X int bflag = 0, qflag = 0;
X int c;
X
X *ptr = '\0';
X if (eof_flag || *lptr == '\0')
X return;
X
X while (isspace(*lptr))
X lptr++;
X
X wptr = lptr;
X
X if (*lptr == '\0')
X return;
X
X if (*lptr == '\'' || *lptr == '\"')
X quote = *lptr++;
X else
X quote = '\0';
X
X for (; *lptr != '\0'; lptr++) {
X if (quote) {
X if (*lptr == '\0') {
X word[0] = '\0';
X fprintf(tfp, "Unmatched quote: %s\r\n", line);
X eof_flag = 1;
X return;
X }
X if (*lptr == quote)
X break;
X } else if (!qflag && isspace(*lptr))
X break;
X
X if (bflag)
X *ptr++ = *lptr & 0x1f;
X else if (qflag)
X *ptr++ = *lptr;
X else if (quote_flag && *lptr == '^')
X bflag = 1;
X else if (quote_flag && *lptr == '\\')
X qflag = 1;
X else
X *ptr++ = *lptr;
X }
X
X lptr++;
X *ptr = '\0';
X}
X
X/*
X Make the specified word all lower case
X*/
X
Xlc_word(ptr)
X char *ptr;
X{
X while (*ptr) {
X *ptr = mklow(*ptr);
X ptr++;
X }
X}
X
X/*
X Input a line from the specified file
X*/
X
Xgetline(fp)
X FILE *fp;
X{
X int l;
X
X memset(line, 0, WBSIZE);
X
X if ((fgets((lptr=line), WBSIZE, fp)) == NULL) {
X eof_flag = 1;
X line[0] = '\0';
X }
X
X l = strlen(line); /* Purge newline if found */
X if (l--) {
X if (line[l] == '\n')
X line[l] = '\0';
X }
X}
X
X/*
X trminp() is used as a single-character terminal input routine
X*/
X
Xstatic alrm() {} /* do nothing */
X
Xint trminp(fd, seconds)
X int fd, seconds;
X{
X static char rxbuf[BUFSIZ], *p; /* BUFSIZ is defined in stdio.h */
X static int count = 0;
X
X if(count > 0){
X count--;
X return(*p++ & 0xff);
X }
X if(seconds > 0){
X signal(SIGALRM, alrm);
X alarm((unsigned)seconds);
X }
X if((count = read(fd, p = rxbuf, BUFSIZ)) < 1)
X return(-1);
X if(seconds > 0)
X alarm(0);
X count--;
X return(*p++ & 0xff);
X}
X
X/*
X coninp() gets a single character from the local terminal
X*/
X
Xconinp()
X{
X int c;
X
X fflush(tfp);
X
X while ((c = trminp(tfd, 0)) == -1)
X ;
X
X return c;
X}
X
Xintdel(flag)
X{
X if (flag)
X ioctl(tfd, TCSETAW, &sigmode);
X else
X ioctl(tfd, TCSETAW, &newmode);
X}
X
X#if !HAVE_STRDUP
Xchar *
Xstrdup(s)
Xchar *s;
X{
X extern char *calloc(), *strcpy();
X char *r = calloc(1, strlen(s)+1);
X
X return(strcpy(r, s));
X}
X#endif /* !HAVE_STRDUP */
SHAR_EOF
if test 4386 -ne "`wc -c < 'xcsubs.c'`"
then
echo shar: error transmitting "'xcsubs.c'" '(should have been 4386 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcterm.c'" '(8607 characters)'
if test -f 'xcterm.c'
then
echo shar: will not over-write existing file "'xcterm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xcterm.c'
X/* xcterm.c XCOMM terminal mode
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include "xcomm.h"
X
X/* globals */
Xchar captfile[NMSIZE] = CAPTFILE; /* capture file's name */
Xchar phonefile[NMSIZE] = PHFILE; /* phone number file's name */
X
Xint cismode = CIS_INIT; /* Respond to CIS "ENQ" */
Xextern FILE *tfp; /* Local terminal pointer */
X
X/* locals */
X
Xstatic FILE *cfp; /* capture file pointer */
Xstatic int ctop; /* index top of capture buffer */
Xstatic int child_pid = 0; /* ID of child process */
Xstatic int capture = FALSE; /* are we capturing or not ? */
Xstatic char *cbuffp = NULL; /* capture buffer pointer */
Xstatic jmp_buf rtm;
X
X/* forward declarations */
Xvoid toggle(), cleanup(), newbmask(), cisbmode();
X
Xstatic int script_flag = 0;
Xstatic char *script_file;
Xstatic char script_buf[100];
X
Xterminal()
X{
X int c;
X
Xreterm:
X setjmp(rtm);
X
X if (cismode > 1)
X return;
X
X script_flag = 0; /* reset scripting flag */
X
X fprintf(tfp,"Entering Terminal Mode\r\n");
X /* split into read and write processes */
X if((child_pid = forkem()) == 0){
X /* child, read proc: read from port and write to tty */
X cfp = NULL;
X signal(SIGALRM, toggle);
X signal(SIGTERM, cleanup);
X signal(SIGUSR1, newbmask);
X while(1){
X while((c = read_mbyte(0)) == -1)
X ;
X if (cismode && c == ENQ) {
X cismode = 2;
X cleanup();
X }
X fputc(c, tfp);
X fflush(tfp);
X if(capture && c != '\r')
X fputc(c, cfp);
X }
X /*NOTREACHED*/
X }
X /* parent, write proc: read from tty and write to port */
X signal(SIGCLD, cisbmode);
X
X do {
X switch(c = getconchr()) {
X case TOGCHAR: /* signal child to toggle buffer */
X kill(child_pid, SIGALRM);
X break;
X
X case DIVCHAR: /* divert a file through modem port */
X divert();
X break;
X
X case SCRPCHR: /* execute a script file */
X if (get_script())
X break;
X script_flag = 1;
X goto fillicide;
X
X case PSELECT: /* select and dial a phone number */
X pselect();
X if (!script_flag)
X break;
X
X case ENDCHAR: /* signal child to cleanup and exit */
Xfillicide:
X c = ENDCHAR;
X signal(SIGCLD, SIG_IGN);
X kill(child_pid, SIGTERM);
X break;
X
X case HUPCHAR: /* Hangup */
X hangup();
X break;
X
X case '\n': /* See if NL translation in effect */
X if (nlmode)
X c = '\r';
X
X default: /* just send the character to the port */
X send_mbyte(c);
X break;
X }
X } while(c != ENDCHAR);
X
X while(wait((int *) 0) >= 0) /* wait for the read process to die */
X ;
X
X if (script_flag) {
X do_script(script_file);
X goto reterm;
X }
X
X fprintf(tfp,"\r\nLeaving Terminal Mode\r\n");
X}
X
Xstatic void cisbmode()
X{
X cismode = 2;
X signal(SIGCLD, SIG_IGN);
X
X longjmp(rtm);
X}
X
X/* The next three functions are only run by the port read process (child).
X * They handle the capture buffer.
X *
X * toggle capture status
X */
Xstatic void toggle()
X{
X char *malloc();
X
X if(capture) {
X fclose(cfp);
X capture = FALSE;
X fprintf(tfp, "\r\n<<CAPTURE BUFF CLOSED>>\r\n");
X } else {
X if ((cfp = fopen(captfile, "a")) == NULL) {
X fprintf(tfp,"\r\n<<CAN'T OPEN CAPTURE FILE>\r\n");
X } else {
X capture = TRUE;
X fprintf(tfp,"\r\n<<CAPTURE BUFF OPEN>>\r\n");
X }
X }
X
X signal(SIGALRM, toggle); /* set signal for next toggle */
X}
X
X/* cleanup, flush and exit
X */
Xstatic void cleanup()
X{
X if(capture){
X fclose(cfp);
X fprintf(tfp,"\r\n<<CAPTURE BUFF SAVED>>\r\n");
X }
X
X if (cismode == 2)
X fprintf(tfp,"\r\n<<FILE TRANSFER REQUEST>>\r\n");
X
X fflush(tfp);
X exit(0);
X}
X
Xstatic void newbmask()
X{
X if (bitmask == 0xff)
X bitmask = 0x7f;
X else
X bitmask = 0xff;
X
X if (child_pid)
X kill(child_pid, SIGUSR1);
X else
X fprintf(tfp,"<<SET TO %d BIT MASK>>\r\n", bitmask == 0xff ? 8 : 7);
X}
X
Xstatic FILE *openfile(name)
X char *name;
X{
X FILE *fp;
X char *home, fullname[NMSIZE];
X
X if (fp = fopen(name, "r"))
X return fp;
X
X if (home = (char *) getenv("HOME")) {
X sprintf(fullname, "%s/%s", home, name);
X return fopen(fullname, "r");
X } else
X return NULL;
X}
X
X/*
X Select a script file. If the file exists, execute it, otherwise
X exit with a non-zero return.
X*/
X
Xget_script()
X{
X fprintf(tfp,"\r\nEnter script file: ");
X getsome(script_buf);
X if (script_buf[0] == '\0') {
X fprintf(tfp,"\r\n<<ABORTED>>\r\n");
X return 1;
X }
X if (access(script_buf, 04)) {
X fprintf(tfp," <<- NOT FOUND\r\n");
X return 1;
X }
X fprintf(tfp, "\r\n");
X linkflag = FALSE;
X script_file = script_buf;
X return 0;
X}
X
X/* pselect() and divert() are used by the port write process (parent).
X * They produce other sources of input for the port than the keayboard.
X *
X * Select phone number and dial it. (Hayes - type modem)
X * Phone number is stored in a file, one number per line, with the phone
X * number first, followed by some space and then any comments.
X * VERSION 2.1 - If line contains BAUD=nnnn, the baud rate will be changed
X * to nnn. If lines contains BITS=7 or BITS=8, the bitmask
X * will be changed to the specified value.
X * VERSION 2.2 - If line contains SCRIPT=nnnnn, the designated script file
X * will be started.
X */
Xpselect()
X{
X FILE *fp;
X char buffer[WBSIZE + 1];
X int c, i;
X
X if ((fp = openfile(phonefile)) == NULL) {
X fprintf(tfp,"Phonelist file '%s' not in current or home directory\r\n",
X phonefile);
X return;
X }
X
X fprintf(tfp,"Type D-Dial X-Exit Any other key for next line.\r\n");
X do {
X if(fgets(buffer, WBSIZE, fp) == NULL){
X rewind(fp);
X if(fgets(buffer, WBSIZE, fp) == NULL){
X fprintf(tfp,"Empty phonelist file!\r\n");
X return;
X }
X }
X erasln();
X for(i = 0; i < WBSIZE && (c = buffer[i]) != '\n'; i++)
X fputc(c, tfp);
X fputc('\r', tfp);
X } while((c = mklow(getc(tfp))) != 'd' && c != 'x');
X erasln();
X fclose(fp);
X if(c == 'd')
X dialbuf(buffer);
X}
X
X#if !HAVE_STRSTR
X/*
X Find first occurance of str2 in str1 and return a pointer to it
X*/
X
Xchar *strstr(str1, str2)
X char *str1, *str2;
X{
X char *Sptr, *Tptr;
X int len = strlen(str1) - strlen(str2) + 1;
X
X if (*str2)
X for (; len > 0; len--, str1++) {
X if (*str1 != *str2)
X continue;
X
X for (Sptr = str1, Tptr = str2; *Tptr != '\0'; Sptr++, Tptr++)
X if (*Sptr != *Tptr)
X break;
X
X if (*Tptr == '\0')
X return str1;
X }
X
X return NULL;
X}
X#endif
X
Xdialbuf(buf)
X char *buf;
X{
X char *nbr, *ptr, *ptr1, c;
X
X if (ptr = strstr(buf, "BAUD=")) {
X ptr += 5;
X if (mbaud(ptr) == -1)
X fprintf(tfp,"Invalid BAUD= value\r\n");
X else
X fprintf(tfp,"<<SET TO %d BAUD>>\r\n", mbaud(NULL));
X }
X
X if (ptr = strstr(buf, "BITS=")) {
X ptr += 5;
X switch (*ptr) {
X case '7':
X if (bitmask == 0xff)
X newbmask();
X break;
X case '8':
X if (bitmask == 0x7f)
X newbmask();
X break;
X default:
X fprintf(tfp,"Invalid BITS= value\r\n");
X }
X }
X
X while (isspace(*buf) && *buf)
X buf++;
X
X if (!(*buf))
X return;
X
X for (nbr = buf; !isspace(*buf) && *buf; buf++)
X ;
X
X c = *buf;
X *buf = '\0';
X dial (nbr);
X
X *buf = c;
X if (ptr = strstr(buf, "SCRIPT=")) {
X ptr += 7;
X ptr1 = ptr;
X while (!isspace(*ptr1) && *ptr1 != '\0')
X ptr1++;
X *ptr1 = '\0';
X script_file = ptr;
X script_flag = 1;
X linkflag = TRUE;
X }
X}
X
X/* Divert file into input stream, with optional delay after each newline.
X */
Xdivert()
X{
X FILE *fp;
X char buffer[NMSIZE];
X int c, i;
X
X fprintf(tfp,"\r\nFile? ");
X getsome(buffer);
X if((fp = fopen(buffer, "r")) == NULL){
X fprintf(tfp,"\r\nCan't open %s for input\r\n", buffer);
X return;
X }
X fprintf(tfp,"\r\nThe default delay of %d can be ", DRIBBLE);
X fprintf(tfp,"changed by typing the new delay after the 'y'\r\n");
X fprintf(tfp,"Delay after every newline (y/n)? ");
X
X getsome(buffer);
X fprintf(tfp,"\r\n");
X
X i = 0;
X if(mklow(buffer[0]) == 'y' && (i = atoi(buffer + 1)) == 0)
X i = DRIBBLE;
X while((c = getc(fp)) != EOF)
X if(c != '\n')
X send_mbyte(c);
X else {
X send_mbyte('\r');
X if(i)
X sleep((unsigned) i);
X }
X fclose(fp);
X}
X
Xgetconchr()
X{
X int c, tc;
X
X if ((c = coninp()) == ESCAPE_CHR) {
X switch (c = ((tc = coninp()) & 0x1f) + 128) {
X case ENDCHAR:
X case TOGCHAR:
X case DIVCHAR:
X case PSELECT:
X case HUPCHAR:
X case SCRPCHR:
X break;
X
X default:
X c = tc;
X }
X }
X return c;
X}
X
SHAR_EOF
if test 8607 -ne "`wc -c < 'xcterm.c'`"
then
echo shar: error transmitting "'xcterm.c'" '(should have been 8607 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcxmdm.c'" '(12344 characters)'
if test -f 'xcxmdm.c'
then
echo shar: will not over-write existing file "'xcxmdm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'xcxmdm.c'
X/*
X Module: xcxmdm.c XMODEM Protocol Module
X
X This source code is purely public domain
X*/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <signal.h>
X
X#include "xcomm.h"
X
X#define SOH 001 /* ^A */
X#define EOT 004 /* ^D */
X#define ACK 006 /* ^F */
X#define NAK 025 /* ^U */
X#define CAN 030 /* ^X */
X#define CPMEOF 032 /* ^Z */
X#define WANTCRC 'C'
X#define OK 0
X#define TIMEOUT -1 /* -1 is returned by readbyte() upon timeout */
X#define ERROR -2
X#define WCEOT -3
X#define RETRYMAX 10
X#define SECSIZ 128
X
X/* globals */
Xint
X badline = FALSE, /* bad telephone line? */
X crcheck = TRUE; /* CRC check enabled? */
X
Xextern FILE *tfp; /* TTY File pointer */
X
X/* locals */
Xstatic FILE
X *xfp; /* buffered file pointer */
Xstatic int
X firstsec, /* first sector of file or not? */
X textmode = TRUE; /* Text translations enabled? */
Xstatic char wcbuff[SECSIZ]; /* Ward Christensen sector buffer */
Xstatic unsigned short updcrc();
X
Xstatic void newsigint(); /* Our SIGINT handler */
Xstatic int save_crc; /* Saved crcheck value */
Xstatic jmp_buf our_env;
X
Xxreceive(c)
X int c;
X{
X if (word[0] == '\0') {
X fprintf(tfp,"No file name specified for XMODEM receive\r\n");
X return;
X }
X
X xc_setxon(0); /* turn off XON/XOFF */
X save_crc = crcheck;
X signal(SIGINT, newsigint); /* Install our handler */
X
X if (!setmode(c)) {
X if (setjmp (our_env) == 0) {
X crcheck = 0xff;
X do_xreceive(word);
X }
X }
X
X signal(SIGINT, SIG_IGN); /* Reinstall old handler */
X crcheck = save_crc;
X restmode();
X}
X
Xxsend(c)
X int c;
X{
X if (word[0] == '\0') {
X fprintf(tfp,"No file name specified for XMODEM send\r\n");
X return;
X }
X
X xc_setxon(0); /* turn off XON/XOFF */
X save_crc = crcheck;
X signal(SIGINT, newsigint); /* Install our handler */
X
X if (!setmode(c)) {
X if (setjmp (our_env) == 0) {
X crcheck = 0xff;
X do_xsend(word);
X }
X }
X
X signal(SIGINT, SIG_IGN); /* Reinstall old handler */
X crcheck = save_crc;
X restmode();
X}
X
Xstatic void newsigint()
X{
X fprintf(tfp,"\r\nUser abort\r\n");
X signal(SIGINT, SIG_IGN); /* Ignore subsequent DEL's */
X canit(); /* Abort the transmission */
X longjmp(our_env, 0);
X}
X
Xstatic restmode()
X{
X intdel(0);
X
X xc_setflow(); /* restore XON/XOFF */
X}
X
Xstatic do_xreceive(p)
X char *p;
X{
X long bytes, ftime;
X short fmode;
X char *ctime();
X
X fprintf(tfp,"XCOMM: Ready to receive single file %s\r\n", p);
X if (wcrx(p) == ERROR)
X canit();
X return;
X}
X
Xdo_xsend(p)
X char *p;
X{
X if (wctx(p) == ERROR) {
X fprintf(tfp,"Error transmitting file %s\r\n", p);
X return;
X }
X}
X
X/*
X Receive a file using XMODEM protocol
X*/
X
Xstatic wcrx(name)
Xchar *name;
X{
X register int sectnum, sectcurr, sendchar, eofseen;
X
X if (!mungmode && !access(name, 0)) {
X canit();
X fprintf(tfp,"Receive of %s aborted due to pre-exsistence.\r\n");
X return(ERROR);
X }
X
X if ((xfp = fopen(name, "w")) == NULL) {
X canit();
X fprintf(tfp,"Receive of %s aborted due to inabilty to open.\r\n");
X return(ERROR);
X }
X firstsec = TRUE;
X eofseen = FALSE;
X sectnum = 0;
X sendchar = crcheck ? WANTCRC : NAK;
X fprintf(tfp,"Sync...\r\n");
X
X while(TRUE) {
X if (badline)
X purge();
X sendbyte(sendchar);
X sectcurr = wcgetsec(6);
X if (sectcurr == ((sectnum + 1) & 0xff)) {
X sectnum++;
X putsec();
X fprintf(tfp,"Received sector #%d \r", sectnum);
X fflush(tfp);
X
X sendchar = ACK;
X continue;
X }
X
X if (sectcurr == (sectnum & 0xff)) {
X fprintf(tfp,"Received duplicate sector #%d \r", sectnum);
X fflush(tfp);
X sendchar = ACK;
X continue;
X }
X
X fprintf(tfp, "\r\n");
X fclose(xfp);
X
X if (sectcurr == WCEOT) {
X fprintf(tfp,"File recived OK\r\n");
X sendbyte(ACK);
X return(OK);
X }
X
X if (sectcurr == ERROR)
X return(ERROR);
X
X fprintf(tfp,"Sync error ... expected %d(%d), got %d\r\n",
X (sectnum + 1) & 0xff, sectnum, sectcurr);
X return(ERROR);
X }
X}
X
X/*
X Transmit a file using XMODEM protocol
X*/
X
Xstatic wctx(name)
Xchar *name;
X{
X register int sectnum, eoflg, c, attempts;
X
X if ((xfp = fopen(name, "r")) == NULL) {
X fprintf(tfp,"Can't open file %s for reading.\r\n", name);
X return(ERROR);
X }
X firstsec = TRUE;
X attempts = 0;
X fprintf(tfp,"Sync...\r\n");
X
X while((c = readbyte(30)) != NAK && c != WANTCRC && c != CAN)
X if (c == TIMEOUT && ++attempts > RETRYMAX) {
X fprintf(tfp,"Receiver not responding.\r\n");
X fclose(xfp);
X return(ERROR);
X }
X if (c == CAN) {
X fprintf(tfp,"Receiver CANcelled.\r\n");
X fclose(xfp);
X return(ERROR);
X }
X crcheck = (c == WANTCRC);
X fprintf(tfp,"%s error checking requested.\r\n",
X crcheck ? "CRC check" : "Checksum");
X sectnum = 1;
X
X do {
X eoflg = getsec();
X fprintf(tfp,"Transmitting sector #%d\r", sectnum);
X fflush(tfp);
X
X if (wcputsec(sectnum) == ERROR) {
X fclose(xfp);
X return(ERROR);
X }
X sectnum++;
X } while(eoflg);
X
X fprintf(tfp, "\r\n");
X fclose(xfp);
X attempts = 0;
X sendbyte(EOT);
X while(readbyte(5) != ACK && attempts++ < RETRYMAX)
X sendbyte(EOT);
X if (attempts >= RETRYMAX) {
X fprintf(tfp,"Receiver not responding to completion.\r\n");
X return(ERROR);
X }
X
X fprintf(tfp,"Transmission complete.\r\n");
X return(OK);
X}
X
X/*
X wcgetsec() inputs an XMODEM "sector".
X This routine returns the sector number encountered, or ERROR if a valid
X sector is not received or CAN received; or WCEOT if EOT sector.
X
X Maxtime is the timeout for the first character, set to 6 seconds for
X retries. No ACK is sent if the sector is received ok. This must be
X done by the caller when it is ready to receive the next sector.
X*/
X
Xstatic wcgetsec(maxtime)
Xint maxtime;
X{
X register checksum, j, c;
X register unsigned short oldcrc;
X int sectcurr, sectcomp, attempts;
X
X for(attempts = 0; attempts < RETRYMAX; attempts++) {
X do {
X c = readbyte(maxtime);
X } while(c != SOH && c != EOT && c != CAN && c != TIMEOUT);
X
X switch(c) {
X case SOH:
X sectcurr = readbyte(3);
X sectcomp = readbyte(3);
X if ((sectcurr + sectcomp) == 0xff) {
X oldcrc = checksum = 0;
X for(j = 0; j < SECSIZ; j++) {
X if ((c = readbyte(3)) < 0)
X goto timeout;
X wcbuff[j] = c;
X if (crcheck)
X oldcrc = updcrc(c, oldcrc);
X else
X checksum += c;
X }
X if ((c = readbyte(3)) < 0)
X goto timeout;
X if (crcheck) {
X oldcrc = updcrc(c, oldcrc);
X if ((c = readbyte(3)) < 0)
X goto timeout;
X if (updcrc(c, oldcrc)) {
X fprintf(tfp,"\r\nCRC error\r\n");
X break;
X }
X }
X else if (((checksum - c) & 0xff) != 0) {
X fprintf(tfp,"\r\nChecksum error\r\n");
X break;
X }
X firstsec = FALSE;
X return(sectcurr);
X }
X else
X fprintf(tfp,"\r\nSector number garbled 0%03o 0%03o\r\n",
X sectcurr, sectcomp);
X break;
X case EOT:
X if (readbyte(3) == TIMEOUT)
X return(WCEOT);
X break;
X case CAN:
X fprintf(tfp,"\r\nSender CANcelled.\r\n");
X return(ERROR);
X case TIMEOUT:
X if (firstsec)
X break;
Xtimeout:
X fprintf(tfp,"\r\nTimeout\r\n");
X break;
X }
X fprintf(tfp,"\r\nTrying again on ths sector.\r\n");
X purge();
X if (firstsec)
X sendbyte(crcheck ? WANTCRC : NAK);
X else {
X maxtime = 6;
X sendbyte(NAK);
X }
X }
X fprintf(tfp,"\r\nRetry count exceeded.\r\n");
X canit();
X return(ERROR);
X}
X
X/* wcputsec outputs a Ward Christensen type sector.
X * it returns OK or ERROR
X */
Xstatic wcputsec(sectnum)
Xint sectnum;
X{
X register checksum, j, c, attempts;
X register unsigned short oldcrc;
X
X oldcrc = checksum = 0;
X for(j = 0; j < SECSIZ; j++) {
X c = wcbuff[j];
X oldcrc = updcrc(c, oldcrc);
X checksum += c;
X }
X oldcrc = updcrc(0, updcrc(0, oldcrc));
X
X for(attempts = 0; attempts < RETRYMAX; attempts++) {
X sendbyte(SOH);
X sendbyte(sectnum);
X sendbyte(-sectnum - 1);
X for(j = 0; j < SECSIZ; j++)
X sendbyte(wcbuff[j]);
X if (badline)
X purge();
X if (crcheck) {
X sendbyte((int) (oldcrc >> 8));
X sendbyte((int) oldcrc);
X }
X else
X sendbyte(checksum);
X switch(c = readbyte(10)) {
X case CAN:
X fprintf(tfp,"\r\nReceiver CANcelled.\r\n");
X return(ERROR);
X case ACK:
X firstsec = FALSE;
X return(OK);
X case NAK:
X fprintf(tfp,"\r\nGot a NAK on sector acknowledge.\r\n");
X break;
X case TIMEOUT:
X fprintf(tfp,"\r\nTimeout on sector acknowledge.\r\n");
X break;
X default:
X fprintf(tfp,"\r\nGot 0%03o for sector acknowledge.\r\n", c);
X do {
X if ((c = readbyte(3)) == CAN) {
X fprintf(tfp,"\r\nReceiver CANcelled.\r\n");
X return(ERROR);
X }
X } while(c != TIMEOUT);
X if (firstsec)
X crcheck = (c == WANTCRC);
X break;
X }
X }
X fprintf(tfp,"\r\nRetry count exceeded.\r\n");
X return(ERROR);
X}
X
X/* update the cyclic redundantcy check value
X */
Xstatic unsigned short updcrc(c, crc)
Xregister c;
Xregister unsigned crc;
X{
X register int i;
X
X for(i = 0; i < 8; i++) {
X if (crc & 0x8000) {
X crc <<= 1;
X crc += (((c <<= 1) & 0400) != 0);
X crc ^= 0x1021;
X }
X else {
X crc <<= 1;
X crc += (((c <<= 1) & 0400) != 0);
X }
X }
X return(crc);
X}
X
Xstatic zerobuff()
X{
X register int i;
X
X for(i = 0; i < SECSIZ; i++)
X wcbuff[i] = '\0';
X}
X
X/* send 10 CAN's to try to get the other end to shut up */
Xstatic canit()
X{
X register int i;
X
X for(i = 0; i < 20; i++)
X sendbyte(CAN);
X}
X
Xstatic setmode(c)
Xint c;
X{
X intdel(1);
X
X switch(mklow(c)) {
X case 't':
X textmode = TRUE;
X break;
X case 'b':
X textmode = FALSE;
X case ' ':
X break;
X
X default:
X return(1);
X }
X
X fprintf(tfp,"%s file transfer mode.\r\n", textmode ? "Text" : "Binary");
X
X return(0);
X}
X
X/* fill the CP/M sector buffer from the UNIX file
X * do text adjustments if necessary
X * return 1 if more sectors are to be read, or 0 if this is the last
X */
Xstatic getsec()
X{
X register int i, c;
X
X i = 0;
X while(i < SECSIZ && (c = getc(xfp)) != EOF) {
X if (textmode && c == '\n') {
X wcbuff[i++] = '\r';
X if (i >= SECSIZ) { /* handle a newline on the last byte */
X ungetc(c, xfp); /* of the sector */
X return(1);
X }
X }
X wcbuff[i++] = c;
X }
X /* make sure that an extra blank sector is not sent */
X if (c != EOF && (c = getc(xfp)) != EOF) {
X ungetc(c, xfp);
X return(1);
X }
X /* fill up the last sector with ^Z's if text mode or 0's if binary mode */
X while(i < SECSIZ)
X wcbuff[i++] = textmode ? CPMEOF : '\0';
X return(0);
X}
X
X/* Put received WC sector into a UNIX file
X * using text translations in nessesary.
X */
X
Xstatic putsec()
X{
X register int i, c;
X
X for(i = 0; i < SECSIZ; i++) {
X c = wcbuff[i];
X if (textmode) {
X if (c == CPMEOF)
X return(1);
X if (c == '\r')
X continue;
X }
X putc(c, xfp);
X }
X return(0);
X}
X
SHAR_EOF
if test 12344 -ne "`wc -c < 'xcxmdm.c'`"
then
echo shar: error transmitting "'xcxmdm.c'" '(should have been 12344 characters)'
fi
fi # end of overwriting check
echo shar: done with directory "'src'"
cd ..
# End of shell archive
exit 0
More information about the Alt.sources
mailing list