/* pe7pta.c */ /* Include external declarations */ #include "pe7inc.h" /* * g i n i t * * Get receive Initialization * */ TEXT ginit(l, file) int l; /* Length of the filename */ TEXT *file; /* File name pointer */ { int len, num, slen; /* Packet length, number */ if (numtry++ > MAXTRY) return ('A'); /* If too many tries, "abort" */ flushinput(); /* Clear out the i/o channel */ spack('R',n,l,file); /* Send the requested file name */ switch(rpack(&len,&num,recpkt)) /* Get a packet */ { case 'S': /* Send-Init packet */ if ( n != num) { case 'N': case FALSE: nxi++; return (state); } if (!rpar(recpkt,&len)) /* Get the other side's init data */ return ('A'); /* error with the packet parameters */ slen = spar(packet0); /* Fill up packet with my init info */ spack('Y',n,slen,packet0);/* ACK with my parameters */ oldtry = numtry; /* Save old try count */ nxtpkt(); return ('F'); /* Enter File-Receive state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ default: return ('A'); /* Some other packet type, "abort" */ } } /* * x i n i t * * Server command scanning */ TEXT xinit() { int i, /* A counter */ search, /* Filename search state flag */ len, num, slen; /* Packet length, number */ TEXT *filep; /* Pointer to input buffer */ switch(rpack(&len,&num,recpkt)) /* Get a packet */ { case 'S': /* Send-Init packet */ if (!rpar(recpkt,&len)) /* Get the other side's init data */ return ('A'); /* error with the packet parameters */ slen = spar(packet0); /* Fill up packet with my init info */ spack('Y',n,slen,packet0); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ nxtpkt(); return ('F'); /* Enter File-Receive state */ case 'I': /* Send-Init packet */ if (!rpar(recpkt,&len)) /* Get the other side's init data */ return ('A'); /* error with the packet parameters */ slen = spar(packet0); /* Fill up packet with my init info */ spack('Y',n,slen,packet0); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ n = 0; numtry = 0; return (state); /* Say we got our parameters */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return ('A'); /* abort */ case FALSE: /* Didn't get packet */ nxi++; spack('N',n,0,0); /* Return a NAK */ case 'N': return (state); /* Keep trying */ case 'R': /* copy the packet data into a filename_buffer */ /* cpystr(&filename_buffer, &recpkt, NULL); /* */ btobemp(filename_buffer, recpkt, MAXPACKSIZ); /* Uncode packet */ filecount = 0; filelist = &files; filep = &filename_buffer; search = 2; while (*filep != NULL && filecount < 10) { switch (search) { case 1: /* Looking for next filename */ if (iswhite(*filep)) break; search = 2; case 2: /* Looking for filename */ if (iswhite(*filep)) break; files[filecount++] = filep; search = 3; case 3: /* Looking for end of filename */ if (!iswhite(*filep)) break; *filep = NULL; search = 1; } filep++; } if (debug) printf("Xinit 1: Request for %d files...\n", filecount); if (gnxtfl() == FALSE) /* Any files to send? */ return ('B'); /* if not, break, EOT, all done */ return ('S'); /* Start sending files, switch state to S */ case 'G': if (recpkt[0] == 'F') { spack('Y',n,0,0); /* say ok */ return ('G'); } else { error("Invalid server command"); return (state); /* keep trying */ } default: error("Unknown packet type"); return (state); } } /* * s f i l e * * Send File Header. */ TEXT sfile() { TEXT filnam1[MAXFNAME], /* Converted file name */ *newfilnam, /* Pointer to file name to send */ *cp; /* char pointer */ int num, len; /* Packet number, length */ ULONG time(); if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */ if (fd == NULL) /* If not already open, */ { if (debug) printf("Sfile 1: Opening %s for sending.\n",filnam); /* Open file to be sent */ if ((fd = fopen(&pfio, filnam, READ)) == NULL) /* If bad file pointer, give up */ { printmsg("Cannot open file %s\n",filnam); return ('A'); } /* cpystr(filnam1, filnam, NULL); /* Copy file name */ btobemp(filnam1, filnam, MAXFNAME); /* Copy file name */ newfilnam = cp = filnam1; while (*cp != '\0') /* Strip off all leading directory */ if (*cp++ == '/') /* names (ie. up to the last /). */ newfilnam = cp; if (filnamcnv) /* Convert lower case to upper */ for (cp = newfilnam; *cp != '\0'; cp++) *cp = toupper(*cp); len = cp - newfilnam; /* Compute length of new filename */ if (vflg) printmsg("Sending %s as %s",filnam,newfilnam); } dostat(2); spack('F',n,len,newfilnam); /* Send an F packet */ switch(rpack(&len,&num,recpkt)) /* What was the reply? */ { case 'N': /* NAK, just stay in this state, */ num = (--num<0 ? 63 : num);/* unless it's NAK for next packet */ case 'Y': if (n != num) /* which is just like an ACK for */ { /* Wrong packet number */ case FALSE: /* Receive failure, stay in F state */ nxi++; return (state); } nxtpkt(); dostat(4); repeat_count = 0; /* Reset repeat character counter */ empty[1-pknum] = 0; /* Make other buffer empty */ if ((empty[pknum] = size[pknum] = bufill (packet[pknum])) != EOF) return ('E'); /* Switch to data state */ return ('Z'); /* Must be end of file */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ default: return ('A'); /* Something else, just "abort" */ } } /* * r f i l e * * Receive File Header */ TEXT rfile() { TEXT filnam1[MAXFNAME]; /* Holds the converted file name */ int num, len, slen; /* Packet number, length */ int dum; /* Holds array pointer */ ULONG time(); if (numtry++ > MAXTRY) return ('A'); /* "abort" if too many tries */ dostat(2); switch(rpack(&len,&num,recpkt)) /* Get a packet */ { case 'S': /* Send-Init, maybe our ACK lost */ if (oldtry++ > MAXTRY) return ('A'); /* If too many tries "abort" */ if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again with */ slen = spar(packet0);/* our Send-Init parameters */ spack('Y',num,slen,packet0); numtry = 0; /* Reset try counter */ return (state); /* Stay in this 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, mod 64? */ { /* Yes, ACK it again. */ spack('Y',num,0,0); numtry = 0; return (state); /* Stay in this state */ } else return ('A'); /* Not previous packet, "abort" */ case 'F': /* File Header (just what we want) */ if (num != n) return ('A');/* The packet number must be right */ /* cpystr(filnam1, recpkt, NULL); /* Copy the file name */ btobemp(filnam1, recpkt, MAXFNAME); /* Copy the file name */ if (filnamcnv) /* Convert upper case to lower */ for (filnam=filnam1; *filnam != '\0'; filnam++) *filnam = tolower(*filnam); /* Create the file for writing into */ if ((fd = fcreate(&pfio, filnam1, WRITE)) == NULL) { error("Cannot create %s",filnam1); /* Give up if can't */ return ('A'); } if (vflg) printmsg("Receiving %s as %s",recpkt,filnam1); spack('Y',n,0,0); /* Acknowledge the file header */ oldtry = numtry; /* Reset try counters */ nxtpkt(); dostat(4); return ('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) return ('A'); /* Need right packet number here */ spack('Y',n,0,0); /* Say OK */ return ('C'); /* Go to complete state */ case FALSE: /* Didn't get packet */ nxi++; spack('N',n,0,0); /* Return a NAK */ return (state); /* Keep trying */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ default: return ('A'); /* Some other packet, "abort" */ } } /* * Checksum computations * * chk1 - Compute a type 1 Kermit 6 bit checksum * chk2 - Compute a type 2 Kermit block check * chk3 - Compute a type 3 Kermit block check * */ chk1(packet) char *packet; { int checksum; checksum = chk2(packet); return ((((checksum & 0300) >> 6) + checksum) & 077); } chk2(packet) char *packet; { ULONG checksum; for (checksum = 0; *packet != '\0' ; packet++) checksum += pflg ? *packet & 0177 : *packet; return (checksum); } chk3(packet) char *packet; { int c, checksum, q; checksum = 0; while ((c = pflg ? *packet & 0177 : *packet) != '\0') { q = (checksum ^ c) & 017; /* Low order nibble */ checksum = (checksum >> 4) ^ (q * 010201); q = (checksum ^ (c >> 4)) & 017; /* High order nibble */ checksum = (checksum >> 4) ^ (q * 010201); packet++; } return (checksum); } /* * s p a r * * Fill the data array with my send-init parameters * */ spar(data) TEXT data[]; { int len; data[0] = tochar(MAXPACKSIZ);/* Biggest packet I can receive */ data[1] = tochar(MYTIME); /* When I want to be timed out */ data[2] = tochar(MYPAD); /* How much padding I need */ data[3] = ctl(MYPCHAR); /* Padding character I want */ data[4] = tochar(MYEOL); /* End-Of-Line character I want */ data[5] = MYQUOTE; /* Control-Quote character I send */ if (state == 'S') { /* Set up the startup parameters */ /* The other side may call the shots if we are a server */ data[6] = sqbin = image ? pflg ? MYQBIN : DEFQBIN : 'N'; data[7] = DEFCHKT; /* I will use this check sum */ data[8] = DEFREPT; /* This is my repeat character */ data[9] = tochar(NULL); /* No bit mask at this time */ data[10] = tochar(NULL); data[11] = tochar(NULL); data[12] = tochar(NULL); data[13] = tochar(NULL); /* Tell the other side what we set up in the start */ data[14] = image ? tochar( 1 ) : tochar ( NULL ); data[15] = pflg ? pflg : tochar(NULL); len = 16; } else /* Receive flag must be on. We are not the starters */ { data[6] = rqbin; /* Quote character both sides will use */ data[7] = chkt; /* Checksum type */ data[8] = rrept; /* Set My repeat character */ data[9] = tochar(NULL); /* No bit mask at this time */ len = 10; } if (debug > 1) { printf("Spar: spsiz=%d, timint=%d\n", spsiz, timint); printf(" pad=%d, padchar=%d, eol=%d, ", pad, padchar, eol); printf("quote=%d, qbin=%d, chkt=%d, ", quote, qbin, chkt); printf("rept=%d\n", rept); if (len > 10) printf(" image= %d, pflg= %c, iflg= %d, spflg= %c\n", image,pflg,iflg,spflg); } return ( len ); } /* r p a r * * Get the other host's send-init parameters * */ rpar(data,len) TEXT data[]; int *len; { TEXT chkchar(); /* Maximum send packet size */ spsiz = *len < 1 ? DEFPACKSIZ : unchar(data[0]); /* When I should time out */ timint = *len < 2 ? MYTIME : unchar(data[1]); /* Number of pads to send */ pad = *len < 3 ? 0 : unchar(data[2]); /* Padding character to send */ padchar = dopar(*len < 4 ? NULL : ctl(data[3])); /* EOL character I must send */ eol = *len < 5 ? CR : unchar(data[4]); /* Incoming data quote character */ quote = *len < 6 ? '#' : data[5]; /* Force to a type one check sum */ chkt = *len < 8 ? DEFCHKT : data[7] != MYCHKT ? DEFCHKT : MYCHKT; /* Set up the multi repeat char */ rrept = *len < 9 ? ' ' : data[8]; if (state != 'S') { /* Determine the state of image and parity flags from the other side */ image = *len < 15 ? iflg : data[14] == SP ? FALSE : TRUE; pflg = *len < 16 ? spflg : data[15] == SP ? FALSE : data[15]; /* Determine the state of the sqbin */ sqbin = image ? pflg ? MYQBIN : DEFQBIN : 'N'; /* Determine the quoting mode we will use based on what the other side * allows and what we are capable of */ rqbin = *len < 7 ? 'N' : data[6] == DEFQBIN ? sqbin : data[6]; qbin = chkchar(rqbin); /* Determine the repeat mode based on what the other side allows */ rept = chkchar(rrept); } else { /* Determine the final quoting mode based on what the other side allows */ rqbin = *len < 7 ? 'N' : data[6]; qbin = sqbin == DEFQBIN ? chkchar(rqbin) : rqbin == MYQBIN ? MYQBIN : FALSE; /* Determine the final repeat mode based on what the other side allows */ rept = rrept == DEFREPT ? rrept : FALSE; } /* Force 8 bit quoting if requested and we are not generating parity */ if (qbin && !pflg) pflg = 'n'; /* Maybe we can not do image because the other end can not support binary quote */ if (image && rqbin == 'N') { error("Binary file transfer not supported"); return (FALSE); } if (debug > 1) { printf("Rpar: spsiz=%d, timint=%d\n", spsiz, timint); printf(" pad=%d, padchar=%d, eol=%d, ", pad, padchar, eol); printf("quote=%d, qbin=%d, chkt=%d, ", quote, qbin, chkt); printf("rept=%d\n", rept); if (*len > 14 ) printf(" image=%d, pflg=%c\n",image,pflg); } return (TRUE); } /* * b u f i l l * * Get a bufferful of data from the file that's being sent. * */ bufill(buffer) TEXT buffer[]; /* Buffer */ { int i; /* Loop index */ METACH t; /* Character that may be output */ static METACH tt {0}; /* For the comparisions of the repeat count */ i = 0; /* Init data buffer pointer */ while ((t = getc(&pfio)) != EOF) /* fetch till end */ { file.fc++; if (rept) /* If rept set then true */ { if (repeat_count) /* If r..c.. set then true */ { /* Check for repeat character and not too many of them */ if ((tt == t) && (++repeat_count < 95)) continue; /* The characters were different or we ran out of repeat count */ if (repeat_count > 3) /* Output repeat string */ { buffer[i++] = rept; if (repeat_count >= 95) repeat_count = 94; buffer[i++] = tochar(repeat_count); repeat_count = 1; /* Set for next */ } for (; repeat_count ; repeat_count -= 1) store_in_buffer(tt, buffer, &i); /* We have output the repeat count and the repeat character */ } /* End of repeat_count test */ tt = t; /* Set up temps for next character */ repeat_count = 1; } /* End of non NULL rept */ else /* rept = 0 */ store_in_buffer(t, buffer, &i); if (i >= spsiz-SPOVER) return (i); /* Check length */ } /* End of while loop */ /* Test if there is an repeat count outstanding. It could be that we have not inserted any data into output buffer */ if (repeat_count > 3) { buffer[i++] = rept; buffer[i++] = tochar(repeat_count); repeat_count = 1; /* Set for next */ } for (; repeat_count ; --repeat_count) store_in_buffer(tt, buffer, &i); if (i==0) return (EOF); /* Wind up here only on EOF */ /* We need to split the packet. Scan backwards for a natural * break, and then send of the packet. When we return point * to the data and move to the front the rest and fetch more * more data. */ /* Natural breaks are the quote character, repeat character * and the binary character */ return (i); /* Handle partial buffer */ } /* * b u f e m p * * Put data from an incoming packet into a file. * */ bufemp(buffer,len) register TEXT buffer[]; /* Buffer */ int len; /* Length */ { register int i; /* Counter for number of characters */ int ri; /* Repeat counter for repeated characters */ TEXT t, t7, tm; /* Character holders */ for (i = 0; i < len; i++) /* Loop thru the data field */ { tm = 0; /* Preset for next */ t = buffer[i]; /* Get character */ ri = 1; /* Set repeat count to one (do at least one) */ /* At this point we check for a repeat character * if the rept char is set then the condition will be tested * else we can not get here since the character t may * not be a NULL */ if (t == rept) /* Repeated character? */ { ri = unchar(buffer[++i]); /* Fetch repeat count */ t = buffer[++i]; /* Fetch next character */ } if (t == qbin) /* Next character have high bit on? */ { tm = 0200; /* Set mask to high bit on */ t = buffer[++i];/* Fetch next character */ } if (t == quote) /* Control quote? */ { /* Yes */ t = buffer[++i]; /* Get the quoted character */ t7 = t & 0177; /* make a match character */ if (t7 != quote && t7 != rept && t7 != qbin) /* Low bits match quote, rept or qbin? */ t = ctl(t); /* No, uncontrollify it */ } if (t==CR && !image) /* Pass CR if in image mode */ continue; t |= tm; for (; ri ; --ri) /* We put at least one character away */ { putc(&pfio, t); file.fc++; } } } /* * b t o b e m p * * Put data from an incoming packet into a buffer. * */ btobemp(bout,buffer,len) register TEXT buffer[]; /* Buffer */ register TEXT bout[]; /* Output Buffer */ int len; /* Length */ { register int i; /* Counter for number of characters */ register int j; /* Output buffer counter */ int ri; /* Repeat counter for repeated characters */ TEXT t, t7, tm; /* Character holders */ j = 0; /* Initialize output buffer pointer */ if(debug) printf("[btobemp] buffer=>>>%s<<<\n",buffer); /* for (i = 0; i < len; i++) /* Loop thru the data field */ for (i = 0; buffer[i] != '\0'; i++) /* Loop thru the data field */ { tm = 0; /* Preset for next */ t = buffer[i]; /* Get character */ ri = 1; /* Set repeat count to one (do at least one) */ /* At this point we check for a repeat character * if the rept char is set then the condition will be tested * else we can not get here since the character t may * not be a NULL */ if (t == rept) /* Repeated character? */ { ri = unchar(buffer[++i]); /* Fetch repeat count */ t = buffer[++i]; /* Fetch next character */ } if (t == qbin) /* Next character have high bit on? */ { tm = 0200; /* Set mask to high bit on */ t = buffer[++i];/* Fetch next character */ } if (t == quote) /* Control quote? */ { /* Yes */ t = buffer[++i]; /* Get the quoted character */ t7 = t & 0177; /* make a match character */ if (t7 != quote && t7 != rept && t7 != qbin) /* Low bits match quote, rept or qbin? */ t = ctl(t); /* No, uncontrollify it */ } if (t==CR && !image) /* Pass CR if in image mode */ continue; t |= tm; for (; ri ; --ri) /* We put at least one character away */ { if( j >= (len) ) { printf("Kermit: [btobemp] Expanded packet overflows buffer\ \n j=%d MAXFNAME=%d\n",j,(MAXFNAME)); error("Kermit: [btobemp] Expanded packet overflows buffer\n"); break; } bout[j] = t; j++; } } if( j < len ) bout[j] = '\0'; } /* * s t o r e _ i n _ b u f f e r * * This routine stores the character into the output buffer * */ store_in_buffer(t, buffer, i) TEXT t; register TEXT buffer[]; register int *i; { TEXT t7,tm; t7 = t & 0177; /* Strip high bit */ if (t7 == '\n' && !image) { /* Do LF->CRLF mapping if !image */ buffer[(*i)++] = MYQUOTE; buffer[(*i)++] = ctl('\r'); } if (qbin != 0 && (pflg ? t & 0200 : 0) != 0) /* Binary quote on? */ buffer[(*i)++] = MYQBIN; /* Output a flag char */ /* Does this character need special handling? */ if (t7 < SP || t7 == DEL) { /* Yes this character need some changes */ buffer[(*i)++] = MYQUOTE; /* Quote the character */ t7 = ctl(t7); /* and uncontrolify */ t = ctl(t); } else /* it is not a special character */ { if (t7 == MYQUOTE || t7 == rept || t7 == qbin) buffer[(*i)++] = MYQUOTE; /* Quote the character */ } buffer[(*i)++] = pflg ? t7 : t; } /* pe7pta.c End-of-file */