static char sccsid
[] = "@(#)umodem.c 1.1 (Berkeley) 11/2/84";
* UMODEM -- Implements the "CP/M User's Group XMODEM" protocol,
* the TERM II File Transfer Protocol (FTP) Number 1,
* and the TERM II File Transfer Protocol Number 4 for
* packetized file up/downloading.
* Note: UNIX System-Dependent values are indicated by the string [SD]
* in a comment field on the same line as the values.
* -- Lauren Weinstein, 6/81
* -- (Version 2.0) Modified for JHU/UNIX by Richard Conn, 8/1/81
* -- Version 2.1 Mods by Richard Conn, 8/2/81
* . File Size Included on Send Option
* -- Version 2.2 Mods by Richard Conn, 8/2/81
* . Log File Generation and Option Incorporated
* -- Version 2.3 Mods by Richard Conn, 8/3/81
* . TERM II FTP 1 Supported
* . Error Log Reports Enhanced
* . CAN Function Added to FTP 3
* . 'd' Option Added to Delete umodem.log File before starting
* -- Version 2.4 Mods by Richard Conn, 8/4/81
* . 16K-extent sector number check error corrected
* . Count of number of received sectors added
* -- Version 2.5 Mods by Richard Conn, 8/5/81
* . ARPA Net parameter ('a') added to command line
* . ARPA Net BIS, BIE, BOS, BOE added
* . ARPA Net FFH escape added
* -- Version 2.6 Mods by Bennett Marks, 8/21/81 (Bucky @ CCA-UNIX)
* . mods for UNIX V7 (Note: for JHU compilation define
* the variable JHU during 'cc'
* . added 'mungmode' flag to protect from inadvertant
* overwrite on file receive
* . changed timeout handling prior to issuing checksum
* -- Version 2.7 Mods by Richard Conn, 8/25/81 (rconn @ BRL)
* . correct minor "ifndef" error in which ifndef had no arg
* . restructured "ifdef" references so that other versions
* of UNIX than Version 7 and JHU can be easily incorporated;
* previous ifdef references were for JHU/not JHU;
* to compile under Version 7 or JHU UNIX, the following
* command lines are recommended:
* "cc umodem.c -o umodem -DVER7" for Version 7
* "cc -7 umodem.c -o umodem -DJHU" for JHU
* . added 'y' file status display option; this option gives
* the user an estimate of the size of the target file to
* send from the UNIX system in terms of CP/M records (128
* bytes) and Kbytes (1024 byte units)
* . added '7' option which modifies the transmission protocols
* for 7 significant bits rather than 8; modifies both FTP 1
* -- Version 2.8 Mods by Richard Conn, 8/28/81
* . corrected system-dependent reference to TIOCSSCR (for
* disabling page mode) and created the PAGEMODE flag which
* is to be set to TRUE to enable this
* . added -4 option which engages TERM II, FTP 4 (new release)
* -- Version 2.9 Mods by Richard Conn, 9/1/81
* . internal documentation on ARPA Net protocols expanded
* . possible operator precedence problem with BITMASK corrected
* by redundant parentheses
* -- Version 3.0 Mods by Lauren Weinstein, 9/14/81
* . fixed bug in PAGEMODE defines (removed PAGEMODE define
* line; now should be compiled with "-DPAGEMODE" if
* . included forward declaration of ttyname() to avoid problems
* with newer V7 C compilers
* -- Version 3.1 Mods by Lauren Weinstein, 4/17/82
* . avoids sending extraneous last sector when file EOF
* occurs on an exact sector boundary
* -- Version 3.2 Mods by Michael M Rubenstein, 5/26/83
* . fixed bug in readbyte. assumed that int's are ordered
* from low significance to high
* . added LOGDEFAULT define to allow default logging to be
* off. compile with -DLOGDEFAULT=0 to set default to no
* -- Version 3.3 Mod by Ben Goldfarb, 07/02/83
* . Corrected problem with above implementation of "LOGDEFAULT".
* A bitwise, instead of a logical negation operator was
* used to complement LOGFLAG when the '-l' command line
* flag was specified. This can cause LOGFLAG to be true
* when it should be false.
* -- Version 3.4 Mods by David F. Hinnant, NCECS, 7/15/83
* . placed log file in HOME directory in case user doesn't
* have write permission in working directory.
* . added DELDEFAULT define to allow default purge/no purge
* of logfile before starting. Compile with -DDELDEFAULT=0
* to set default to NOT delete the log file before starting.
* . check log file for sucessful fopen().
* . buffer disk read for sfile().
* . turn messages off (standard v7) before starting.
* -- Version 3.5 Mods by Richard Conn, 08/27/83
* . added equates for compilation under UNIX SYSTEM III
* to compile for SYSTEM III, use -DSYS3 instead of
* . added command mode (-c option) for continuous entry
* -- Version 3.6 Mods by Ben Goldfarb (ucf-cs!goldfarb), 09/03/83
* . added '#include <ctype.h>' since tolower() is used, but
* is not defined in umodem. This is necessary to compile
* on V7 systems. Also added a isupper() test because
* tolower() in /usr/include/ctype.h doesn't do that.
* . cleaned up all the improper bitwise complementation of
* logical constants and variables.
* -- Version 3.7 Mods by Noel J. Bergman, 02/27/84
* . Corrected problem with ALARM signal in 4.2 BSD Unix.
* BSD Unix restarts system calls after signal is handled,
* so setjmp() and longjmp() are used to handle I/O timeout.
* Since this will work with all Unix systems, and is a lot
* cleaner than depending on side effects, there is no need
* to make this code conditional.
/* JHU UNIX tty parameter file */
/* Version 7 UNIX tty parameter file */
/* UNIX SYSTEM III tty parameter file */
/* Delete logfile define. Useful on small systems with limited
* filesystem space and careless users.
#define VERSION 37 /* Version Number */
/* Compile with "-DPAGEMODE" if Page Mode (TIOCSSCR) is supported on your
* UNIX system. If it is supported, make sure that TIOCSSCR is the
* correct name for Page Mode engagement.
#define LF 012 /* Unix LF/NL */
#define CTRLZ 032 /* CP/M EOF for text (usually!) */
#define ERRORMAX 10 /* maximum errors tolerated */
#define RETRYMAX 10 /* maximum retries to be made */
#define BBUFSIZ 128 /* buffer size -- do not change! */
/* [SD] Mode for Created Files */
#define CREATMODE 0600 /* mode for created files */
/* The following constants are used to communicate with the ARPA
* Net SERVER TELNET and TIP programs. These constants are defined
* IAC <-- Is A Command; indicates that
* WILL/WONT <-- Command issued to SERVER TELNET
* (Host); WILL issues command
* and WONT issues negative of
* DO/DONT <-- Command issued to TIP; DO issues
* command and DONT issues
* negative of the command
* TRBIN <-- Transmit Binary Command
* IAC WILL TRBIN <-- Host is configured to transmit Binary
* IAC WONT TRBIN <-- Host is configured NOT to transmit binary
* IAC DO TRBIN <-- TIP is configured to transmit Binary
* IAC DONT TRBIN <-- TIP is configured NOT to transmit binary
#define IAC 0377 /* Is A Command */
#define DO 0375 /* Command to TIP */
#define DONT 0376 /* Negative of Command to TIP */
#define WILL 0373 /* Command to SERVER TELNET (Host) */
#define WONT 0374 /* Negative of Command to SERVER TELNET */
#define TRBIN 0 /* Transmit Binary Command */
/* JHU UNIX structures */
struct sttybuf ttys
, ttysnew
, ttystemp
; /* for stty terminal mode calls */
/* Version 7 UNIX structures */
struct sgttyb ttys
, ttysnew
, ttystemp
; /* for stty terminal mode calls */
/* UNIX SYSTEM III structures */
struct sgttyb ttys
, ttysnew
, ttystemp
; /* for stty terminal mode calls */
struct stat statbuf
; /* for terminal message on/off control */
int nbchr
; /* number of chars read so far for buffered read */
char *ttyname(); /* forward declaration for C */
char *ttyname(); /* forward declaration for C */
int ARPA
, CMNDFLAG
, RECVFLAG
, SENDFLAG
, FTP1
, PMSG
, DELFLAG
, LOGFLAG
, MUNGMODE
;
int STATDISP
, BIT7
, BITMASK
;
logfile
= "umodem.log"; /* Name of LOG File */
printf("\nUMODEM Version %d.%d", VERSION
/10, VERSION
%10);
printf(" -- UNIX-Based Remote File Transfer Facility\n");
if (argc
< 2 || *argv
[1] != '-')
index
= 1; /* set index for loop */
delay
= 3; /* assume FTP 3 delay */
PMSG
= FALSE
; /* turn off flags */
FTP1
= FALSE
; /* assume FTP 3 (CP/M UG XMODEM2) */
RECVFLAG
= FALSE
; /* not receive */
SENDFLAG
= FALSE
; /* not send either */
CMNDFLAG
= FALSE
; /* not command either */
XMITTYPE
= 't'; /* assume text */
ARPA
= FALSE
; /* assume not on ARPA Net */
MUNGMODE
= FALSE
; /* protect files from overwriting */
STATDISP
= FALSE
; /* assume not a status display */
BIT7
= FALSE
; /* assume 8-bit communication */
while ((flag
= argv
[1][index
++]) != '\0')
case '1' : FTP1
= TRUE
; /* select FTP 1 */
delay
= 5; /* FTP 1 delay constant */
printf("\nUMODEM: TERM II FTP 1 Selected\n");
case '4' : FTP1
= TRUE
; /* select FTP 1 (varient) */
BIT7
= TRUE
; /* transfer only 7 bits */
delay
= 5; /* FTP 1 delay constant */
printf("\nUMODEM: TERM II FTP 4 Selected\n");
case '7' : BIT7
= TRUE
; /* transfer only 7 bits */
case 'a' : ARPA
= TRUE
; /* set ARPA Net */
case 'c' : CMNDFLAG
= TRUE
; /* command mode */
case 'd' : DELFLAG
= !DELDEFAULT
; /* delete log file ? */
case 'l' : LOGFLAG
= !LOGDEFAULT
; /* turn off log ? */
case 'm' : MUNGMODE
= TRUE
; /* allow overwriting of files */
case 'p' : PMSG
= TRUE
; /* print all messages */
case 'r' : RECVFLAG
= TRUE
; /* receive file */
XMITTYPE
= gettype(argv
[1][index
++]); /* get t/b */
case 's' : SENDFLAG
= TRUE
; /* send file */
XMITTYPE
= gettype(argv
[1][index
++]);
case 'y' : STATDISP
= TRUE
; /* display file status */
default : error("Invalid Flag", FALSE
);
if (BIT7
&& (XMITTYPE
== 'b'))
{ printf("\nUMODEM: Fatal Error -- Both 7-Bit Transfer and ");
printf("Binary Transfer Selected");
exit(-1); /* error exit to UNIX */
if (BIT7
) /* set MASK value */
BITMASK
= 0177; /* 7 significant bits */
BITMASK
= 0377; /* 8 significant bits */
{ printf("\nSupported File Transfer Protocols:");
printf("\n\tTERM II FTP 1");
printf("\n\tCP/M UG XMODEM2 (TERM II FTP 3)");
printf("\n\tTERM II FTP 4");
if (CMNDFLAG
) LOGFLAG
= TRUE
; /* if command mode, always log */
if ((fname
= getenv("HOME")) == 0) /* Get HOME variable */
error("Can't get Environment!", FALSE
);
fname
= strcat(fname
, "/");
fname
= strcat(fname
, logfile
);
LOGFP
= fopen(fname
, "a"); /* append to LOG file */
LOGFP
= fopen(fname
, "w"); /* new LOG file */
error("Can't Open Log File", FALSE
);
fprintf(LOGFP
,"\n\n++++++++\n");
fprintf(LOGFP
,"\nUMODEM Version %d.%d\n", VERSION
/10, VERSION
%10);
printf("\nUMODEM: LOG File '%s' is Open\n", fname
);
yfile(argv
[2]); /* status of a file */
exit(0); /* exit to UNIX */
if (RECVFLAG
&& SENDFLAG
)
error("Both Send and Receive Functions Specified", FALSE
);
if (!RECVFLAG
&& !SENDFLAG
&& !CMNDFLAG
)
error("Send, Receive, or Command Functions NOT Given", FALSE
);
{ if(open(argv
[2], 0) != -1) /* possible abort if file exists */
{ printf("\nUMODEM: Warning -- Target File Exists\n");
error("Fatal - Can't overwrite file\n",FALSE
);
printf("UMODEM: Overwriting Target File\n");
rfile(argv
[2]); /* receive file */
if (SENDFLAG
) sfile(argv
[2]); /* send file */
else command(); /* command mode */
if (CMNDFLAG
) LOGFLAG
= TRUE
; /* for closing log file */
if (LOGFLAG
) fclose(LOGFP
);
printf("\nUMODEM Command Mode -- Type ? for Help");
printf(FTP1
? "1" : "3"); /* FTP 1 or 3? */
printf(BIT7
? "7" : " "); /* BIT 7 or not? */
printf(ARPA
? "A" : " "); /* ARPA Net or not? */
printf(LOGFLAG
? "L" : " "); /* Log Entries or not? */
printf(MUNGMODE
? "M" : " "); /* Mung Files or not? */
cmd
= isupper(filename
[0]) ? tolower(filename
[0]) : filename
[0];
case '1' : FTP1
= TRUE
; /* select FTP 1 */
delay
= 5; /* FTP 1 delay constant */
printf("\nTERM FTP 1 Selected");
case '3' : FTP1
= FALSE
; /* select FTP 3 */
delay
= 3; /* FTP 3 delay constant */
printf("\nTERM FTP 3 Selected");
case '7' : BIT7
= !BIT7
; /* toggle 7 bit transfer */
printf("\n7-Bit Transfer %s Selected",
case 'a' : ARPA
= !ARPA
; /* toggle ARPA Net */
printf("\nDDN Interface %s Selected",
case 'l' : LOGFLAG
= !LOGFLAG
; /* toggle log flag */
printf("\nEntry Logging %s Enabled",
case 'm' : MUNGMODE
= !MUNGMODE
; /* toggle file overwrite */
printf("\nFile Overwriting %s Enabled",
case 'r' : RECVFLAG
= TRUE
; /* receive file */
XMITTYPE
= tolower(filename
[1]);
fname
= infile(); /* get file name */
if (*fname
!= '\0') rfile(fname
);
case 's' : SENDFLAG
= TRUE
; /* send file */
XMITTYPE
= tolower(filename
[1]);
fname
= infile(); /* get file name */
if (*fname
!= '\0') sfile(fname
);
case 'y' : fname
= infile(); /* get file name */
if (*fname
!= '\0') yfile(fname
);
/* Get file name from user */
char *startptr
= filename
;
if (*startptr
== '.') *startptr
= '\0'; /* set NULL */
if (!caller
) { printf("\nUsage: \n\tumodem ");
printf("-[c!rb!rt!sb!st][options]");
printf("\nUsage: r or s or option");
printf("\nMajor Commands --");
if (!caller
) printf("\n\tc <-- Enter Command Mode");
printf("\n\trb <-- Receive Binary");
printf("\n\trt <-- Receive Text");
printf("\n\tsb <-- Send Binary");
printf("\n\tst <-- Send Text");
printf("\n\t1 <-- (one) Employ TERM II FTP 1");
if (caller
) printf("\n\t3 <-- Enable TERM FTP 3 (CP/M UG)");
if (!caller
) printf("\n\t4 <-- Enable TERM FTP 4");
printf("\n\t7 <-- Enable 7-bit transfer mask");
printf("\n\ta <-- Turn ON ARPA Net Flag");
printf("\n\td <-- Do not delete umodem.log file before starting");
printf("\n\td <-- Delete umodem.log file before starting");
printf("\n\tl <-- (ell) Turn OFF LOG File Entries");
printf("\n\tl <-- (ell) Turn ON LOG File Entries");
else printf("\n\tl <-- Toggle LOG File Entries");
printf("\n\tm <-- Allow file overwiting on receive");
if (!caller
) printf("\n\tp <-- Turn ON Parameter Display");
if (caller
) printf("\n\tx <-- Exit");
printf("\n\ty <-- Display file status (size) information only");
if (ichar
== 't') return(ichar
);
if (ichar
== 'b') return(ichar
);
error("Invalid Send/Receive Parameter - not t or b", FALSE
);
/* set tty modes for UMODEM transfers */
/* Device characteristics for JHU UNIX */
if (gtty(0, &ttys
) < 0) /* get current tty params */
error("Can't get TTY Parameters", TRUE
);
tty
= ttyname(0); /* identify current tty */
/* duplicate current modes in ttysnew structure */
ttysnew
.ispeed
= ttys
.ispeed
; /* copy input speed */
ttysnew
.ospeed
= ttys
.ospeed
; /* copy output speed */
ttysnew
.xflags
= ttys
.xflags
; /* copy JHU/UNIX extended flags */
ttysnew
.mode
= ttys
.mode
; /* copy standard terminal flags */
ttysnew
.mode
|= RAW
; /* set for RAW Mode */
/* This ORs in the RAW mode value, thereby
setting RAW mode and leaving the other
mode settings unchanged */
ttysnew
.mode
&= ~ECHO
; /* set for no echoing */
/* This ANDs in the complement of the ECHO
setting (for NO echo), thereby leaving all
current parameters unchanged and turning
ttysnew
.mode
&= ~XTABS
; /* set for no tab expansion */
ttysnew
.mode
&= ~LCASE
; /* set for no upper-to-lower case xlate */
ttysnew
.mode
|= ANYP
; /* set for ANY Parity */
ttysnew
.mode
&= ~NL3
; /* turn off ALL delays - new line */
ttysnew
.mode
&= ~TAB3
; /* turn off tab delays */
ttysnew
.mode
&= ~CR3
; /* turn off CR delays */
ttysnew
.mode
&= ~FF1
; /* turn off FF delays */
ttysnew
.mode
&= ~BS1
; /* turn off BS delays */
/* the following are JHU/UNIX xflags settings; they are [SD] */
ttysnew
.xflags
&= ~PAGE
; /* turn off paging */
ttysnew
.xflags
&= ~STALL
; /* turn off ^S/^Q recognition */
ttysnew
.xflags
&= ~TAPE
; /* turn off ^S/^Q input control */
ttysnew
.xflags
&= ~FOLD
; /* turn off CR/LF folding at col 72 */
ttysnew
.xflags
|= NB8
; /* turn on 8-bit input/output */
if (stty(0, &ttysnew
) < 0) /* set new params */
error("Can't set new TTY Parameters", TRUE
);
if (stat(tty
, &statbuf
) < 0) /* get tty status */
error("Can't get your TTY Status", TRUE
);
if (statbuf
.st_mode
&011) /* messages are on [SD] */
if (chmod(tty
, 020600) < 0) /* turn off tty messages [SD] */
error("Can't change TTY Mode", TRUE
);
wason
= FALSE
; /* messages are already off */
/* Device characteristics for Version 7 UNIX */
if (ioctl(0,TIOCGETP
,&ttys
)<0) /* get tty params [V7] */
error("Can't get TTY Parameters", TRUE
);
tty
= ttyname(0); /* identify current tty */
/* transfer current modes to new structure */
ttysnew
.sg_ispeed
= ttys
.sg_ispeed
; /* copy input speed */
ttysnew
.sg_ospeed
= ttys
.sg_ospeed
; /* copy output speed */
ttysnew
.sg_erase
= ttys
.sg_erase
; /* copy erase flags */
ttysnew
.sg_flags
= ttys
.sg_flags
; /* copy flags */
ttysnew
.sg_kill
= ttys
.sg_kill
; /* copy std terminal flags */
ttysnew
.sg_flags
|= RAW
; /* set for RAW Mode */
/* This ORs in the RAW mode value, thereby
setting RAW mode and leaving the other
mode settings unchanged */
ttysnew
.sg_flags
&= ~ECHO
; /* set for no echoing */
/* This ANDs in the complement of the ECHO
setting (for NO echo), thereby leaving all
current parameters unchanged and turning
ttysnew
.sg_flags
&= ~XTABS
; /* set for no tab expansion */
ttysnew
.sg_flags
&= ~LCASE
; /* set for no upper-to-lower case xlate */
ttysnew
.sg_flags
|= ANYP
; /* set for ANY Parity */
ttysnew
.sg_flags
&= ~NL3
; /* turn off ALL delays - new line */
ttysnew
.sg_flags
&= ~TAB2
; /* turn off tab delays */
ttysnew
.sg_flags
&= ~CR3
; /* turn off CR delays */
ttysnew
.sg_flags
&= ~FF1
; /* turn off FF delays */
ttysnew
.sg_flags
&= ~BS1
; /* turn off BS delays */
ttysnew
.sg_flags
&= ~TANDEM
; /* turn off flow control */
/* make sure page mode is off */
ioctl(0,TIOCSSCR
,&pagelen
); /* [SD] */
if (ioctl(0,TIOCSETP
,&ttysnew
) < 0)
error("Can't set new TTY Parameters", TRUE
);
if (stat(tty
, &statbuf
) < 0) /* get tty status */
error("Can't get your TTY Status", TRUE
);
if (statbuf
.st_mode
& 022) /* Need to turn messages off */
if (chmod(tty
, statbuf
.st_mode
& ~022) < 0)
error("Can't change TTY mode", TRUE
);
/* Device Characteristics for UNIX SYSTEM III */
if (gtty(0, &ttys
) < 0) /* get current tty params */
error("Can't get TTY Parameters", TRUE
);
tty
= ttyname(0); /* identify current tty */
/* transfer current modes to new structure */
ttysnew
.sg_ispeed
= ttys
.sg_ispeed
; /* copy input speed */
ttysnew
.sg_ospeed
= ttys
.sg_ospeed
; /* copy output speed */
ttysnew
.sg_erase
= ttys
.sg_erase
; /* copy erase flags */
ttysnew
.sg_flags
= ttys
.sg_flags
; /* copy flags */
ttysnew
.sg_kill
= ttys
.sg_kill
; /* copy std terminal flags */
ttysnew
.sg_flags
|= RAW
; /* set for RAW Mode */
/* This ORs in the RAW mode value, thereby
setting RAW mode and leaving the other
mode settings unchanged */
ttysnew
.sg_flags
&= ~ECHO
; /* set for no echoing */
/* This ANDs in the complement of the ECHO
setting (for NO echo), thereby leaving all
current parameters unchanged and turning
ttysnew
.sg_flags
&= ~XTABS
; /* set for no tab expansion */
ttysnew
.sg_flags
&= ~LCASE
; /* set for no upper-to-lower case xlate */
ttysnew
.sg_flags
|= ANYP
; /* set for ANY Parity */
ttysnew
.sg_flags
&= ~NL3
; /* turn off ALL delays - new line */
ttysnew
.sg_flags
&= ~TAB0
; /* turn off tab delays */
ttysnew
.sg_flags
&= ~TAB1
;
ttysnew
.sg_flags
&= ~CR3
; /* turn off CR delays */
ttysnew
.sg_flags
&= ~FF1
; /* turn off FF delays */
ttysnew
.sg_flags
&= ~BS1
; /* turn off BS delays */
if (stty(0, &ttysnew
) < 0) /* set new params */
error("Can't set new TTY Parameters", TRUE
);
if (stat(tty
, &statbuf
) < 0) /* get tty status */
error("Can't get your TTY Status", TRUE
);
if (statbuf
.st_mode
& 022) /* Need to turn messages off */
if (chmod(tty
, statbuf
.st_mode
& ~022) < 0)
error("Can't change TTY mode", TRUE
);
{ printf("\nUMODEM: TTY Device Parameters Altered");
ttyparams(); /* print tty params */
if (ARPA
) /* set 8-bit on ARPA Net */
/* set ARPA Net for 8-bit transfers */
sendbyte(IAC
); /* Is A Command */
sendbyte(WILL
); /* Command to SERVER TELNET (Host) */
sendbyte(TRBIN
); /* Command is: Transmit Binary */
sendbyte(IAC
); /* Is A Command */
sendbyte(DO
); /* Command to TIP */
sendbyte(TRBIN
); /* Command is: Transmit Binary */
sleep(3); /* wait for TIP to configure */
/* restore normal tty modes */
if (ARPA
) /* if ARPA Net, reconfigure */
/* Device characteristic restoration for JHU UNIX */
if (wason
) /* if messages were on originally */
if (chmod(tty
, 020611) < 0) /* [SD] */
error("Can't change TTY Mode", FALSE
);
if (stty(0, &ttys
) < 0) /* restore original tty modes */
error("RESET - Can't restore normal TTY Params", FALSE
);
printf("RESET - Can't restore normal TTY Params\n");
/* Device characteristic restoration for Version 7 UNIX */
if (chmod(tty
, statbuf
.st_mode
| 022) < 0)
error("Can't change TTY mode", FALSE
);
if (ioctl(0,TIOCSETP
,&ttys
) < 0)
error("RESET - Can't restore normal TTY Params", FALSE
);
printf("RESET - Can't restore normal TTY Params\n");
/* Device characteristic restoration for UNIX SYSTEM III */
if (chmod(tty
, statbuf
.st_mode
| 022) < 0)
error("Can't change TTY mode", FALSE
);
if (stty(0, &ttys
) < 0) /* restore original tty modes */
error("RESET - Can't restore normal TTY Params", FALSE
);
printf("RESET - Can't restore normal TTY Params\n");
{ printf("\nUMODEM: TTY Device Parameters Restored");
ttyparams(); /* print tty params */
sendbyte(IAC
); /* Is A Command */
sendbyte(WONT
); /* Negative Command to SERVER TELNET (Host) */
sendbyte(TRBIN
); /* Command is: Don't Transmit Binary */
sendbyte(IAC
); /* Is A Command */
sendbyte(DONT
); /* Negative Command to TIP */
sendbyte(TRBIN
); /* Command is: Don't Transmit Binary */
/* print error message and exit; if mode == TRUE, restore normal tty modes */
restoremodes(TRUE
); /* put back normal tty modes */
printf("UMODEM: %s\n", msg
);
if (LOGFLAG
& (int)LOGFP
)
{ fprintf(LOGFP
, "UMODEM Fatal Error: %s\n", msg
);
/** print status (size) of a file **/
printf("\nUMODEM File Status Display for %s\n", name
);
printf("File %s does not exist\n", name
);
prfilestat(name
); /* print status */
getbyte(fildes
, ch
) /* Buffered disk read */
* Get a byte from the specified file. Buffer the read so we don't
* have to use a system call for each character.
static char buf
[BUFSIZ
]; /* Remember buffer */
static char *bufp
= buf
; /* Remember where we are in buffer */
if (nbchr
== 0) /* Buffer exausted; read some more */
if ((nbchr
= read(fildes
, buf
, BUFSIZ
)) < 0)
error("File Read Error", TRUE
);
bufp
= buf
; /* Set pointer to start of array */
int fd
, j
, firstchar
, sectnum
, sectcurr
, tmode
;
int sectcomp
, errors
, errorflag
, recfin
;
register int bufctr
, checksum
;
int errorchar
, fatalerror
, startstx
, inchecksum
, endetx
, endenq
;
mode
= XMITTYPE
; /* set t/b mode */
if ((fd
= creat(name
, CREATMODE
)) < 0)
error("Can't create file for receive", FALSE
);
setmodes(); /* setup tty modes for xfer */
printf("\r\nUMODEM: File Name: %s", name
);
{ fprintf(LOGFP
, "\n----\nUMODEM Receive Function\n");
fprintf(LOGFP
, "File Name: %s\n", name
);
fprintf(LOGFP
, "TERM II File Transfer Protocol 1 Selected\n");
fprintf(LOGFP
, "TERM II File Transfer Protocol 4 Selected\n");
"TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
fprintf(LOGFP
, "7-Bit Transmission Enabled\n");
fprintf(LOGFP
, "8-Bit Transmission Enabled\n");
printf(" Transmission Enabled");
printf("\r\nUMODEM: Ready to RECEIVE File\r\n");
fatalerror
= FALSE
; /* NO fatal errors */
recvsectcnt
= 0; /* number of received sectors */
while (readbyte(4) != SYN
);
sendbyte(ACK
); /* FTP 1 Sync */
else sendbyte(NAK
); /* FTP 3 Sync */
} while ((firstchar
!= SOH
) && (firstchar
!= EOT
) && (firstchar
if (firstchar
== TIMEOUT
)
fprintf(LOGFP
, "Timeout on Sector %d\n", sectnum
);
{ if (FTP1
) readbyte(5); /* discard leading zero */
sectcurr
= readbyte(delay
);
sectcomp
= readbyte(delay
);
if (FTP1
) startstx
= readbyte(delay
); /* get leading STX */
if ((sectcurr
+ sectcomp
) == BITMASK
)
{ if (sectcurr
== ((sectnum
+1)&BITMASK
))
for (j
= bufctr
= 0; j
< BBUFSIZ
; j
++)
{ buff
[bufctr
] = c
= readbyte(delay
);
checksum
= ((checksum
+c
)&BITMASK
);
if (!tmode
) /* binary mode */
continue; /* skip CR's */
if (c
== CTRLZ
) /* skip CP/M EOF char */
{ recfin
= TRUE
; /* flag EOF */
if (FTP1
) endetx
= readbyte(delay
); /* get ending ETX */
inchecksum
= readbyte(delay
); /* get checksum */
if (FTP1
) endenq
= readbyte(delay
); /* get ENQ */
if (checksum
== inchecksum
) /* good checksum */
sectnum
= sectcurr
; /* update sector counter */
if (write(fd
, buff
, bufctr
) < 0)
error("File Write Error", TRUE
);
{ if (FTP1
) sendbyte(ESC
); /* FTP 1 requires <ESC> */
fprintf(LOGFP
, "Checksum Error on Sector %d\n",
{ if (sectcurr
== sectnum
)
{ while(readbyte(3) != TIMEOUT
);
if (FTP1
) sendbyte(ESC
); /* FTP 1 requires <ESC> */
{ fprintf(LOGFP
, "Phase Error - Received Sector is ");
fprintf(LOGFP
, "%d while Expected Sector is %d\n",
sectcurr
, ((sectnum
+1)&BITMASK
));
if (FTP1
) sendbyte(ESC
); /* FTP 1 requires <ESC> */
fprintf(LOGFP
, "Header Sector Number Error on Sector %d\n",
{ errorflag
= TRUE
; /* FTP 1 STX missing */
{ errorflag
= TRUE
; /* FTP 1 ETX missing */
{ errorflag
= TRUE
; /* FTP 1 ENQ missing */
if (errorflag
&& LOGFLAG
)
{ fprintf(LOGFP
, "Invalid Packet-Control Character: ");
case STX
: fprintf(LOGFP
, "STX"); break;
case ETX
: fprintf(LOGFP
, "ETX"); break;
case ENQ
: fprintf(LOGFP
, "ENQ"); break;
default : fprintf(LOGFP
, "Error"); break;
while (readbyte(3) != TIMEOUT
);
while ((firstchar
!= EOT
) && (errors
!= ERRORMAX
) && !fatalerror
);
if ((firstchar
== EOT
) && (errors
< ERRORMAX
))
{ if (!FTP1
) sendbyte(ACK
);
restoremodes(FALSE
); /* restore normal tty modes */
while (readbyte(3) != TIMEOUT
); /* flush EOT's */
sleep(3); /* give other side time to return to terminal mode */
{ fprintf(LOGFP
, "\nReceive Complete\n");
fprintf(LOGFP
,"Number of Received CP/M Records is %ld\n", recvsectcnt
);
{ if (LOGFLAG
&& FTP1
&& fatalerror
) fprintf(LOGFP
,
"Synchronization Error");
error("TIMEOUT -- Too Many Errors", TRUE
);
int nlflag
, sendfin
, tmode
;
register int bufctr
, checksum
, sectnum
;
int sendresp
; /* response char to sent block */
nbchr
= 0; /* clear buffered read char count */
mode
= XMITTYPE
; /* set t/b mode */
if ((fd
= open(name
, 0)) < 0)
{ if (LOGFLAG
) fprintf(LOGFP
, "Can't Open File\n");
error("Can't open file for send", FALSE
);
setmodes(); /* setup tty modes for xfer */
printf("\r\nUMODEM: File Name: %s", name
);
{ fprintf(LOGFP
, "\n----\nUMODEM Send Function\n");
fprintf(LOGFP
, "File Name: %s\n", name
);
printf("\r\n"); prfilestat(name
); /* print file size statistics */
fprintf(LOGFP
, "TERM II File Transfer Protocol 1 Selected\n");
fprintf(LOGFP
, "TERM II File Transfer Protocol 4 Selected\n");
"TERM II File Transfer Protocol 3 (CP/M UG) Selected\n");
fprintf(LOGFP
, "7-Bit Transmission Enabled\n");
fprintf(LOGFP
, "8-Bit Transmission Enabled\n");
printf(" Transmission Enabled");
printf("\r\nUMODEM: Ready to SEND File\r\n");
sendfin
= nlflag
= FALSE
;
{ sendbyte(SYN
); /* FTP 1 Synchronize with Receiver */
while (readbyte(5) != ACK
)
{ if(++attempts
> RETRYMAX
*6) error("Remote System Not Responding",
{ while (readbyte(30) != NAK
) /* FTP 3 Synchronize with Receiver */
if (++attempts
> RETRYMAX
) error("Remote System Not Responding",
sectnum
= 1; /* first sector number */
{ for (bufctr
=0; bufctr
< BBUFSIZ
;)
{ buff
[bufctr
++] = LF
; /* leftover newline */
if (getbyte(fd
, &c
) == EOF
)
{ sendfin
= TRUE
; /* this is the last sector */
if (!bufctr
) /* if EOF on sector boundary */
break; /* avoid sending extra sector */
buff
[bufctr
++] = CTRLZ
; /* Control-Z for CP/M EOF */
if (tmode
&& c
== LF
) /* text mode & Unix newline? */
{ if (c
== LF
) /* Unix newline? */
{ buff
[bufctr
++] = CR
; /* insert carriage return */
buff
[bufctr
++] = LF
; /* insert Unix newline */
nlflag
= TRUE
; /* insert newline on next sector */
buff
[bufctr
++] = c
; /* copy the char without change */
if (!bufctr
) /* if EOF on sector boundary */
break; /* avoid sending empty sector */
{ sendbyte(SOH
); /* send start of packet header */
if (FTP1
) sendbyte(0); /* FTP 1 Type 0 Packet */
sendbyte(sectnum
); /* send current sector number */
sendbyte(-sectnum
-1); /* and its complement */
if (FTP1
) sendbyte(STX
); /* send STX */
checksum
= 0; /* init checksum */
for (bufctr
=0; bufctr
< BBUFSIZ
; bufctr
++)
{ sendbyte(buff
[bufctr
]); /* send the byte */
if (ARPA
&& (buff
[bufctr
]==0xff)) /* ARPA Net FFH esc */
sendbyte(buff
[bufctr
]); /* send 2 FFH's for one */
checksum
= ((checksum
+buff
[bufctr
])&BITMASK
);
/* while (readbyte(3) != TIMEOUT); flush chars from line */
if (FTP1
) sendbyte(ETX
); /* send ETX */
sendbyte(checksum
); /* send the checksum */
if (FTP1
) sendbyte(ENQ
); /* send ENQ */
{ sendresp
= NAK
; /* prepare for NAK */
if (readbyte(10) == ESC
) sendresp
= readbyte(10);
sendresp
= readbyte(10); /* get response */
if ((sendresp
!= ACK
) && LOGFLAG
)
{ fprintf(LOGFP
, "Non-ACK Received on Sector %d\n",
fprintf(LOGFP
, "This Non-ACK was a TIMEOUT\n");
} while((sendresp
!= ACK
) && (attempts
!= RETRYMAX
));
sectnum
++; /* increment to next sector number */
} while (!sendfin
&& (attempts
!= RETRYMAX
));
if (attempts
== RETRYMAX
)
error("Remote System Not Responding", TRUE
);
while (attempts
++ < 10) sendbyte(EOT
);
{ sendbyte(EOT
); /* send 1st EOT */
while ((readbyte(15) != ACK
) && (attempts
++ < RETRYMAX
))
if (attempts
>= RETRYMAX
)
error("Remote System Not Responding on Completion", TRUE
);
sleep(5); /* give other side time to return to terminal mode */
{ fprintf(LOGFP
, "\nSend Complete\n");
/* print file size status information */
struct stat filestatbuf
; /* file status info */
stat(name
, &filestatbuf
); /* get file status bytes */
printf(" Estimated File Size %ldK, %ld Records, %ld Bytes",
(filestatbuf
.st_size
/1024)+1, (filestatbuf
.st_size
/128)+1,
fprintf(LOGFP
,"Estimated File Size %ldK, %ld Records, %ld Bytes\n",
(filestatbuf
.st_size
/1024)+1, (filestatbuf
.st_size
/128)+1,
/* get a byte from data stream -- timeout if "seconds" elapses */
signal(SIGALRM
,alarmfunc
); /* catch alarms */
alarm((unsigned) seconds
); /* set the alarm clock */
if (setjmp(env
) == 0) { /* if <> 0 then returned from timeout */
if (read(0, &c
, 1) < 0) /* get a char; error means time out */
alarm((unsigned) 0); /* turn off the alarm */
return((c
&BITMASK
)); /* return the char */
/* send a byte to data stream */
dataout
= (data
&BITMASK
); /* mask for 7 or 8 bits */
write(1, &dataout
, 1); /* write the byte */
/* function for alarm clock timeouts */
longjmp(env
,1); /* this is basically a dummy function to force error */
/* status return on the "read" call in "readbyte" */
/* print data on TTY setting */
/* Obtain TTY parameters for JHU UNIX */
gtty(0, &ttystemp
); /* get current tty params */
/* Obtain TTY parameters for Version 7 UNIX */
ioctl(0,TIOCGETP
,&ttystemp
);
/* Obtain TTY parameters for UNIX SYSTEM III */
gtty(0, &ttystemp
); /* get current tty params */
tty
= ttyname(0); /* get name of tty */
stat(tty
, &statbuf
); /* get more tty params */
printf("\r\n\nTTY Device Parameter Display");
printf("\r\n\tTTY Device Name is %s\r\n\n", tty
);
printf("\tAny Parity Allowed "); pryn(ANYP
);
printf("\tEven Parity Allowed"); pryn(EVENP
);
printf("\tOdd Parity Allowed "); pryn(ODDP
);
printf("\tEcho Enabled "); pryn(ECHO
);
printf("\tLower Case Map "); pryn(LCASE
);
printf("\tTabs Expanded "); pryn(XTABS
);
printf("\tCR Mode Enabled "); pryn(CRMOD
);
printf("\tRAW Mode Enabled "); pryn(RAW
);
/* Print extended terminal characteristics for JHU UNIX */
printf("\tBinary Mode Enabled"); pryn1(NB8
);
printf("\tCR/LF in Col 72 "); pryn1(FOLD
);
printf("\tRecognize ^S/^Q "); pryn1(STALL
);
printf("\tSend ^S/^Q "); pryn1(TAPE
);
printf("\tTerminal can BS "); pryn1(SCOPE
);
printf("\r\n"); /* New line to separate topics */
printf("\tTerminal Paging is "); pryn1(PAGE
);
if (ttystemp
.xflags
&PAGE
)
printf("\t Lines/Page is %d\r\n", ttystemp
.xflags
&PAGE
);
printf("\r\n"); /* New line to separate topics */
printf("\tTTY Input Rate : ");
prbaud(ttystemp
.ispeed
); /* print baud rate */
printf("\tTTY Output Rate : ");
prbaud(ttystemp
.ospeed
); /* print output baud rate */
printf("\r\n"); /* New line to separate topics */
printf("\tMessages Enabled ");
/* Print extended characteristics for Version 7 UNIX */
printf("\tTTY Input Rate : ");
prbaud(ttystemp
.sg_ispeed
);
printf("\tTTY Output Rate : ");
prbaud(ttystemp
.sg_ospeed
); /* print output baud rate */
/* Print extended characteristics for UNIX SYSTEM III */
printf("\tTTY Input Rate : ");
prbaud(ttystemp
.sg_ispeed
);
printf("\tTTY Output Rate : ");
prbaud(ttystemp
.sg_ospeed
); /* print output baud rate */
/* Version 7 UNIX flag test */
if (ttystemp
.sg_flags
&iflag
)
/* UNIX SYSTEM III flag test */
if (ttystemp
.sg_flags
&iflag
)
/* Extended flag test for JHU UNIX only */
if (ttystemp
.xflags
&iflag
)
/* JHU UNIX speed flag cases */
case B0050
: printf("50"); break;
case B0075
: printf("75"); break;
case B0110
: printf("110"); break;
case B0134
: printf("134.5"); break;
case B0150
: printf("150"); break;
case B0200
: printf("200"); break;
case B0300
: printf("300"); break;
case B0600
: printf("600"); break;
case B1200
: printf("1200"); break;
case B1800
: printf("1800"); break;
case B2400
: printf("2400"); break;
case B4800
: printf("4800"); break;
case B9600
: printf("9600"); break;
case EXT_A
: printf("External A"); break;
case EXT_B
: printf("External B"); break;
/* Version 7 UNIX speed flag cases */
case B50
: printf("50"); break;
case B75
: printf("75"); break;
case B110
: printf("110"); break;
case B134
: printf("134.5"); break;
case B150
: printf("150"); break;
case B200
: printf("200"); break;
case B300
: printf("300"); break;
case B600
: printf("600"); break;
case B1200
: printf("1200"); break;
case B1800
: printf("1800"); break;
case B2400
: printf("2400"); break;
case B4800
: printf("4800"); break;
case B9600
: printf("9600"); break;
case EXTA
: printf("External A"); break;
case EXTB
: printf("External B"); break;
/* UNIX SYSTEM III speed flag cases */
case B50
: printf("50"); break;
case B75
: printf("75"); break;
case B110
: printf("110"); break;
case B134
: printf("134.5"); break;
case B150
: printf("150"); break;
case B200
: printf("200"); break;
case B300
: printf("300"); break;
case B600
: printf("600"); break;
case B1200
: printf("1200"); break;
case B1800
: printf("1800"); break;
case B2400
: printf("2400"); break;
case B4800
: printf("4800"); break;
case B9600
: printf("9600"); break;
case EXTA
: printf("External A"); break;
case EXTB
: printf("External B"); break;
default : printf("Error"); break;