home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
uniflex
/
ufsend.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-22
|
19KB
|
527 lines
#include "ufk.h"
int offset, /* Offset in data buffer to start */
org_size; /* Original packet size */
char size_lowered; /* Flag if packet shortening has been done */
sendfile()
{
if (numprm <= 1) /* check parameter */
prterr(ER_FSPCREQ);
else if (!get_file_spec(TRUE)) /* Get filespec for send */
prterr(ER_NOFILSEL);
else
{
if (!open_port(TRUE,FALSE)) /* Setup communication port */
prterr(ER_POPNERR);
else
{
if (alloc_pkt(SEND)) /* Allocate packet memory */
{
sflg++;
set_frame();
if (!sendsw()) /* Send the file(s) */
disp(0,18,"Send failed.\n"); /* Report failure */
beep();
while (get_file_spec(FALSE)); /* Flush directory buffer */
}
close_port(sflg,FALSE);
}
}
}
/*
* 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(), sfile(), sattr(), sdata(), seof(), sbreak();
init_xfer(); /* Reset counters */
set_default_comm(); /* Set communication parameters */
state = 'S'; /* Send initiate is start state */
n = 0; /* Initialize message number */
offset = 0; /* Offset in data buffer to start */
size_lowered = FALSE; /* No long packet error received */
numtry = 0; /* Say no tries yet */
if (remote && (sflg != 2)) /* Wait before sending if remote */
kdelay(send_delay); /* and if no server mode request */
purgeline(ttyfd); /* Eat old input */
while(TRUE) /* Do this as long as necessary */
{
if (debug)
{
prtdbgf("Send state: ");
if (!screen)
fputs("Send state: ",stdout);
disp_state(50,13,state);
}
switch(state)
{
case 'S': /* Send-init */
state = sinit();
break;
case 'F': /* Send-file */
state = sfile();
break;
case 'A': /* Send attributes */
state = sattr();
break;
case 'D': /* Send-data */
state = sdata();
break;
case 'Z': /* Send-End-of-File */
state = seof();
break;
case 'B': /* Send-Break */
state = sbreak();
break;
case 'C': /* Complete */
fin_xfer();
return (TRUE);
case 'Q':
default: /* Unknown or abort, fail */
fin_xfer();
return (FALSE);
}
}
}
/*
* s i n i t
*
* Send Initiate: send this host's parameters and get other side's back.
*/
char sinit()
{
char num; /* Packet number */
int len; /* length */
if (numtry++ >= maxtry) /* If too many tries, give up */
return('Q');
spar(sndpkt,&len); /* Fill up init info packet */
spack('S',n,len,sndpkt,0,1); /* Send an S packet */
switch(rpack(&len,&num,recpkt,1)) /* What was the reply? */
{
case 'N': /* NAK, try it again */
return(state);
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, stay in S state */
return(state); /* and try again */
rpar(recpkt,len); /* Get other side's init info */
numtry = 0; /* Reset try counter */
n = ( n + 1) % 64; /* Bump packet count */
return('F'); /* OK, switch state to F */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('Q'); /* Abort */
case 'T': /* Timeout */
if (aborted)
return('Q'); /* aborted by user */
case FALSE: /* Receive failure, try again */
return(state);
default: /* Anything else, just "abort" */
return('Q');
}
}
/*
* s f i l e
*
* Send File Header.
*/
char sfile()
{
char num, /* Packet number */
fnm[15];
int i, len; /* length */
if (numtry++ >= maxtry) /* If too many tries, give up */
return('Q');
aborted = FALSE;
if (fp != ERROR) /* If left open, close it */
fclose(fp);
fp = fopen(filnam,"r"); /* open the file to be sent */
if (fp == NULL) /* If bad file pointer, give up */
{
error(PER_OPEN,"%s",filnam); /* Can't open file */
if (!get_file_spec(FALSE))
return('C'); /* No more files to do */
else
return('S'); /* Try next file */
}
for (i = strlen(filnam) - 1; i >= 0; --i)
if (filnam[i] == '/') /* Skip directory specification */
break;
strcpy(fnm,&filnam[i+1]);
map_case(fnm,OUT); /* map to correct case */
if (!nooutput)
{
if (screen)
{
disp(0,2,"Sending: ");
posit(20,2);
printf("%s as %s", filnam, fnm);
clreol(-1,-1);
}
else
printf("\n\lSending: %s as %s\n\l",filnam,fnm);
}
fnm[strlen(fnm)] = EOF; /* Terminate data */
len = bufill(sndpkt,TRUE,fnm);
spack('F',n,len,sndpkt,0,block_check_type); /* Send an F packet */
switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, stay in F state */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* Bump packet count */
if (attribute)
return('A'); /* Switch to attribute state */
else
{
if ((size = bufill(sndpkt,TRUE,0)) == EOF)/* data from file */
return('Z'); /* If EOF then empty data file */
org_size = size; /* Remember original size */
return('D'); /* Switch state to D */
}
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('Q'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(PER_ABORTED); /* send error packet */
return('Q'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in F */
return(state);
default: /* Something else, just "abort" */
return('Q');
}
}
/*
* s a t t r
*
* Send File Attributes
*/
char sattr()
{
char num; /* Packet number */
int len; /* length */
if (numtry++ >= maxtry) /* If too many tries "abort" */
return('Q');
snd_attributes(); /* Prepare send attribute packet */
spack('A',n,size,sndpkt,0,block_check_type);/* Send an A packet */
switch (rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, fail */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* and bump packet count */
if ((size = bufill(sndpkt,TRUE,0)) == EOF)/* Get data from file */
return('Z'); /* If EOF then empty data file */
org_size = size; /* Remember original size */
return('D'); /* Switch state to data */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('Q'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(PER_ABORTED); /* send error packet */
return('Q'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in B */
return(state);
default: /* Other, "abort" */
return ('Q');
}
}
/*
* s d a t a
*
* Send File Data
*/
char sdata()
{
char num, /* Packet number */
tmpc;
int len; /* length */
if (numtry++ >= maxtry) /* If too many tries, give up */
return('Q');
spack('D',n,size,sndpkt,offset,block_check_type);/* Send a D packet */
switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
if (n != num) /* which is just like an ACK for */
{ /* this packet so fall thru to 'Y' */
if ((org_size > 91) && auto_recover)/* If extended length... */
lower_size(); /* Lower packet size on error */
return(state); /* Try again */
}
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, fail */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* Bump packet count */
if (size_lowered)
adjust_size(); /* Still data in buffer */
else
{
offset = 0; /* No more old data in buffer */
if ((size = bufill(sndpkt,FALSE,0)) == EOF)/* Get new data */
return('Z'); /* If EOF set state to that */
org_size = size; /* Remember original size */
}
tmpc = *recpkt;
if (len == 1) /* Data on ack */
{
if (tmpc == 'Z') /* Stop entire batch */
filecount = 0; /* No more files to send */
if ((tmpc == 'X') || (tmpc == 'Z'))
aborted = tmpc - 64; /* Make binary */
}
if ((aborted == ABORTX) || (aborted == ABORTZ))
{
if (screen)
disp(0,19,"Transfer interrupted.");
else
fputs("Transfer interrupted.\n\l",stdout);
beep();
return('Z'); /* Send abort */
}
return('D'); /* Got data, stay in state D */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('Q'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(PER_ABORTED); /* send error packet */
return('Q'); /* aborted by user */
}
if ((org_size > 91) && auto_recover) /* If extended length... */
lower_size(); /* Lower packet size on error */
case FALSE: /* Receive failure, stay in D */
return(state);
default: /* Anything else, "abort" */
return('Q');
}
}
/*
* s e o f
*
* Send End-Of-File.
*/
char seof()
{
char num; /* Packet number */
int len, tlen; /* length */
if (numtry++ >= maxtry) /* If too many tries, "abort" */
return('Q');
tlen = 0; /* Assume no abort */
if ((aborted == ABORTX) || (aborted == ABORTZ))
{
*sndpkt = 'D'; /* Discard file on abort */
tlen = 1;
*(sndpkt+sizeof(char)) = '\0'; /* For debug printout */
}
spack('Z',n,tlen,sndpkt,0,block_check_type); /* Send a 'Z' packet */
switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, hold out */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* and bump packet count */
fclose(fp); /* Close the input file */
fp = ERROR; /* flag no file open */
if (!get_file_spec(FALSE))
return ('B'); /* Stop if no more files */
if (aborted == ABORTZ) /* Abort the rest ? */
{
while (get_file_spec(FALSE)); /* Flush directory buffer */
return ('B');
}
return('F'); /* More files, switch state to F */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('Q'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(PER_ABORTED); /* send error packet */
return('Q'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in Z */
return(state);
default: /* Something else, "abort" */
return('Q');
}
}
/*
* s b r e a k
*
* Send Break (EOT)
*/
char sbreak()
{
char num; /* Packet number */
int len; /* length */
if (numtry++ >= maxtry) /* If too many tries "abort" */
return('Q');
spack('B',n,0,sndpkt,0,block_check_type);/* Send a B packet */
switch (rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
{
case 'N': /* NAK, just stay in this state, */
num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
if (n != num) /* which is just like an ACK for */
return(state); /* this packet so fall thru to... */
case 'Y': /* ACK */
if (n != num) /* If wrong ACK, fail */
return(state);
numtry = 0; /* Reset try counter */
n = (n + 1) % 64; /* and bump packet count */
return('C'); /* Switch state to Complete */
case 'E': /* Error packet received */
prerrpkt(recpkt); /* Print it out and */
return('Q'); /* abort */
case 'T': /* Timeout */
if (aborted)
{
error(PER_ABORTED); /* send error packet */
return('Q'); /* aborted by user */
}
case FALSE: /* Receive failure, stay in B */
return(state);
default: /* Other, "abort" */
return ('Q');
}
}
lower_size()
{
int rest;
if (size >= 80) /* Minimum size to cut packet size to */
{
rest = size % 2; /* Find out if odd or even */
size /= 2; /* Half of it */
size += rest; /* Add rest if odd */
spsiz = size; /* Use the new size from now on */
size_lowered = TRUE; /* Flag size has been modified */
check_prefix(); /* Make sure not in middle of prefix sequence */
}
}
adjust_size()
{
offset += size; /* Increment offset to next unsend character */
if (offset + size >= org_size) /* Adjust size if past end of buffer */
{
size = org_size - offset;
size_lowered = FALSE; /* Flag modification done */
}
else
check_prefix(); /* Make sure not in middle of prefix sequence */
}
check_prefix()
{
register char *p;
char *q;
p = sndpkt + offset; /* Start check at this place */
q = p + size; /* Until end of current window */
while (p < q)
{
if (*p == repeat_quote) /* If it's a repeat quote character .. */
p += 2 * sizeof(char); /* Skip count */
if (*p == eight_quote) /* If it's an eight-bit quote */
p++; /* Skip it */
if (*p == quote) /* Same for control quote character */
p++;
p++; /* Point to next data character */
}
size = p - (sndpkt + offset); /* Calculate new size */
}