home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pub
/
researchmachines
/
rmlrec.c
< prev
next >
Wrap
Text File
|
2020-01-01
|
10KB
|
421 lines
/***********************************************************************/
/* File KREC.C - Receive-procedures for RML Kermit;
Chris Kennington, RML. 9th July 1985. */
#define DEFS1 1
#define DEFS2 1
#define DEFS4 1
#include "stdio.h"
#include "b:kext.h"
static char *ptr2; /* Pointer to converted file name */
static int len;
char cpmunge(len,new,old)
/* Convert supplied name to a (similar) one which is legal
* for CP/M; all alphabetics to upper case, all punctuation
* deleted except for a single dot (the first if more than
* one in input), colon taken as restarting the munge, all
* controls deleted, length limited to 8.3, if input is
* > 8 without a dot, dot inserted and next 3 chars used
* as suffix. Munge terminated by 0 as a C-string.
* Returns length of munged name (not including terminating 0). */
char *old, *new;
int len;
{
char c, i, j, p2, dotty;
j = p2 = dotty = 0;
for (i=0; i<len; ++i) { /* step thro' old */
/* unwanted chars, continue the loop; wanted chars, store at end. */
if (p2 > 3)
goto Exit; /* suffix full */
c = old[i] & 0x7f;
if (c > '@') { /* ordinaries */
c &= 0x5f; /* upper case */
if (c > 0x5a)
continue; /* illegal chars */
}
else if (c > SP) switch(c) { /* punctuation & numerals */
case'0': /* accept all numerals */
case'1':
case'2':
case'3':
case'4':
case'5':
case'6':
case'7':
case'8':
case'9':
case'$':
break;
case ':': /* previous was disk-letter */
j = 0; /* start afresh */
dotty = 0;
continue;
case '.': /* CP/M divider */
if (dotty != 0)
continue; /* two dots illegal */
if (j == 0)
continue; /* leading dot illegal */
++dotty;
break;
default: /* all others ignored */
continue;
} /* end else-if-switch */
else /* controls etc. */
continue;
/* anything that reaches here must be stored */
if (dotty == 0) { /* in main name */
if (j > 7) { /* but it's full */
++dotty;
new[j++] = '.'; /* rest as suffix */
++p2;
} }
else /* in suffix */
++p2;
new[j++] = c;
} /* end for */
if (j == 0) { /* no valid chars in "old" */
strcpy(new,DEFNAM); /* so replace with default */
j = DEFLEN; /* length of default */
}
Exit:
new[j] = 0; /* close as string */
return(j);
} /* end of cpmunge() */
char rdata() /* Receive Data */
{
int fail, num;
char typ;
if (numtry++ > MAXTRY)
return('A'); /* abort if too many tries */
typ = rpack(&len,&num,recpkt);
switch(typ) {
case 'D': /* Data */
if (num != n) { /* not right packet */
if (oldtry++ > MAXTRY)
return('A');
if (num == ((n==0) ? 63:n-1)) {
spack('Y',num,0,0); /* re-ACK previous */
numtry = 0;
if (list == 1)
outc('D');
if (list > 2)
printf("\rDbg: Duplicate (%c).",tochar(num));
return(state); /* Don't write out data! */
}
else return('A'); /* sorry, wrong number */
}
if ( (fail = bufemp(recpkt,len)) != 0 ) {
error(diskfail,fail);
return('A');
}
spack('Y',n,0,0);
inctry(); /* ++n%64 & mod tries */
return('D'); /* Remain in data state */
case 'F': /* Got a File Header */
case 'X': /* or a text header */
if (oldtry++ > MAXTRY)
return('A'); /* If too many tries, "abort" */
if (num == ((n==0) ? 63:n-1)) {
spack('Y',num,0,0); /* ACK previous again */
numtry = 0;
return(state); /* Stay in Data state */
}
else return('A'); /* Not previous packet, "abort" */
case 'Z': /* End-Of-File */
if (num != n)
return('A');
if (fp != 0)
printmsg("** File <%s> received. ",ptr2);
kclose(fp); /* Close the file */
spack('Y',n,0,0);
fp = 0;
n = (n+1)%64;
return('F'); /* Go back to Receive File state */
case 'E': /* Error packet received */
prerrpkt(recpkt);
reclose();
return('A'); /* abort */
case 'A': /* user aborted transfer */
recfail();
reclose();
return('A');
case FALSE: /* Didn't get packet */
spack('N',n,0,0);
return(state); /* Keep trying */
default: /* Some other; abort */
error(badmsg,'D',typ);
return('A');
}
} /* end of rdata() */
static recfail() /* process user abort */
{
char num;
abtflag = 0;
rpack(&len,&num,recpkt); /* wait for next packet */
error(errmsg); /* then abort */
return;
} /* end of recfail() */
static reclose() /* close file if open */
{
if (fp != 0) {
kclose(fp);
fp = 0;
printmsg("File <%s> partially received; last data was:",ptr2);
oldpkt[len] = 0;
printf("\r \"%s\". ",oldpkt);
}
return;
} /* end of reclose() */
recsw(ist,ipkt) /* Receive files. */
int ist; /* initial state */
char ipkt; /* initial packet-type */
{
fp = 0;
numtry = 0;
state = ist;
forever {
if (list > 2) {
outc(CR);
printf("Dbg: recsw() state: %c",state);
}
errdisp();
if (abtflag != 0) {
recfail();
reclose();
return(FALSE);
} /* catch user aborts during spack() */
switch(state) {
/* special initial states (message already in packet[]):- */
case RMH: /* send command and display */
case RMSV: /* anything sent back */
case GET: /* get files */
spack(ipkt,n,strlen(packet),packet);
state = rinit();
break;
/* normal staes during reception:- */
case 'R':
state = rinit();
break; /* Receive-Init */
case 'F':
state = rfile();
break; /* Receive-File */
case 'D':
state = rdata();
break; /* Receive-Data */
case 'C':
reclose();
return(TRUE); /* Complete state */
case 'A':
reclose();
return(FALSE); /* "Abort" state */
} }
} /* end of recsw() */
char rfile() /* Receive File Header */
{
char disk, *ptr1;
int num;
if (numtry++ > MAXTRY)
return('A');
switch(rpack(&len,&num,recpkt)) {
case 'S': /* Send-Init, maybe our ACK lost */
if (oldtry++ > MAXTRY)
return('A');
if (num == ((n==0) ? 63:n-1)) { /* Previous packet? */
len = spar(packet);
spack('Y',num,len,packet);
numtry = 0;
return(state);
}
else return('A'); /* Not previous packet, "abort" */
case 'Z': /* End-Of-File */
if (oldtry++ > MAXTRY) return('A');
if (num == ((n==0) ? 63:n-1)) { /* Previous packet? */
spack('Y',num,0,0);
numtry = 0;
return(state);
}
else return('A'); /* Not previous packet, "abort" */
case 'F': /* File Header */
if (num != n)
return('A');
vtline(LOCFILE,filblank);
ptr2 = fname + 2; /* leave room for disk-letter */
cpmunge(len,ptr2,recpkt); /* validate file name received */
if (filecount) { /* if override name or disk */
disk = 0;
ptr1 = *filelist;
if (*(ptr1+1) == ':') { /* if disk-letter present */
disk = *ptr1;
ptr1 += 2; /* up to start of filename */
}
if (*ptr1 != 0) { /* if filename present */
cpmunge(strlen(ptr1),ptr2,ptr1);
--filecount; /* substitute for name received */
++filelist; /* & advance parm-counters */
}
if (disk != 0) { /* if disk-letter specified */
*(--ptr2) = ':'; /* put it into fname */
*(--ptr2) = disk; /* in front of filename */
} } /* end if, if */
/* fname[] now contains correct validated name, including any disk-letter,
and ptr2 => either its beginning or third char. */
vtline(LOCFILE,ptr2);
s4sleep();
if ( (ptr1 = avoid(ptr2)) != 0 ) {
error(ptr1,ptr2);
return('A');
}
if ((fp=kwopen(ptr2))==NULL) {
error("Cant create <%s> - cancelled",ptr2);
return('A');
}
else
printmsg("Receiving <%s> as <%s>\r",recpkt,ptr2);
spack('Y',n,0,0);
inctry(); /* ++n%64 & mod tries */
return('D'); /* Switch to Data state */
case 'Y': /* short reply */
recpkt[*len] = 0;
printmsg("%s\r%s", mainsays,recpkt);
return('C');
case 'X': /* long reply */
vtline(LOCFILE,mainsays);
printmsg("%s\r",mainsays);
spack('Y',n,0,0);
inctry();
return('D');
case 'B': /* Break transmission (EOT) */
if (num != n)
return ('A');
spack('Y',n,0,0);
return('C'); /* Go to complete state */
case 'E': /* Error packet received */
prerrpkt(recpkt);
return('A');
case 'A': /* user aborted transfer */
return('A');
case FALSE: /* Didn't get packet */
if (list != 1)
txtout(trying);
spack('N',n,0,0);
return(state);
default: /* Some other type, abort */
error(badmsg,'F',type);
return('A');
}
} /* end of rfile() */
char rinit() /* Receive Initialization */
{
int num;
/* unlimited retries in this state */
switch(rpack(&len,&num,recpkt))
{
case 'S': /* Send-Init */
n = num; /* accept their number */
rpar(recpkt,len);
len = spar(packet);
spack('Y',n,len,packet);
compmode();
inctry(); /* ++n%64 & mod tries */
return('F');
case 'I': /* Info-exchange */
rpar(recpkt,len);
len = spar(packet);
spack('Y',n,len,packet);
compmode();
return('R');
case 'Y': /* short reply */
recpkt[*len] = 0;
printmsg("%s\r%s", mainsays,recpkt);
return('C');
case 'X': /* long reply */
vtline(LOCFILE,mainsays);
printmsg("%s\r",mainsays);
n = num;
spack('Y',n,0,0);
inctry();
return('D');
case 'E': /* Error packet received */
prerrpkt(recpkt);
case 'N': /* NAK */
return('A');
case 'A': /* User abort */
return('A');
case FALSE: /* Didn't get packet */
if (list != 1)
txtout(trying);
if (state == 'R') /* normal receive */
spack('N',n,0,0);
return(state);
default: /* Some other type, abort */
error(badmsg,'S',type);
return('A');
}
} /* end of rinit() */
/************ END of file KREC.C ***************************/