/* * astrec.c receive file routines for ATARI ST kermit */ #include #include #include "astobj.h" #include "astinc.h" extern FILE *fopen(),*fopenb(); /* * r e c s w * * This is the state table switcher for receiving files. */ recsw() { char rinit(), rfile(), rdata(); /* Use these procedures */ start_timer(&starttrans); state = 'R'; n = 0; /* Initialize message number */ numtry = 0; /* Say no tries yet */ /* * We are commenting out code that automatically NAKed * in case the sender started first; this may be the reason * that this Kermit gets out of whack. The original code * said * if (gflg == FALSE) * spack('N', n, 0, NIL); */ for (;;) { msgdeb(MSGDSTAT,state,n); bps = ((timer(starttrans) != 0) ? (bytecnt/timer(starttrans)) : 0); dt_packets(TRUE); switch(state) { /* Do until done */ case 'R': state = rinit(); break; /* Receive-Init */ case 'F': state = rfile(); break; /* Receive-File */ case 'D': state = rdata(); break; /* Receive-Data */ case 'C': return(TRUE); /* Complete state */ case 'A': spack('E', n, 5, "Abort"); return (FALSE); /* "Abort" */ case 'E': return(FALSE); /* "Error Abort" */ default: msgdeb(MSGSTATE); return (FALSE); /* Unknown, fail */ } } } /* * r i n i t * * Receive Initialization */ char rinit() { int i, len, num; /* Packet length, number */ char sfile(); /* routine used for get command */ if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A');}; ebq = TRUE; /* assume 7-bit transfer for init */ switch(rpack(&len, &num, packet)) { /* Get a packet */ case 'S': /* Send-Init */ for (i=len;i<10;i++) packet[i] = '\0'; rpar(packet); /* Get the other side's init data */ spar(packet); /* Fill up packet with my init info */ spack('Y', n, 7, packet); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ n_total++; return('F'); /* Enter File-Receive state */ case 'E': /* Error packet received */ prerrpkt(packet); /* Print it out and */ return('E'); /* abort */ case FALSE: /* Didn't get packet */ case 'N': /* or got a NAK */ nakcnt++; if (!getfile) spack('N', n, 0, NIL); /* Return a NAK */ else spack('R',n,strlen(filnam1),filnam1); return(state); /* Keep trying */ case 'Y': return(state); /* Ignore leftover ACK */ /* (or incorrect ACK of 'R' packet) */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return('A'); /* Some other packet type, "abort" */ } } /* * r f i l e * * Receive File Header */ char rfile() { int num, len; /* Packet number, length */ int f1x, fx; /* index to filnam1 and filnam */ int extx; /* start of extension */ int tryix; /* trying numbers for extension */ char convc; /* converted char in filename */ if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A');}; switch (rpack(&len, &num, packet)) { /* Get a packet */ case 'S': /* Send-Init, maybe our ACK lost */ nakcnt++; if (oldtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A');}; if (num != ((n == 0) ? 63 : n - 1)) {msgall(KRPROERR,MSGPROER); return('A'); /* Not previous packet, "abort" */ }; /* Previous packet, mod 64; ack with our */ /* Send-Init parameters */ spar(packet); spack('Y', num, 7, packet); numtry = 0; /* Reset try counter */ return(state); /* Stay in this state */ case 'Z': /* End-Of-File */ nakcnt++; if (oldtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A');}; if (num != ((n==0) ? 63:n-1)) {msgall(KRPROERR,MSGPROER); return('A'); /* Not previous packet, "abort" */ }; spack('Y',num,0,NIL); numtry = 0; return(state); /* Stay in this state */ case 'F': /* File Header (just what we want) */ if (num != n) {msgall(KRPROERR,MSGPROER); return('A'); /* The packet number must be right */ }; strcpy(filnam1, packet); /* Copy the file name */ /* convert filename to valid TOS file name*/ fx = 0; extx = -1; if (filnam[0] == '\0') {for (f1x = 0; filnam1[f1x] != '\0'; f1x++) {convc = filnam1[f1x]; if ((convc >= 'a') && (convc <= 'z')) convc ^= 040; if (convc == ' ') convc = '.'; if (!((convc == '.') || ((convc >= 'A') && (convc <= 'Z')) || ((convc >= '0') && (convc <= '9')))) convc = ']'; if (convc == '.') if (extx >= 0) convc = ']'; else extx = fx; if ((fx < 8) || ((extx >= 0) && ((fx - extx) < 4))) filnam[fx++] = convc; }; filnam[fx] = '\0'; if (filnamwarn) {tryix = 0; while ((!access(filnam,4)) && (tryix < 50)) {msgdeb(MSGERSNA,filnam1,filnam); if (extx < 0) {extx = fx; filnam[fx++] = '.'; filnam[fx] = '\0'; }; sprintf(&filnam[extx+1],"K%02d",tryix++); }; }; }; /* Try to open a new file */ if (image) fp = fopenb(filnam,"w"); else fp = fopen(filnam,"w"); if (fp == NULL) { msgall(KRWOPERR,MSGWOPER, filnam); return('A'); /* Give up */ } /* OK, give message */ msgall(-1,MSGFRASF, filnam1, filnam); dt_files(TRUE); spack('Y', n, 0, NIL); /* Acknowledge the file header */ n_total++; oldtry = numtry; /* Reset try counters */ numtry = 0; /* ... */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) {msgall(KRPROERR,MSGPROER); return ('A'); /* Need right packet number here */ }; spack('Y', n, 0, NIL); /* Say OK */ n_total++; return('C'); /* Go to complete state */ case 'E': /* Error packet received */ prerrpkt(packet); /* Print it out and */ return('E'); /* abort */ case FALSE: /* Didn't get packet */ spack('N', n, 0, NIL); /* Return a NAK */ nakcnt++; return(state); /* Keep trying */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return ('A'); /* Some other packet, "abort" */ } } /* * r d a t a * * Receive Data */ char rdata() { int num, len; /* Packet number, length */ if (numtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A');}; switch (rpack(&len, &num, packet)) { /* Get packet */ case 'D': /* Got Data packet */ if (num != n) { /* Right packet? */ /* No! */ if (num != ((n==0) ? 63:n-1)) /* not prev. packet */ {msgall(KRPROERR,MSGPROER); return('A'); }; if (oldtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A'); }; spack('Y', num, 0, NIL); /* Yes, re-ACK it */ nakcnt++; numtry = 0; /* Reset try counter */ return(state); /* Don't write data! */ } /* Got data with right packet number */ #ifdef nooverlap /* Cannot handle concurrent disk and serial i/o, so delay ACK */ /* until file written */ bufemp(packet, len); /* Write the data to the file */ spack('Y', n, 0, NIL); /* Acknowledge the packet */ #else /* ACK before file write to overlap disk and serial i/o */ spack('Y', n, 0, NIL); /* Acknowledge the packet */ bufemp(packet, len); /* Write the data to the file */ #endif oldtry = numtry; /* Reset the try counters */ numtry = 0; /* ... */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ n_total++; if (ferror(fp)) {msgall(KRFATFER,MSGFATFE); return('A'); }; return('D'); /* Remain in data state */ case 'F': /* Got a File Header */ if (num != ((n==0) ? 63:n-1)) /* not prev. packet */ {msgall(KRPROERR,MSGPROER); return('A'); }; if (oldtry++ > maxtry) {msgall(KRTRAERR,MSGTRAER); return('A'); }; spack('Y', num, 0, NIL); /* ACK it again */ nakcnt++; numtry = 0; /* Reset try counter */ return(state); /* Stay in Data state */ case 'Z': /* End-Of-File */ if (num != n) {msgall(KRPROERR,MSGPROER); return('A'); /* Must have right packet number */ }; if (ferror(fp)) {msgall(KRFATFER,MSGFATFE); return('A'); }; #ifdef nooverlap /* can't handle disk and serial i/o at the same time */ fclose(fp); /* close the file */ spack('Y', n, 0, NIL); /* Ack the 'Z' packet */ #else /* ACK before close to allow i/o overlap */ spack('Y', n, 0, NIL); /* OK, ACK it. */ fclose(fp); /* Close the file */ #endif n = (n + 1) % 64; /* Bump packet number */ msgall(-1,MSGTREOF,filnam); n_total++; filecnt++; dt_files(TRUE); filnam[0] = '\0'; return('F'); /* Go back to Receive File state */ case 'E': /* Error packet received */ prerrpkt(packet); /* Print it out and */ return('E'); /* abort */ case FALSE: /* Didn't get packet */ spack('N', n, 0, NIL); /* Return a NAK */ nakcnt++; return(state); /* Keep trying */ case 'A': return('A'); /* user abort */ default: msgall(KRPROERR,MSGPROER); return('A'); /* Some other packet, "abort" */ } }