/***********************************************************************/ /* 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 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 ***************************/