home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource3
/
169_01
/
kermitpc.c
< prev
next >
Wrap
Text File
|
1984-07-29
|
31KB
|
974 lines
/*
* K e r m i t File Transfer Utility
*
* UNIX Kermit, Columbia University, 1981, 1982, 1983
* Bill Catchings, Bob Cattani, Chris Maio, Frank da Cruz
*
* usage: kermit [csr][dlbe line baud escapechar] [f1 f2 ...]
*
* where c=connect, s=send [files], r=receive, d=debug,
* l=tty line, b=baud rate, e=escape char (decimal ascii code).
* For "host" mode Kermit, format is either "kermit r" to
* receive files, or "kermit s f1 f2 ..." to send f1 .. fn.
*
*
* Fixed up again for Unix, Jim Guyton 7/13/83 (Rand Corp)
*/
#include <stdio.h> /* Standard UNIX definitions */
#include <sgtty.h>
#include <signal.h>
#include <setjmp.h>
/* Conditional Compilation: 0 means don't compile it, nonzero means do */
#define UNIX 1 /* Conditional compilation for UNIX */
#define TOPS_20 0 /* Conditional compilation for TOPS-20 */
#define VAX_VMS 0 /* Ditto for VAX/VMS */
#define IBM_UTS 0 /* Ditto for Amdahl UTS on IBM systems */
/* Symbol Definitions */
#define MAXPACK 94 /* Maximum packet size */
#define SOH 1 /* Start of header */
#define SP 32 /* ASCII space */
#define CR 015 /* ASCII Carriage Return */
#define DEL 127 /* Delete (rubout) */
#define CTRLD 4
#define BRKCHR CTRLD /* Default escape character for CONNECT */
#define MAXTRY 5 /* Times to retry a packet */
#define MYQUOTE '#' /* Quote character I will use */
#define MYPAD 0 /* Number of padding characters I will need */
#define MYPCHAR 0 /* Padding character I need */
#define MYEOL '\n' /* End-Of-Line character I need */
#define MYTIME 5 /* Seconds after which I should be timed out */
#define MAXTIM 20 /* Maximum timeout interval */
#define MINTIM 2 /* Minumum timeout interval */
#define TRUE -1 /* Boolean constants */
#define FALSE 0
/* Global Variables */
int size, /* Size of present data */
n, /* Message number */
rpsiz, /* Maximum receive packet size */
spsiz, /* Maximum send packet size */
pad, /* How much padding to send */
timint, /* Timeout for foreign host on sends */
numtry, /* Times this packet retried */
oldtry, /* Times previous packet retried */
fd, /* File pointer of file to read/write */
remfd, /* File pointer of the host's tty */
image, /* -1 means 8-bit mode */
remspd, /* Speed of this tty */
host, /* -1 means we're a host-mode kermit */
debug; /* -1 means debugging */
char state, /* Present state of the automaton */
padchar, /* Padding character to send */
eol, /* End-Of-Line character to send */
escchr, /* Connect command escape character */
quote, /* Quote character in incoming data */
**filelist, /* List of files to be sent */
*filnam, /* Current file name */
recpkt[MAXPACK], /* Receive packet buffer */
packet[MAXPACK]; /* Packet buffer */
struct sgttyb
rawmode, /* Host tty "raw" mode */
cookedmode, /* Host tty "normal" mode */
remttymode; /* Assigned tty line "raw" mode */
jmp_buf env; /* Environment ptr for timeout longjump */
/*
* m a i n
*
* Main routine - parse command and options, set up the
* tty lines, and dispatch to the appropriate routine.
*/
main(argc,argv)
int argc; /* Character pointer for */
char **argv; /* command line arguments */
{
char *remtty,*cp; /* tty for CONNECT, char pointer */
int speed, cflg, rflg, sflg; /* speed of assigned tty, */
/* flags for CONNECT, RECEIVE, SEND */
if (argc < 2) usage(); /* Make sure there's a command line. */
cp = *++argv; argv++; argc -= 2; /* Set up pointers to args */
/* Initialize this side's SEND-INIT parameters */
eol = CR; /* EOL for outgoing packets */
quote = MYQUOTE; /* Standard control-quote char "#" */
pad = 0; /* No padding */
padchar = NULL; /* Use null if any padding wanted */
speed = cflg = sflg = rflg = 0; /* Turn off all parse flags */
remtty = 0; /* Default is host (remote) mode */
image = FALSE; /* Default to 7-bit mode */
escchr = BRKCHR; /* Default escape character */
while ((*cp) != NULL) /* Get a character from the cmd line */
switch (*cp++) /* Based on what the character is, */
{ /* do one of the folloing */
case '-': break; /* Ignore dash (UNIX style) */
case 'c': cflg++; break; /* C = CONNECT command */
case 's': sflg++; break; /* S = SEND command */
case 'r': rflg++; break; /* R = RECEIVE command */
case 'e': if (argc--) /* E = specify escape char */
escchr = atoi(*argv++); /* as ascii decimal number */
else usage();
if (debug) fprintf(stderr,"escape char is ascii %d\n",escchr);
break;
case 'l': if (argc--) /* L = specify tty line to use */
remtty = *argv++;
else usage();
if (debug) fprintf(stderr,"line %s\n",remtty);
break;
#if UNIX /* This part only for UNIX systems */
case 'b': if (argc--) speed = atoi(*argv++); /* Set baud rate */
else usage();
if (debug) fprintf(stderr,"speed %d\n",speed); break;
case 'i': image = TRUE; break; /* Image (8-bit) mode */
#endif /* UNIX */
case 'd': debug = TRUE; break; /* Debug mode */
}
/* Done parsing */
if ((cflg+sflg+rflg) != 1) usage(); /* Only one command allowed */
remfd = 0; /* Start out as a host (remote) */
host = TRUE;
if (remtty) /* If another tty was specified, */
{
remfd = open(remtty,2); /* open it */
if (remfd < 0) /* check for failure */
{
fprintf(stderr,"Kermit: cannot open %s\n",remtty);
exit(-1); /* Failed, quit. */
}
host = FALSE; /* Opened OK, flag local (not host) */
}
/* Put the tty(s) into the correct modes */
gtty(0,&cookedmode); /* Save current mode for later */
gtty(0,&rawmode);
rawmode.sg_flags |= (RAW|TANDEM);
rawmode.sg_flags &= ~(ECHO|CRMOD);
gtty(remfd,&remttymode); /* If local kermit, get mode of */
/* assigned tty */
remttymode.sg_flags |= (RAW|TANDEM);
remttymode.sg_flags &= ~(ECHO|CRMOD);
#if UNIX /* Speed changing for UNIX only */
if (speed) /* User specified a speed? */
{
switch(speed) /* Get internal system code */
{
case 110: speed = B110; break;
case 150: speed = B150; break;
case 300: speed = B300; break;
case 1200: speed = B1200; break;
case 2400: speed = B2400; break;
case 4800: speed = B4800; break;
case 9600: speed = B9600; break;
default: fprintf(stderr,"bad line speed\n");
}
remttymode.sg_ispeed = speed;
remttymode.sg_ospeed = speed;
}
#endif /* UNIX */
if (remfd) stty(remfd,&remttymode); /* Put asg'd tty in raw mode */
/* All set up, now execute the command that was given. */
if (cflg) connect(); /* CONNECT command */
if (sflg) /* SEND command */
{
if (argc--) filnam = *argv++; /* Get file to send */
else usage();
filelist = argv;
if (host) stty(0,&rawmode); /* Put tty in raw mode if remote */
if (sendsw() == FALSE) /* Send the file(s) */
printf("Send failed.\n"); /* Report failure */
else /* or */
printf("OK\n"); /* success */
if (host) stty(0,&cookedmode); /* Restore tty */
}
if (rflg) /* RECEIVE command */
{
if (host) stty(0,&rawmode); /* Put tty in raw mode if remote */
if (recsw() == FALSE) /* Receive the file */
printf("Receive failed.\n"); /* Report failure */
else /* or */
printf("OK\n"); /* success */
if (host) stty(0,&cookedmode); /* Restore tty */
}
}
usage() /* Give message if user makes */
{ /* a mistake in the command */
fprintf(stderr,
"usage: kermit [csr][di][lbe] [line] [baud] [esc char] [f1 f2 ...]\n");
exit();
}
/*
* s e n d s w
*
* Sendsw is the state table switcher for sending
* files. It loops until either it finishes, or
* an error is encountered. The routines called by
* sendsw are responsible for changing the state.
*
*/
sendsw()
{
char sinit(),sf