karl@triceratops.cis.ohio-state.edu (Karl Kleinpaste) (09/28/88)
#! /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