[net.sources] UMODEM

mike2@lcuxa.UUCP (01/05/87)

In response to the several requests for this over the past week
or so, following is a "shar" file of one of the many UMODEM
programs that float around.  It is fairly primitive, but it 
does work.  It can be improved, but doing so may not be worth
the effort.  Be aware that the various improvements to implement
ARPA FTP transfers are not documented in the manual pages below.
The source code is quite clear on this, as are the 'help' menus.
--------------------------CUT HERE--------------------------

#! /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:
#
#		umodem.1
#		umodem41.1
#		umodem41.c
#
-n # Created by  () 
on Mon Jan  5 10:38:35 EST 1987
#
if test -f 'umodem.1'
then
	echo shar: will not over-write existing file "'umodem.1'"
else
echo extracting "'umodem.1'"
sed 's/^X//' >umodem.1 <<'SHAR_EOF'
X'\" t
X.TH umodem 1 "Local"
X.SH NAME
Xumodem \- file transfer to and from personal computers
X.SH SYNOPSIS
X.B umodem\ 
X\fB-rb\fR | \fB-rt\fR | \fB-sb\fR | \fB-st\fR [ \fBqlmdy7\fR ] \fIfilename\fR
X.br
X.SH DESCRIPTION
XThis command is used to transfer files to and from a Personal Computer
Xusing the standard "CP/M User's Group (Ward Christensen)" protocol.
X\fIUmodem\fR can be used to transfer one file at a time either to the PC or
Xfrom the PC, and is compatible with most file transfer programs running on
Xthe PC.
X.SH "umodem"
X.I Umodem
Xcooperates with the a multitude of programs that run
Xon a Personal Computer to perform a file transfer.
XThe integrity of the transfer is enhanced by use of a block checksum
Xfor error detection, and block retransmission for error correction.
X.PP
X.I Umodem
Xrequires exactly one of the following :
X.TP 8
X.B -rb
XReceive Binary \- transfer a file
X.I from
Xthe Personal Computer, in raw binary mode.  Every byte of the file will be
Xtransferred intact.  This mode is usually used to transfer, for example, .COM
Xfiles.
X.TP
X.B -rt
XReceive Text \- transfer a file
X.I from
Xthe Personal Computer, in text mode.  In this mode the program attempts to
Xconvert from the CP/M text file format to the Unix format on-the-fly,
Xby stripping carriage-return characters, and by ceasing to store data
Xafter a Control-Z is detected.
X.TP
X.B -sb
XSend Binary \- transfer a file
X.I to
Xthe Personal Computer, in raw binary mode.  Every byte of the file will be
Xtransferred intact.  This mode is usually used to transfer, for example, .COM
Xfiles.
X.TP
X.B -st
XSend Text \- transfer a file
X.I to
Xthe Personal Computer, in text mode.  In this mode the program attempts to
Xconvert from the Unix text file format to the CP/M format on-the-fly,
Xby adding carriage-return characters, and by appending a control-z
Xcharacter to the end of the file.
X.PP
XIn addition,
X.I umodem
Xrecognizes the following options:
X.TP 8
X.B q
XQuiet option - the initial "boiler plate" of program name,
Xfile size, etc., is suppressed.
X.TP
X.B l
XLogfile option - enables logging the progress of the file transfer.
XThis option is primarily useful for debugging.
X.TP
X.B m
X"Mung-mode" option - unless this option is specified, an attempt to
Xreceive a
X.I filename
Xthat already exists will be denied.  With this option, the existing file
Xis overwritten.
X.TP
X.B d
XDelete the logfile, if it exists, before starting.
X.TP
X.B y
XDisplay file status (size) information only.
X.TP
X.B 7
XSeven-bit transfer option - strip off the high-order bit of each byte
Xbefore it is sent (\f2-st\f1 case) or stored (\f2-rt\f1 case).
XThis option is valid only for text-mode transfers.
X.PP
X\fIUmodem\fR supports only the checksum block
Xerror check, and not the more robust CRC.
XIt supports neither the MODEM7 nor the YAM batch file transfer
Xprotocols.  Only single file transfers are supported.
X.SH FILES
X$HOME/umodem.log - created or appended to if the
X.B "-l"
Xoption is specified.
SHAR_EOF
if test 2921 -ne "`wc -c < 'umodem.1'`"
then
	echo shar: error transmitting "'umodem.1'" '(should have been 2921 characters)'
fi
fi
if test -f 'umodem41.1'
then
	echo shar: will not over-write existing file "'umodem41.1'"
else
echo extracting "'umodem41.1'"
sed 's/^X//' >umodem41.1 <<'SHAR_EOF'
X.TH umodem 41 "Public Domain"
X.SH NAME
Xumodem - UNIX xmodem and terminal program
X.SH SYNOPSIS
Xumodem - [sb|st|rb|rt|o ...]
X.SH DESCRIPTION
X.I umodem
XThis documentation is intended to supplement the documentation
Xfor earlier versions of umodem that did not support terminal
Xmode.
X.br
X
XThis is a combination xmodem program (that can be activated 
Xremotely through a dial-in connection on a UNIX system) and
Xterminal program (that can access a dialout port on the UNIX
Xsystem, and invoke xmodem transfers with a remotely-dialed
Xsystem).  It employes the original Christensen checksum
Xerror checking only, not the more recent CRC checks.
X.br
X
XNo dialer protocol support is contained in the
Xprogram.  If the terminal mode is used, the user must send
Xthe appropriate codes to a modem attached to a UNIX port.
X.I umodem
Xtakes the current directory as default
X.SH TERMINAL MODE
XTerminal mode is invoked with the call umodem -o, but, before
Xdoing so the variable MODEM must be set with the identity of
Xthe modem port, typically of the form /dev/tty#.  If the
Xport is /dev/tty11, prior to invoking umodem the command:
X
X		export MODEM; MODEM=/dev/tty11
X
Xmust be sent.  There is no error-checking in this implementation
Xto check whether MODEM has been set appropriately; unpredictable
Xresults will occur in its absence!
X.SH DIAGNOSTICS
X.br
XWhen invoking terminal mode, there is no error checking for
Xa MODEM variable.  Get in the habit of making certain that MODEM
Xhas been set (e.g., echo $MODEM) before invoking umodem -o.
X.br
X
XThe escape character from terminal mode has been set to CONTROL-G
Xfor minimal interference with other applications.  This can be
Xchanged in the source code, if necessary.
X.br
X
XWhen in terminal mode, to receive an xmodem transfer from a remote
Xend, escape to the command mode (CTRL-G) and enter rb [name] or 
Xrt [name] as appropriate.  No error checking is performed if you
Xforget to specify a filename, and the incoming file will be stored
Xunpredictably, depending on the UNIX system.
X
SHAR_EOF
if test 2004 -ne "`wc -c < 'umodem41.1'`"
then
	echo shar: error transmitting "'umodem41.1'" '(should have been 2004 characters)'
fi
fi
if test -f 'umodem41.c'
then
	echo shar: will not over-write existing file "'umodem41.c'"
else
echo extracting "'umodem41.c'"
sed 's/^X//' >umodem41.c <<'SHAR_EOF'
X/*
X *  UMODEM Version 4.0
X *
X *  UMODEM -- Implements the "CP/M User's Group XMODEM" protocol, 
X *            the TERM II File Transfer Protocol (FTP) Number 1,
X *            and the TERM II File Transfer Protocol Number 4 for
X *            packetized file up/downloading.    
X *
X *    Note: UNIX System-Dependent values are indicated by the string [SD]
X *          in a comment field on the same line as the values.
X *
X *
X *         -- Lauren Weinstein, 6/81
X *         -- (Version 2.0) Modified for JHU/UNIX by Richard Conn, 8/1/81
X *         -- Version 2.1 Mods by Richard Conn, 8/2/81
X *              . File Size Included on Send Option
X *         -- Version 2.2 Mods by Richard Conn, 8/2/81
X *              . Log File Generation and Option Incorporated
X *         -- Version 2.3 Mods by Richard Conn, 8/3/81
X *              . TERM II FTP 1 Supported
X *              . Error Log Reports Enhanced
X *              . CAN Function Added to FTP 3
X *              . 'd' Option Added to Delete umodem.log File before starting
X *         -- Version 2.4 Mods by Richard Conn, 8/4/81
X *              . 16K-extent sector number check error corrected
X *              . Count of number of received sectors added
X *         -- Version 2.5 Mods by Richard Conn, 8/5/81
X *              . ARPA Net Flag added
X *              . ARPA Net parameter ('a') added to command line
X *              . ARPA Net BIS, BIE, BOS, BOE added
X *              . ARPA Net FFH escape added
X *         -- Version 2.6 Mods by Bennett Marks, 8/21/81 (Bucky @ CCA-UNIX)
X *              . mods for UNIX V7 (Note: for JHU compilation define
X *                the variable JHU  during 'cc'
X *              . added 'mungmode' flag to protect from inadvertant
X *                overwrite on file receive
X *              . changed timeout handling prior to issuing checksum
X *         -- Version 2.7 Mods by Richard Conn, 8/25/81 (rconn @ BRL)
X *              . correct minor "ifndef" error in which ifndef had no arg
X *              . restructured "ifdef" references so that other versions
X *                of UNIX than Version 7 and JHU can be easily incorporated;
X *                previous ifdef references were for JHU/not JHU;
X *                to compile under Version 7 or JHU UNIX, the following
X *                command lines are recommended:
X *                      "cc umodem.c -o umodem -DVER7" for Version 7
X *                      "cc -7 umodem.c -o umodem -DJHU" for JHU
X *              . added 'y' file status display option; this option gives
X *                the user an estimate of the size of the target file to
X *                send from the UNIX system in terms of CP/M records (128
X *                bytes) and Kbytes (1024 byte units)
X *              . added '7' option which modifies the transmission protocols
X *                for 7 significant bits rather than 8; modifies both FTP 1
X *                and FTP 3
X *         -- Version 2.8 Mods by Richard Conn, 8/28/81
X *              . corrected system-dependent reference to TIOCSSCR (for
X *                disabling page mode) and created the PAGEMODE flag which
X *                is to be set to TRUE to enable this
X *              . added -4 option which engages TERM II, FTP 4 (new release)
X *         -- Version 2.9 Mods by Richard Conn, 9/1/81
X *              . internal documentation on ARPA Net protocols expanded
X *              . possible operator precedence problem with BITMASK corrected
X *                by redundant parentheses
X *         -- Version 3.0 Mods by Lauren Weinstein, 9/14/81
X *              . fixed bug in PAGEMODE defines (removed PAGEMODE define
X *                line; now should be compiled with "-DPAGEMODE" if
X *                Page Mode is desired)
X *              . included forward declaration of ttyname() to avoid problems
X *                with newer V7 C compilers
X *         -- Version 3.1 Mods by Lauren Weinstein, 4/17/82
X *              . avoids sending extraneous last sector when file EOF
X *                occurs on an exact sector boundary
X *         -- Version 3.2 Mods by Michael M Rubenstein, 5/26/83
X *              . fixed bug in readbyte.  assumed that int's are ordered
X *                from low significance to high
X *              . added LOGDEFAULT define to allow default logging to be
X *                off.  compile with -DLOGDEFAULT=0 to set default to no
X *                logging.
X *         -- Version 3.3 Mod by Ben Goldfarb, 07/02/83
X *              . Corrected problem with above implementation of "LOGDEFAULT".
X *                A bitwise, instead of a logical negation operator was
X *                used to complement LOGFLAG when the '-l' command line
X *                flag was specified.  This can cause LOGFLAG to be true
X *                when it should be false.
X *         -- Version 3.4 Mods by David F. Hinnant, NCECS, 7/15/83
X *              . placed log file in HOME directory in case user doesn't
X *                have write permission in working directory.
X *              . added DELDEFAULT define to allow default purge/no purge
X *                of logfile before starting.  Compile with -DDELDEFAULT=0
X *                to set default to NOT delete the log file before starting.
X *              . check log file for sucessful fopen().
X *              . buffer disk read for sfile().
X *              . turn messages off (standard v7) before starting.
X *         -- Version 3.5 Mods by Richard Conn, 08/27/83
X *              . added equates for compilation under UNIX SYSTEM III
X *                      to compile for SYSTEM III, use -DSYS3 instead of
X *                      -DJHU or -DVER7
X *              . added command mode (-c option) for continuous entry
X *                      of commands
X *          --  Version 4.0 Mods by Mycroft Holmes, 04/17/84
X *                . released constraint on using caps for commands in
X *                        the 'command' mode. 
X *                . added descriptors for local mode, allowing use of
X *                        environmental variable 'MODEM' to specify
X *                        i/o port. now, no more limitation to remote
X *                        usage only.
X *                . added rudamentary terminal program for local mode
X *                        and (ala modem7 series, thankyou
X *                        WC) ^E exits terminal mode.  
X *                . reassigned SIGINT to command() when in local mode, thus
X *                        no die from program, just return to command mode.
X *                . put the conditional (on local mode) display of sector
X *                        counts (so you could see it work).
X *                . made case conversions to lower case conditional on
X *                        being upper case, instead of always.  thus using
X *                        lower case in commands works.  (defined 'mklow')
X *                . put in flag to search for in order to get past all this
X *                        garbage at the start of the file.
X *                . forced exit(0) on 'x' from command mode.
X * 	    --  Version 4.1 Mods by Mike Slomin, 11/21/85
X *		  . made compatible with Xilog UNIX system
X *		  . but retains compatibility with System V
X *		  . commands made parity independent
X *		  . port busy routines added (for terminal mode)
X *		  . toggle 300/1200 terminal mode speed added
X *		  . spaces added to the packet no. print routines so that
X *			  each packet number fully overwrites the previous
X *		   	  one (otherwise it's disconcerting!!)
X *EOS
X */
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <ctype.h>
X#define mklow(c) (isupper(c) ? tolower(c) : c)
X 
X#include <sgtty.h>
X 
X/* log default define */
X#ifndef LOGDEFAULT
X#define LOGDEFAULT      1
X#endif
X 
X/* Delete logfile define.  Useful on small systems with limited
X * filesystem space and careless users.
X */
X#ifndef DELDEFAULT
X#define DELDEFAULT      1
X#endif
X 
X#include <signal.h>
X 
X#define      VERSION    40      /* Version Number */
X#define      FALSE      0
X#define      TRUE       ~FALSE
X 
X/*  Compile with "-DPAGEMODE" if Page Mode (TIOCSSCR) is supported on your
X *  UNIX system.  If it is supported, make sure that TIOCSSCR is the
X *  correct name for Page Mode engagement.
X */
X 
X/*  ASCII Constants  */
X#define      SOH        001 
X#define      STX        002
X#define      ETX        003
X#define      EOT        004
X#define      ENQ        005
X#define      ACK        006
X#define      LF         012   /* Unix LF/NL */
X#define      CR         015  
X#define      NAK        025
X#define      SYN        026
X#define      CAN        030
X#define      ESC        033
X#define      CTRLZ      032   /* CP/M EOF for text (usually!) */
X#define      ZERO       000   /* binary send pad character    */
X 
X/*  UMODEM Constants  */
X#define      TIMEOUT    -1
X#define      ERRORMAX   10    /* maximum errors tolerated */
X#define      RETRYMAX   10    /* maximum retries to be made */
X#define      BBUFSIZ    128   /* buffer size -- do not change! */
X 
X/*  [SD] Mode for Created Files  */
X#define      CREATMODE  0644  /* mode for created files */
X 
X/*  ARPA Net Constants  */
X/*      The following constants are used to communicate with the ARPA
X *      Net SERVER TELNET and TIP programs.  These constants are defined
X *      as follows:
X *              IAC                     <-- Is A Command; indicates that
X *                                              a command follows
X *              WILL/WONT               <-- Command issued to SERVER TELNET
X *                                              (Host); WILL issues command
X *                                              and WONT issues negative of
X *                                              the command
X *              DO/DONT                 <-- Command issued to TIP; DO issues
X *                                              command and DONT issues
X *                                              negative of the command
X *              TRBIN                   <-- Transmit Binary Command
X *      Examples:
X *              IAC WILL TRBIN  <-- Host is configured to transmit Binary
X *              IAC WONT TRBIN  <-- Host is configured NOT to transmit binary
X *              IAC DO TRBIN    <-- TIP is configured to transmit Binary
X *              IAC DONT TRBIN  <-- TIP is configured NOT to transmit binary
X */
X#define      IAC        0377    /* Is A Command */
X#define      DO         0375    /* Command to TIP */
X#define      DONT       0376    /* Negative of Command to TIP */
X#define      WILL       0373    /* Command to SERVER TELNET (Host) */
X#define      WONT       0374    /* Negative of Command to SERVER TELNET */
X#define      TRBIN      0       /* Transmit Binary Command */
X 
Xstruct sgttyb  ttys, ttysnew, ttystemp;    /* for stty terminal mode calls */
Xstruct sgttyb  ttycon, ttycom;
X 
Xstruct stat statbuf;    /* for terminal message on/off control */
Xchar *strcat();
XFILE *LOGFP, *fopen();
Xchar buff[BBUFSIZ];
Xint nbchr;  /* number of chars read so far for buffered read */
X 
Xint wason;
Xint i_port, o_port;
Xint catch;
X 
Xint pagelen;
Xchar *ttyname();  /* forward declaration for C */
X 
Xchar *tty;
Xchar XMITTYPE;
Xint ARPA, CMNDFLAG, RECVFLAG, SENDFLAG, FTP1, PMSG, DELFLAG, LOGFLAG, MUNGMODE;
Xint STATDISP, BIT7, BITMASK, NOMUNGMODE;
Xint delay, baud;
Xchar filename[256];
Xchar  abusy[35], bbusy[35]; /* names of lock files */
Xalarmfunc();
X 
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X        char *getenv();
X        char *getlogin();
X        char *fname = filename;
X        char *logfile;
X        int index, termstart();
X        char flag;
X 
X        logfile = "umodem.log";  /* Name of LOG File */
X        i_port = 0;        /* default input port */
X        o_port = 1;        /* default output port */
X 
X        printf("\nUMODEM Version %d.%d", VERSION/10, VERSION%10);
X        printf(" -- UNIX-Based Remote File Transfer Facility\n");
X 
X        if (argc < 2 || *argv[1] != '-')
X        {
X                help(FALSE);
X                exit(-1);
X        }
X 
X	baud = 1200;     /* default to 1200 baud terminal operation */
X        index = 1;  /* set index for loop */
X        delay = 3;  /* assume FTP 3 delay */
X        PMSG = FALSE;  /* turn off flags */
X        FTP1 = FALSE;  /* assume FTP 3 (CP/M UG XMODEM2) */
X        RECVFLAG = FALSE;  /* not receive */
X        SENDFLAG = FALSE;  /* not send either */
X        CMNDFLAG = FALSE;  /* not command either */
X        XMITTYPE = 't';  /* assume text */
X        DELFLAG = DELDEFAULT;
X        LOGFLAG = LOGDEFAULT;
X        if (LOGFLAG) LOGFLAG = TRUE;
X           else LOGFLAG = FALSE;  /* set LOGFLAG to REALLY true or false */
X        ARPA = FALSE;  /* assume not on ARPA Net */
X        MUNGMODE = FALSE; /* protect files from overwriting */
X        NOMUNGMODE = TRUE; /* keep user from using MUNGMODE */
X        if ((strcmp(getlogin(),"zeus"))==0) NOMUNGMODE = FALSE;
X        STATDISP = FALSE;  /* assume not a status display */
X        BIT7 = FALSE;  /* assume 8-bit communication */
X        while ((flag = argv[1][index++]) != '\0')
X            switch (flag) {
X                case '1' : FTP1 = TRUE;  /* select FTP 1 */
X                           delay = 5;  /* FTP 1 delay constant */
X                           printf("\nUMODEM:  TERM II FTP 1 Selected\n");
X                           break;
X                case '4' : FTP1 = TRUE;  /* select FTP 1 (varient) */
X                           BIT7 = TRUE;  /* transfer only 7 bits */
X                           delay = 5;  /* FTP 1 delay constant */
X                           printf("\nUMODEM:  TERM II FTP 4 Selected\n");
X                           break;
X                case '7' : BIT7 = TRUE;  /* transfer only 7 bits */
X                           break;
X                case 'a' : ARPA = TRUE;  /* set ARPA Net */
X                           break;
X                case 'c' : CMNDFLAG = TRUE;  /* command mode */
X                           break;
X                case 'd' : DELFLAG = !DELDEFAULT;  /* delete log file ? */
X                           break;
X                case 'l' : LOGFLAG = !LOGDEFAULT;  /* turn off log ? */
X                           break;
X                case 'm' : 
X                           if(NOMUNGMODE) break;
X                           MUNGMODE = TRUE; /* allow overwriting of files */
X                           break;
X                case 'o' : 
X			   termstart();     /* checks for two lock files */
X			   if ((i_port = open(getenv("MODEM"), 2)) > 0) 
X                                o_port = i_port;
X                           else
X                                i_port = 0;
X                           if (i_port) {
X                               printf("\nCommunications to %s\n", 
X                                   ttyname(i_port));
X                               CMNDFLAG = TRUE; /* turn on command mode */
X                               printf("Entering local mode\n");
X                           }
X				break;
X                case 'p' : PMSG = TRUE;  /* print all messages */
X                           break;
X                case 'r' : RECVFLAG = TRUE;  /* receive file */
X                           XMITTYPE = gettype(argv[1][index++]);  /* get t/b */
X                           break;
X                case 's' : SENDFLAG = TRUE;  /* send file */
X                           XMITTYPE = gettype(argv[1][index++]);
X                           break;
X                case 'y' : STATDISP = TRUE;  /* display file status */
X                           break;
X                default  : error("Invalid Flag", FALSE);
X                }
X 
X        if (BIT7 && (XMITTYPE == 'b'))
X        {  printf("\nUMODEM:  Fatal Error -- Both 7-Bit Transfer and ");
X           printf("Binary Transfer Selected");
X           exit(-1);  /* error exit to UNIX */
X        }
X 
X        if (BIT7)  /* set MASK value */
X           BITMASK = 0177;  /* 7 significant bits */
X        else
X           BITMASK = 0377;  /* 8 significant bits */
X 
X        if (PMSG)
X           { printf("\nSupported File Transfer Protocols:");
X             printf("\n\tTERM II FTP 1");
X             printf("\n\tCP/M UG XMODEM2 (TERM II FTP 3)");
X             printf("\n\tTERM II FTP 4");
X             printf("\n\n");
X           }
X 
X        if (CMNDFLAG) LOGFLAG = TRUE;  /* if command mode, always log */
X        if (LOGFLAG)
X           { 
X             if ((fname = getenv("HOME")) == 0) /* Get HOME variable */
X                error("Can't get Environment!", FALSE);
X             fname = strcat(fname, "/");
X             fname = strcat(fname, logfile);
X             if (!DELFLAG)
X                LOGFP = fopen(fname, "a");  /* append to LOG file */
X             else
X                LOGFP = fopen(fname, "w");  /* new LOG file */
X             if (!LOGFP)
X                error("Can't Open Log File", FALSE);
X             fprintf(LOGFP,"\n\n++++++++\n");
X             fprintf(LOGFP,"\nUMODEM Version %d.%d\n", VERSION/10, VERSION%10);
X             printf("\nUMODEM:  LOG File '%s' is Open\n", fname);
X           }
X 
X        if (STATDISP) {
X                yfile(argv[2]);  /* status of a file */
X                exit(0);  /* exit to UNIX */
X                }
X 
X        if (RECVFLAG && SENDFLAG)
X                error("Both Send and Receive Functions Specified", FALSE);
X        if (!RECVFLAG && !SENDFLAG && !CMNDFLAG)
X                error("Send, Receive, or Command Functions NOT Given", FALSE);
X 
X        if (RECVFLAG)
X        {  if(open(argv[2], 0) != -1)  /* possible abort if file exists */
X           {    printf("\nUMODEM:  Warning -- Target File Exists\n");
X                if( MUNGMODE == FALSE )
X                        error("Fatal - Can't overwrite file\n",FALSE);
X                printf("UMODEM:  Overwriting Target File\n");
X           }
X           rfile(argv[2]);  /* receive file */
X        }
X        else {
X                if (SENDFLAG) sfile(argv[2]);  /* send file */
X                else command();  /* command mode */
X                }
X        if (CMNDFLAG) LOGFLAG = TRUE;  /* for closing log file */
X        if (LOGFLAG) fclose(LOGFP);
X        exit(0);
X}
X 
X/*  Major Command Mode  */
Xcommand()
X{
X        char cmd, *fname, *infile();
X        int command(), fpid, c;
X 
X        if (i_port) /* if local, then i_port is non-zero */
X                signal(SIGINT, command);
X        printf("\nUMODEM Command Mode -- Type ? for Help");
X        do {
X           printf("\n");
X           printf(FTP1 ? "1" : "3");  /* FTP 1 or 3? */
X           printf(BIT7 ? "7" : " ");  /* BIT 7 or not? */
X           printf(ARPA ? "A" : " ");  /* ARPA Net or not? */
X           printf(LOGFLAG ? "L" : " ");  /* Log Entries or not? */
X           printf(MUNGMODE ? "M" : " ");  /* Mung Files or not? */
X           printf(" UMODEM> ");
X           scanf("%s", filename);
X           switch (cmd = (mklow(filename[0])&0177)) {
X                case 't' : if (i_port==0) { /* only do it if local */
X                                printf("Sorry, must be in local mode.\n");
X                                break;
X                           }
X                           setmodes(baud);
X                           /* setup raw and noecho for console */
X                           gtty(0, &ttycon);
X                           gtty(0, &ttycom);
X                           ttycom.sg_flags |= RAW;
X                           ttycom.sg_flags &= ~ECHO;
X                           stty(0, &ttycom);
X			   gtty(i_port, &ttystemp); /* get port parameters */
X			   tty = ttyname(i_port);
X			   stat(tty, &statbuf);
X			   printf("\r\n");
X			   prbaud(ttystemp.sg_ispeed);
X			   printf("Modem port %s\r\n",tty);
X			   printf("Hit Control G to Exit ... \r\n\n");
X                           if (!(fpid = fork())) { 
X                                /* child to read from modem */
X                                signal(SIGINT, SIG_DFL);
X                                do {
X                                    if ((c=readbyte(0)) > 0)
X                                        conout(c);
X                                } while(1);
X                           } else {
X                                /* parent, reading from console */
X                                while ((c=conin()) != 'G'-0x40)
X                                    sendbyte(c);
X                                kill(fpid, 2);
X                           }
X                           /* put it back the way you got it */
X                           stty(0, &ttycon);
X                           printf("\n\nExiting terminal mode\n\n");
X                           break;
X                case '1' : FTP1 = TRUE;  /* select FTP 1 */
X                           delay = 5;  /* FTP 1 delay constant */
X                           printf("\nTERM FTP 1 Selected");
X                           break;
X                case '3' : FTP1 = FALSE; /* select FTP 3 */
X                           delay = 3;  /* FTP 3 delay constant */
X                           printf("\nTERM FTP 3 Selected");
X                           break;
X                case '7' : BIT7 = ~BIT7;  /* toggle 7 bit transfer */
X                           printf("\n7-Bit Transfer %s Selected",
X                                BIT7 ? "" : "NOT");
X                           break;
X                case 'a' : ARPA = ~ARPA;  /* toggle ARPA Net */
X                           printf("\nDDN Interface %s Selected",
X                                ARPA ? "" : "NOT");
X                           break;
X                case 'l' : LOGFLAG = ~LOGFLAG;  /* toggle log flag */
X                           printf("\nEntry Logging %s Enabled",
X                                LOGFLAG ? "" : "NOT");
X                           break;
X                case 'm' : 
X                           if(NOMUNGMODE)
X                           {
X                           printf("\nOverwrite Permission Denied");
X                           break;
X                           }
X                           MUNGMODE = ~MUNGMODE; /* toggle file overwrite */
X                           printf("\nFile Overwriting %s Enabled",
X                                MUNGMODE ? "" : "NOT");
X                           break;
X                case 'r' : RECVFLAG = TRUE;  /* receive file */
X                           XMITTYPE = mklow(filename[1]);
X                           fname = infile();  /* get file name */
X                           if (*fname != '\0') 
X                              {  if(open(fname, 0) != -1)
X                                 {
X                          printf("\nUMODEM:  Warning -- Target File Exists\n");
X                                    if( MUNGMODE == FALSE )
X                                      {
X                                      printf("Fatal - Can't overwrite file\n");
X                                      break;
X                                      }
X                                  printf("UMODEM:  Overwriting Target File\n");
X                                  }
X                                 rfile(fname);
X                              }
X                           break;
X                case 's' : SENDFLAG = TRUE;  /* send file */
X                           XMITTYPE = mklow(filename[1]);
X                           fname = infile();  /* get file name */
X                           if (*fname != '\0') sfile(fname);
X                           break;
X                case 'x' : if(i_port != 0){
X				close(i_port);
X				unlink (abusy);
X				unlink (bbusy);
X			   }
X			   exit(0); /* hard core exit */
X                case 'y' : fname = infile();  /* get file name */
X                           if (*fname != '\0') yfile(fname);
X                           break;
X		case 'b' : printf("Baud rate is now %d. Change? ",baud);
X			   scanf("%s",filename);
X			   printf("\r\n");
X			   cmd = mklow(filename[0] & 0177);
X			   if (cmd == 'y'){
X				if (baud == 1200)
X					baud = 300;
X				else baud = 1200;
X				}
X			   break;
X                default  : help(TRUE);
X           }
X        } while (cmd != 'x');
X}
X 
X/*  Get file name from user  */
Xchar *infile()
X{
X        char *startptr = filename;
X 
X        scanf("%s",startptr);
X        if (*startptr == '.') *startptr = '\0';  /* set NULL */
X        return(startptr);
X}
X 
X/*  Print Help Message  */
Xhelp(caller)
Xint caller;
X{
X        if (!caller) { printf("\nUsage:  \n\tumodem ");
X                printf("-[o!c!rb!rt!sb!st][options]");
X                printf(" filename\n");
X                }
X        else {
X                printf("\nUsage: r or s or option");
X                }
X        printf("\nMajor Commands --");
X        if (!caller) printf("\n\tc  <-- Enter Command Mode");
X        printf("\n\trb <-- Receive Binary");
X        printf("\n\trt <-- Receive Text");
X        printf("\n\tsb <-- Send Binary");
X        printf("\n\tst <-- Send Text");
X        printf("\nOptions --");
X        printf("\n\t1  <-- (one) Employ TERM II FTP 1");
X        if (caller) printf("\n\t3  <-- Enable TERM FTP 3 (CP/M UG)");
X        if (!caller) printf("\n\t4  <-- Enable TERM FTP 4");
X        printf("\n\t7  <-- Enable 7-bit transfer mask");
X        printf("\n\ta  <-- Turn ON ARPA Net Flag");
X	printf("\n\tt  <-- Enter terminal mode (if enabled)");
X	printf("\n\tb  <-- Toggle 1200/300 baud for terminal");
X        if (!caller)
X#if DELDEFAULT == 1
X        printf("\n\td  <-- Do not delete umodem.log file before starting");
X#else
X        printf("\n\td  <-- Delete umodem.log file before starting");
X#endif
X 
X        if (!caller)
X#if LOGDEFAULT == 1
X        printf("\n\tl  <-- (ell) Turn OFF LOG File Entries");
X#else
X        printf("\n\tl  <-- (ell) Turn ON LOG File Entries");
X#endif
X        else printf("\n\tl  <-- Toggle LOG File Entries");
X 
X        printf("\n\tm  <-- Allow file overwiting on receive");
X        if (!caller) printf("\n\tp  <-- Turn ON Parameter Display");
X        if (!caller) printf("\n\to  <-- Enable terminal mode ");
X        if (caller) printf("\n\tx  <-- Exit");
X        printf("\n\ty  <-- Display file status (size) information only");
X        printf("\n");
X}
X 
Xgettype(ichar)
Xchar ichar;
X{
X        if (ichar == 't') return(ichar);
X        if (ichar == 'b') return(ichar);
X        error("Invalid Send/Receive Parameter - not t or b", FALSE);
X        return;
X}
X 
X/* set tty modes for UMODEM transfers */
Xsetmodes(b)
Xint b;
X{
X 
X 
X        /* changed to get tty params from working console, so that
X           other mode changes would not interfere. */
X        if (gtty(0, &ttys) < 0)  /* get current tty params */
X                error("Can't get TTY Parameters", TRUE);
X        tty = ttyname(i_port);  /* identify current tty */
X        /* transfer current modes to new structure */
X        if (!i_port) {
X                ttysnew.sg_ispeed = ttys.sg_ispeed;     /* copy input speed */
X                ttysnew.sg_ospeed = ttys.sg_ospeed;     /* copy output speed */
X        } 
X	else if (b == 1200){
X                ttysnew.sg_ispeed = B1200;
X                ttysnew.sg_ospeed = B1200;
X		}
X	else {
X		ttysnew.sg_ispeed = B300;
X		ttysnew.sg_ospeed = B300;
X	}
X        ttysnew.sg_erase  = ttys.sg_erase;      /* copy erase flags */
X        ttysnew.sg_flags  = ttys.sg_flags;      /* copy flags */
X        ttysnew.sg_kill   = ttys.sg_kill;       /* copy std terminal flags */
X        
X 
X        ttysnew.sg_flags |= RAW;    /* set for RAW Mode */
X                        /* This ORs in the RAW mode value, thereby
X                           setting RAW mode and leaving the other
X                           mode settings unchanged */
X        ttysnew.sg_flags &= ~ECHO;  /* set for no echoing */
X                        /* This ANDs in the complement of the ECHO
X                           setting (for NO echo), thereby leaving all
X                           current parameters unchanged and turning
X                           OFF ECHO only */
X        ttysnew.sg_flags &= ~XTABS;  /* set for no tab expansion */
X        ttysnew.sg_flags &= ~LCASE;  /* set for no upper-to-lower case xlate */
X        ttysnew.sg_flags |= ANYP;  /* set for ANY Parity */
X        ttysnew.sg_flags &= ~NL3;  /* turn off ALL delays - new line */
X        ttysnew.sg_flags &= ~TAB0; /* turn off tab delays */
X        ttysnew.sg_flags &= ~TAB1;
X        ttysnew.sg_flags &= ~CR3;  /* turn off CR delays */
X        ttysnew.sg_flags &= ~FF1;  /* turn off FF delays */
X        ttysnew.sg_flags &= ~BS1;  /* turn off BS delays */
X 
X        if (stty(i_port, &ttysnew) < 0)  /* set new params */
X                error("Can't set new TTY Parameters", TRUE);
X 
X        if (stat(tty, &statbuf) < 0)  /* get tty status */ 
X                error("Can't get your TTY Status", TRUE);
X 
X        if (PMSG)
X                { printf("\nUMODEM:  TTY Device Parameters Altered");
X                  ttyparams();  /* print tty params */
X                }
X 
X        if (ARPA)  /* set 8-bit on ARPA Net */
X                setarpa();
X 
X        return;
X}
X 
X/*  set ARPA Net for 8-bit transfers  */
Xsetarpa()
X{
X        sendbyte(IAC);  /* Is A Command */
X        sendbyte(WILL); /* Command to SERVER TELNET (Host) */
X        sendbyte(TRBIN);        /* Command is:  Transmit Binary */
X 
X        sendbyte(IAC);  /* Is A Command */
X        sendbyte(DO);   /* Command to TIP */
X        sendbyte(TRBIN);        /* Command is:  Transmit Binary */
X 
X        sleep(3);  /* wait for TIP to configure */
X 
X        return;
X}
X 
X/* restore normal tty modes */
Xrestoremodes(errcall)
Xint errcall;
X{
X        if (ARPA)  /* if ARPA Net, reconfigure */
X                resetarpa();
X 
X 
X        if (stty(i_port, &ttys) < 0)  /* restore original tty modes */
X                { if (!errcall)
X                   error("RESET - Can't restore normal TTY Params", FALSE);
X                else
X                   { printf("UMODEM:  ");
X                     printf("RESET - Can't restore normal TTY Params\n");
X                   }
X                }
X 
X        if (PMSG)
X                { printf("\nUMODEM:  TTY Device Parameters Restored");
X                  ttyparams();  /* print tty params */
X                }
X 
X        return;
X}
X 
X/* reset the ARPA Net */
Xresetarpa()
X{
X        sendbyte(IAC);  /* Is A Command */
X        sendbyte(WONT); /* Negative Command to SERVER TELNET (Host) */
X        sendbyte(TRBIN);        /* Command is:  Don't Transmit Binary */
X 
X        sendbyte(IAC);  /* Is A Command */
X        sendbyte(DONT); /* Negative Command to TIP */
X        sendbyte(TRBIN);        /* Command is:  Don't Transmit Binary */
X 
X        return;
X}
X 
X/* print error message and exit; if mode == TRUE, restore normal tty modes */
Xerror(msg, mode)
Xchar *msg;
Xint mode;
X{
X        if (mode)
X                restoremodes(TRUE);  /* put back normal tty modes */
X        printf("UMODEM:  %s\n", msg);
X        if (LOGFLAG & (int)LOGFP)
X        {   fprintf(LOGFP, "UMODEM Fatal Error:  %s\n", msg);
X            fclose(LOGFP);
X        }
X        exit(-1);
X}
X 
X/**  print status (size) of a file  **/
Xyfile(name)
Xchar *name;
X{
X        printf("\nUMODEM File Status Display for %s\n", name);
X 
X        if (open(name,0) < 0) {
X                printf("File %s does not exist\n", name);
X                return;
X                }
X 
X        prfilestat(name);  /* print status */
X        printf("\n");
X}
X 
Xgetbyte(fildes, ch)                             /* Buffered disk read */
Xint fildes;
Xchar *ch;
X/*
X *
X *      Get a byte from the specified file.  Buffer the read so we don't
X *      have to use a system call for each character.
X *
X */
X 
X{
X        static char buf[BUFSIZ];        /* Remember buffer */
X        static char *bufp = buf;        /* Remember where we are in buffer */
X        
X        if (nbchr == 0)                 /* Buffer exausted; read some more */
X        {
X                if ((nbchr = read(fildes, buf, BUFSIZ)) < 0)
X                        error("File Read Error", TRUE);
X                bufp = buf;             /* Set pointer to start of array */
X        }
X        if (--nbchr >= 0)
X        {
X                *ch = *bufp++;
X                return(0);
X        }
X        else
X                return(EOF);
X}
X 
X/**  receive a file  **/
Xrfile(name)
Xchar *name;
X{
X        char mode;
X        int fd, j, firstchar, sectnum, sectcurr, tmode;
X        int sectcomp, errors, errorflag, recfin;
X        register int bufctr, checksum;
X        register int c;
X        int errorchar, fatalerror, startstx, inchecksum, endetx, endenq;
X        long recvsectcnt;
X 
X        mode = XMITTYPE;  /* set t/b mode */
X        if ((fd = creat(name, CREATMODE)) < 0)
X                error("Can't create file for receive", FALSE);
X        setmodes(baud);  /* setup tty modes for xfer */
X        printf("\r\nUMODEM:  File Name: %s", name);
X        if (LOGFLAG)
X        {    fprintf(LOGFP, "\n----\nUMODEM Receive Function\n");
X             fprintf(LOGFP, "File Name: %s\n", name);
X             if (FTP1)
X                if (!BIT7)
X                 fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
X                else
X                 fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
X             else
X                fprintf(LOGFP,
X                  "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
X             if (BIT7)
X                fprintf(LOGFP, "7-Bit Transmission Enabled\n");
X             else
X                fprintf(LOGFP, "8-Bit Transmission Enabled\n");
X        }
X        printf("\r\nUMODEM:  ");
X        if (BIT7)
X                printf("7-Bit");
X        else
X                printf("8-Bit");
X        printf(" Transmission Enabled");
X        printf("\r\nUMODEM:  Ready to RECEIVE File\r\n");
X 
X        recfin = FALSE;
X        sectnum = errors = 0;
X        fatalerror = FALSE;  /* NO fatal errors */
X        recvsectcnt = 0;  /* number of received sectors */
X 
X        if (mode == 't')
X                tmode = TRUE;
X        else
X                tmode = FALSE;
X 
X        if (tmode && i_port)
X                printf("\n\rText mode conversions activated (cp/m files)\n\r");
X 
X        if (i_port)
X                printf("\nSync...\n\n");
X        if (FTP1)
X        {
X          while (readbyte(4) != SYN);
X          sendbyte(ACK);  /* FTP 1 Sync */
X        }
X        else sendbyte(NAK);  /* FTP 3 Sync */
X 
X        do
X        {   errorflag = FALSE;
X            do {
X                  firstchar = readbyte(6);
X            } while ((firstchar != SOH) && (firstchar != EOT) && (firstchar 
X                     != TIMEOUT));
X            if (firstchar == TIMEOUT)
X            {  if (LOGFLAG)
X                fprintf(LOGFP, "Timeout on Sector %d\n", sectnum);
X               errorflag = TRUE;
X            }
X 
X            if (firstchar == SOH)
X            {  if (FTP1) readbyte(5);  /* discard leading zero */
X               sectcurr = readbyte(delay);
X               sectcomp = readbyte(delay);
X               if (FTP1) startstx = readbyte(delay);  /* get leading STX */
X               if ((sectcurr + sectcomp) == BITMASK)
X               {  if (sectcurr == ((sectnum+1)&BITMASK))
X                  {  checksum = 0;
X                     for (j = bufctr = 0; j < BBUFSIZ; j++)
X                     {  buff[bufctr] = c = readbyte(delay);
X                        checksum = ((checksum+c)&BITMASK);
X                        if (!tmode)  /* binary mode */
X                        {  bufctr++;
X                           continue;
X                        }
X                        if (c == CR)
X                           continue;  /* skip CR's */
X                        if (c == CTRLZ)  /* skip CP/M EOF char */
X                        {  recfin = TRUE;  /* flag EOF */
X                           continue;
X                        }
X                        if (!recfin)
X                           bufctr++;
X                     }
X                     if (FTP1) endetx = readbyte(delay);  /* get ending ETX */
X                     inchecksum = readbyte(delay);  /* get checksum */
X                     if (FTP1) endenq = readbyte(delay); /* get ENQ */
X                     if (checksum == inchecksum)  /* good checksum */
X                     {  errors = 0;
X                        recvsectcnt++;
X                        sectnum = sectcurr;  /* update sector counter */
X                        if (write(fd, buff, bufctr) < 0)
X                           error("File Write Error", TRUE);
X                        else
X                        {  
X                           if (i_port)
X                                fprintf(stderr, "Received Sector %d   \r", sectcurr);
X                            if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
X                           sendbyte(ACK);
X                        }
X                     }
X                     else
X                     {  if (LOGFLAG)
X                          fprintf(LOGFP, "Checksum Error on Sector %d   \n",
X                                sectnum);
X                          errorflag = TRUE;
X                     }
X                  }
X                  else
X                  { if (sectcurr == sectnum)
X                    {  while(readbyte(3) != TIMEOUT);
X                       if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
X                       sendbyte(ACK);
X                    }
X                    else
X                    {  if (LOGFLAG)
X                        { fprintf(LOGFP, "Phase Error - Received Sector is ");
X                          fprintf(LOGFP, "%d while Expected Sector is %d\n",
X                           sectcurr, ((sectnum+1)&BITMASK));
X                        }
X                        errorflag = TRUE;
X                        fatalerror = TRUE;
X                        if (FTP1) sendbyte(ESC);  /* FTP 1 requires <ESC> */
X                        sendbyte(CAN);
X                    }
X                  }
X           }
X           else
X           {  if (LOGFLAG)
X                fprintf(LOGFP, "Header Sector Number Error on Sector %d\n",
X                   sectnum);
X               errorflag = TRUE;
X           }
X        }
X        if (FTP1 && !errorflag)
X        {  if (startstx != STX)
X           {  errorflag = TRUE;  /* FTP 1 STX missing */
X              errorchar = STX;
X           }
X           if (endetx != ETX)
X           {  errorflag = TRUE;  /* FTP 1 ETX missing */
X              errorchar = ETX;
X           }
X           if (endenq != ENQ)
X           {  errorflag = TRUE;  /* FTP 1 ENQ missing */
X              errorchar = ENQ;
X           }
X           if (errorflag && LOGFLAG)
X           {  fprintf(LOGFP, "Invalid Packet-Control Character:  ");
X              switch (errorchar) {
X                case STX : fprintf(LOGFP, "STX"); break;
X                case ETX : fprintf(LOGFP, "ETX"); break;
X                case ENQ : fprintf(LOGFP, "ENQ"); break;
X                default  : fprintf(LOGFP, "Error"); break;
X              }
X              fprintf(LOGFP, "\n");
X           }
X        }
X        if (errorflag == TRUE)
X        {  errors++;
X           while (readbyte(3) != TIMEOUT);
X           sendbyte(NAK);
X        }
X  }
X  while ((firstchar != EOT) && (errors != ERRORMAX) && !fatalerror);
X  if ((firstchar == EOT) && (errors < ERRORMAX))
X  {  if (!FTP1) sendbyte(ACK);
X     close(fd);
X     restoremodes(FALSE);  /* restore normal tty modes */
X     if (FTP1)
X        while (readbyte(3) != TIMEOUT);  /* flush EOT's */
X     sleep(3);  /* give other side time to return to terminal mode */
X     if (LOGFLAG)
X     {  fprintf(LOGFP, "\nReceive Complete\n");
X        fprintf(LOGFP,"Number of Received CP/M Records is %ld\n", recvsectcnt);
X     }
X     printf("\n");
X  }
X  else
X  {  if (LOGFLAG && FTP1 && fatalerror) fprintf(LOGFP,
X        "Synchronization Error");
X     error("TIMEOUT -- Too Many Errors", TRUE);
X  }
X}
X 
X/**  send a file  **/
Xsfile(name)
Xchar *name;
X{
X        char mode, c;
X        int fd, attempts, nlflag, sendfin, tmode, sendresp;
X        register int bufctr, checksum, sectnum;
X 
X        nbchr = 0;  /* clear buffered read char count */
X        mode = XMITTYPE;  /* set t/b mode */
X        if ((fd = open(name, 0)) < 0)
X        {  if (LOGFLAG) fprintf(LOGFP, "Can't Open File\n");
X           error("Can't open file for send", FALSE);
X        }
X        setmodes(baud);  /* setup tty modes for xfer */     
X        printf("\r\nUMODEM:  File Name: %s", name);
X        if (LOGFLAG)
X        {   fprintf(LOGFP, "\n----\nUMODEM Send Function\n");
X            fprintf(LOGFP, "File Name: %s\n", name);
X        }
X        printf("\r\n"); prfilestat(name);  /* print file size statistics */
X        if (LOGFLAG)
X        {  if (FTP1)
X              if (!BIT7)
X                fprintf(LOGFP, "TERM II File Transfer Protocol 1 Selected\n");
X              else
X                fprintf(LOGFP, "TERM II File Transfer Protocol 4 Selected\n");
X           else
X                fprintf(LOGFP,
X                   "TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
X           if (BIT7)
X                fprintf(LOGFP, "7-Bit Transmission Enabled\n");
X           else
X                fprintf(LOGFP, "8-Bit Transmission Enabled\n");
X        }
X        printf("\r\nUMODEM:  ");
X        if (BIT7)
X                printf("7-Bit");
X        else
X                printf("8-Bit");
X        printf(" Transmission Enabled");
X        printf("\r\nUMODEM:  Ready to SEND File\r\n");
X 
X        if (mode == 't')
X           tmode = TRUE;
X        else
X           tmode = FALSE;
X 
X        if (tmode && i_port)
X                printf("\n\rText mode conversions activated (cp/m files)\n\r");
X        sendfin = nlflag = FALSE;
X        attempts = 0;
X 
X        if (i_port)
X                printf("\nSync...\n\n");
X        if (FTP1)
X        {  sendbyte(SYN);  /* FTP 1 Synchronize with Receiver */
X           while (readbyte(5) != ACK)
X           {  if(++attempts > RETRYMAX*6) error("Remote System Not Responding",
X                TRUE);
X              sendbyte(SYN);
X           }
X        }
X        else
X        {  while (readbyte(30) != NAK)  /* FTP 3 Synchronize with Receiver */
X           if (++attempts > RETRYMAX) error("Remote System Not Responding",
X                TRUE);
X        }
X 
X        sectnum = 1;  /* first sector number */
X        attempts = 0;
X 
X        do 
X        {   for (bufctr=0; bufctr < BBUFSIZ;)
X            {   if (nlflag)
X                {  buff[bufctr++] = LF;  /* leftover newline */
X                   nlflag = FALSE;
X                }
X                if (getbyte(fd, &c) == EOF)
X                {  sendfin = TRUE;  /* this is the last sector */
X                   if (!bufctr)  /* if EOF on sector boundary */
X                      break;  /* avoid sending extra sector */
X                   if (tmode)
X                      buff[bufctr++] = CTRLZ;  /* Control-Z for CP/M EOF */
X                   else
X                      buff[bufctr++] = ZERO;
X                   continue;
X                }
X                if (tmode && c == LF)  /* text mode & Unix newline? */
X                {  if (c == LF)  /* Unix newline? */
X                   {  buff[bufctr++] = CR;  /* insert carriage return */
X                      if (bufctr < BBUFSIZ)
X                         buff[bufctr++] = LF;  /* insert Unix newline */
X                      else
X                         nlflag = TRUE;  /* insert newline on next sector */
X                   }
X                   continue;
X                }       
X                buff[bufctr++] = c;  /* copy the char without change */
X            }
X            attempts = 0;
X        
X            if (!bufctr)  /* if EOF on sector boundary */
X               break;  /* avoid sending empty sector */
X 
X            do
X            {   
X                if (i_port)
X                        fprintf(stderr, "Sending Sector %d   \r", sectnum);
X                sendbyte(SOH);  /* send start of packet header */
X                if (FTP1) sendbyte(0);  /* FTP 1 Type 0 Packet */
X                sendbyte(sectnum);  /* send current sector number */
X                sendbyte(-sectnum-1);  /* and its complement */
X                if (FTP1) sendbyte(STX);  /* send STX */
X                checksum = 0;  /* init checksum */
X                for (bufctr=0; bufctr < BBUFSIZ; bufctr++)
X                {  sendbyte(buff[bufctr]);  /* send the byte */
X                   if (ARPA && (buff[bufctr]==0xff))  /* ARPA Net FFH esc */
X                        sendbyte(buff[bufctr]);  /* send 2 FFH's for one */
X                   checksum = ((checksum+buff[bufctr])&BITMASK);
X                }
X/*              while (readbyte(3) != TIMEOUT);   flush chars from line */
X                if (FTP1) sendbyte(ETX);  /* send ETX */
X                sendbyte(checksum);  /* send the checksum */
X                if (FTP1) sendbyte(ENQ);  /* send ENQ */
X                attempts++;
X                if (FTP1)
X                {  sendresp = NAK;  /* prepare for NAK */
X                   if (readbyte(10) == ESC) sendresp = readbyte(10);
X                }
X                else
X                   sendresp = readbyte(10);  /* get response */
X                if ((sendresp != ACK) && LOGFLAG)
X                   { fprintf(LOGFP, "Non-ACK Received on Sector %d   \n",
X                      sectnum);
X                     if (sendresp == TIMEOUT)
X                        fprintf(LOGFP, "This Non-ACK was a TIMEOUT\n");
X                   }
X            }   while((sendresp != ACK) && (attempts != RETRYMAX));
X            sectnum++;  /* increment to next sector number */
X    }  while (!sendfin && (attempts != RETRYMAX));
X 
X    if (attempts == RETRYMAX)
X        error("Remote System Not Responding", TRUE);
X 
X    attempts = 0;
X    if (FTP1)
X        while (attempts++ < 10) sendbyte(EOT);
X    else
X    {   sendbyte(EOT);  /* send 1st EOT */
X        while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX))
X           sendbyte(EOT);
X        if (attempts >= RETRYMAX)
X           error("Remote System Not Responding on Completion", TRUE);
X    }
X 
X    close(fd);
X    restoremodes(FALSE);  
X    sleep(5);  /* give other side time to return to terminal mode */
X    if (LOGFLAG)
X    {  fprintf(LOGFP, "\nSend Complete\n");
X    }
X    printf("\n");
X 
X}
X 
X/*  print file size status information  */
Xprfilestat(name)
Xchar *name;
X{
X        struct stat filestatbuf; /* file status info */
X 
X        stat(name, &filestatbuf);  /* get file status bytes */
X        printf("  Estimated File Size %ldK, %ld Records, %ld Bytes",
X          (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
X          filestatbuf.st_size);
X        if (LOGFLAG)
X          fprintf(LOGFP,"Estimated File Size %ldK, %ld Records, %ld Bytes\n",
X          (filestatbuf.st_size/1024)+1, (filestatbuf.st_size/128)+1,
X          filestatbuf.st_size);
X        return;
X}
X 
X/* get a byte from data stream -- timeout if "seconds" elapses */
Xreadbyte(seconds)
Xunsigned seconds;
X{
X        char c;
X        
X        signal(SIGALRM,alarmfunc);  /* catch alarms */  
X        alarm(seconds);  /* set the alarm clock */
X        if (read(i_port, &c, 1) < 0)  /* get a char; error means we timed out */
X          {
X             return(TIMEOUT);
X          }
X        alarm(0);  /* turn off the alarm */
X        return((c&BITMASK));  /* return the char */
X}
X 
X/* send a byte to data stream */
Xsendbyte(data)
Xchar data;
X{
X        char dataout;
X        dataout = (data&BITMASK);  /* mask for 7 or 8 bits */
X        write(o_port, &dataout, 1);  /* write the byte */
X        return;
X}
X 
X/* function for alarm clock timeouts */
Xalarmfunc()
X{
X        return;  /* this is basically a dummy function to force error */
X                 /* status return on the "read" call in "readbyte"    */
X}
X 
X/* print data on TTY setting */
Xttyparams()
X{
X        
X        gtty(i_port, &ttystemp);  /* get current tty params */
X 
X        tty = ttyname(i_port);  /* get name of tty */
X        stat(tty, &statbuf);  /* get more tty params */
X 
X          printf("\r\n\nModem Port Parameter Display");
X          printf("\r\n\tTTY Device Name is %s\r\n\n", tty);
X          printf("\tAny Parity Allowed "); pryn(ANYP);
X          printf("\tEven Parity Allowed"); pryn(EVENP);
X          printf("\tOdd Parity Allowed "); pryn(ODDP);
X          printf("\tEcho Enabled       "); pryn(ECHO);
X          printf("\tLower Case Map     "); pryn(LCASE);
X          printf("\tTabs Expanded      "); pryn(XTABS);
X          printf("\tCR Mode Enabled    "); pryn(CRMOD);
X          printf("\tRAW Mode Enabled   "); pryn(RAW);
X 
X          printf("\tTTY Input Rate     :   ");
X            prbaud(ttystemp.sg_ispeed);
X          printf("\tTTY Output Rate    :   ");
X            prbaud(ttystemp.sg_ospeed);  /* print output baud rate */
X}
X 
Xpryn(iflag)
Xint iflag;
X{
X 
X        if (ttystemp.sg_flags&iflag)
X 
X           printf(":   Yes\r\n");
X        else
X           printf(":   No\r\n");
X}
X 
X 
Xprbaud(speed)
Xchar speed;
X{
X        switch (speed) {
X 
X                case B75 : printf("75"); break;
X                case B110 : printf("110"); break;
X                case B134 : printf("134.5"); break;
X                case B150 : printf("150"); break;
X                case B200 : printf("200"); break;
X                case B300 : printf("300"); break;
X                case B600 : printf("600"); break;
X                case B1200 : printf("1200"); break;
X                case B1800 : printf("1800"); break;
X                case B2400 : printf("2400"); break;
X                case B4800 : printf("4800"); break;
X                case B9600 : printf("9600"); break;
X                default : printf("Error");break;
X        }
X        printf(" Baud\r\n");
X}
X
X
Xtermstart()
X{
X	int k,i;
X	FILE *bp;
X	char *getenv();
X	char filnm[30];
X
X	strcpy (bbusy, getenv("MODEM"));
X	for(i=0; bbusy[i+3]; ++i)
X	{
X		if (bbusy[i] != 'd')
X			continue;
X		if (bbusy[i] != 'e')
X			continue;
X		if (bbusy[i] != 'v')
X			continue;
X		if (bbusy[i] != '/')
X			continue;
X		k=0;
X		while (bbusy[i]){
X			filnm[k] = bbusy[i];
X			++i;
X			++k;
X			}
X		filnm[k] = 0;
X		strcpy (bbusy, "/usr/spool/uucp/LCK..");
X		strcat (bbusy, filnm);
X		if ((bp=fopen(bbusy,"r")) == NULL)
X		{
X			if((bp=fopen(bbusy,"w")) == NULL)
X			{
X			   printf("Can't open uucp lock file %s\n", bbusy);
X			   exit (-1);
X			}
X			fclose(bp);
X			i=438;
X			chmod(bbusy,i);
X		}
X		else
X		{
X			printf("uucp lock file is present! Try later.\n");
X			exit(-1);
X		}
X	}
X	return;
X}
Xconin()
X{
Xchar c;
Xread(0, &c, 1);
Xc=c&127;
Xreturn(c);
X}
Xconout(c)
Xchar c;
X{
Xc = c&127;
Xwrite (1,&c,1);
X}
X
SHAR_EOF
if test 49868 -ne "`wc -c < 'umodem41.c'`"
then
	echo shar: error transmitting "'umodem41.c'" '(should have been 49868 characters)'
fi
fi
# end of shell archive
exit 0