📄 ckcfns.c
字号:
} /* else */ /* else means don't display */#endif /* NOSPL */ conoc(c); return(0);}int /* Output char to file. */#ifdef CK_ANSICputfil(char c)#elseputfil(c) register char c;#endif /* CK_ANSIC *//* putfil */ { if (zchout(ZOFILE, (char) (c & fmask)) < 0) { czseen = 1; /* If write error... */ debug(F101,"putfil zchout write error, setting czseen","",1); return(-1); } return(0);}/* D E C O D E -- Kermit packet decoding procedure *//* Call with string to be decoded and an output function. Returns 0 on success, -1 on failure (e.g. disk full). This is the "inner loop" when receiving files, and must be coded as efficiently as possible. Note some potential problems: if a packet is badly formed, having a prefixed sequence ending prematurely, this function, as coded, could read past the end of the packet. This has never happened, thus the additional (time-consuming) tests have not been added.*/static CHAR *xdbuf; /* Global version of decode()'s buffer pointer */ /* for use by translation functions. *//* Function for pushing a character onto decode()'s input stream. */VOID#ifdef CK_ANSICzdstuff(CHAR c)#elsezdstuff(c) CHAR c;#endif /* CK_ANSIC *//* zdstuff */ { xdbuf--; /* Back up the pointer. */ *xdbuf = c; /* Stuff the character. */}int#ifdef CK_ANSICdecode(CHAR *buf, int (*fn)(char), int xlate)#elsedecode(buf,fn,xlate) register CHAR *buf; register int (*fn)(); int xlate;#endif /* CK_ANSIC *//* decode */ { register unsigned int a, a7, a8, b8; /* Various copies of current char */ int t; /* Int version of character */ int ssflg; /* Character was single-shifted */ int ccpflg; /* For Ctrl-unprefixing stats */ long z; CHAR c;/* Catch the case in which we are asked to decode into a file that is not open, for example, if the user interrupted the transfer, but the other Kermit keeps sending.*/ if ((cxseen || czseen || discard) && (fn == putfil)) return(0); xdbuf = buf; /* Make global copy of pointer. */ rpt = 0; /* Initialize repeat count. */ while ((a = *xdbuf++ & 0xFF) != '\0') { /* Get next character. */ if (a == rptq && rptflg) { /* Got a repeat prefix? */ rpt = xunchar(*xdbuf++ & 0xFF); /* Yes, get the repeat count, */ rptn += rpt; a = *xdbuf++ & 0xFF; /* and get the prefixed character. */ } b8 = lsstate ? 0200 : 0; /* 8th-bit value from SHIFT-STATE */ if (ebqflg && a == ebq) { /* Have 8th-bit prefix? */ b8 ^= 0200; /* Yes, invert the 8th bit's value, */ ssflg = 1; /* remember we did this, */ a = *xdbuf++ & 0xFF; /* and get the prefixed character. */ } else ssflg = 0; ccpflg = 0; if (a == ctlq) { /* If control prefix, */ a = *xdbuf++ & 0xFF; /* get its operand */ a7 = a & 0x7F; /* and its low 7 bits. */ if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') { /* Controllify */ a = ctl(a); /* if in control range. */ a7 = a & 0x7F; ccpflg = 1; /* Note that we did this */ ccp++; /* Count for stats */ } } else a7 = a & 0x7f; /* Not control quote */ if (a7 < 32 || a7 == 127) { /* Control character? */ if (!ccpflg) ccu++; /* A bare one, count it */ if (lscapu) { /* If doing locking shifts... */ if (lsstate) /* If SHIFTED */ a8 = (a & ~b8) & 0xFF; /* Invert meaning of 8th bit */ else /* otherwise */ a8 = a | b8; /* OR in 8th bit */ /* If we're not in a quoted sequence */ if (!lsquote && (!lsstate || !ssflg)) { if (a8 == DLE) { /* Check for DLE quote */ lsquote = 1; /* prefixed by single shift! */ continue; } else if (a8 == SO) { /* Check for Shift-Out */ lsstate = 1; /* SHIFT-STATE = SHIFTED */ continue; } else if (a8 == SI) { /* or Shift-In */ lsstate = 0; /* SHIFT-STATE = UNSHIFTED */ continue; } } else lsquote = 0; } } a |= b8; /* OR in the 8th bit */ if (rpt == 0) rpt = 1; /* If no repeats, then one */ if (!binary) { /* If in text mode, */ if (feol && a == CR) continue; /* Convert CRLF to newline char */ if (feol && a == LF) a = feol;#ifndef NOCSETS /* Character-set translation */#ifdef KANJI /* For Kanji transfers, */ if (tcharset != TC_JEUC) /* postpone translation. */#endif /* KANJI */ if (xlate && rx) a = (*rx)((CHAR) a); /* Translate charset */#endif /* NOCSETS */ } if (fn == putfil) { /* (PWP) speedup via buffered output and a macro */ for (; rpt > 0; rpt--) { /* Output the char RPT times */#ifndef NOCSETS#ifdef KANJI if (!binary && tcharset == TC_JEUC && fcharset != FC_JEUC) { /* Translating from J-EUC */ if (ffc == 0L) xkanjf(); if (xkanji(a,fn) < 0) /* to something else? */ return(-1); else t = 1; } else#endif /* KANJI */#endif /* NOCSETS */#ifdef OS2 if (xflg && !remfile) { /* Write to virtual screen */ char _a; _a = a & fmask; t = conoc(_a); if (t < 1) t = -1; } else#endif /* OS2 */ t = zmchout(a & fmask); /* zmchout is a macro */ if (t < 0) { debug(F101,"decode _write error - errno","",errno); return(-1); }#ifdef COMMENT if (ffc == 0 && filcnt <= 1) { debug(F101,"decode new file, filcnt","",filcnt); debug(F101,"decode crc16","",crc16); crc16 = 0L; /* Should already have been done */ }#endif /* COMMENT */ ffc++; /* Count the character */ if (docrc && !xflg && !remfile) { /* Update file CRC */ c = a; /* Force conversion to unsigned char */ z = crc16 ^ (long)c; crc16 = (crc16 >> 8) ^ (crcta[(z & 0xF0) >> 4] ^ crctb[z & 0x0F]); } } } else { /* Output to something else. */ a &= fmask; /* Apply file mask */ for (; rpt > 0; rpt--) { /* Output the char RPT times */ if ((*fn)((char) a) < 0) return(-1); /* Send to output func. */#ifdef COMMENT/* This was causing the server to count extra bytes that were part of server command packets, like FINISH.*/ ffc++;#endif /* COMMENT */ } } } return(0);}/* G E T P K T -- Fill a packet data field *//* Gets characters from the current source -- file or memory string. Encodes the data into the packet, filling the packet optimally. Set first = 1 when calling for the first time on a given input stream (string or file). Call with: bufmax -- current send-packet size xlate -- flag: 0 to skip character-set translation, 1 to translate Uses global variables: t -- current character. first -- flag: 1 to start up, 0 for input in progress, -1 for EOF. next -- next character (not used any more). data -- pointer to the packet data buffer. size -- number of characters in the data buffer. memstr - flag that input is coming from a memory string instead of a file. memptr - pointer to string in memory. (*sx)() character set translation functionReturns the size as value of the function, and also sets global "size",and fills (and null-terminates) the global data array. Returns 0 upon eof.Rewritten by Paul W. Placeway (PWP) of Ohio State University, March 1989.Incorporates old getchx() and encode() inline to reduce function calls,uses buffered input for much-improved efficiency, and clears up someconfusion with line termination (CRLF vs LF vs CR).Rewritten again by Frank da Cruz to incorporate locking shift mechanism,May 1991.*//* Lookahead function to decide whether locking shift is worth it. Looks at the next four input characters to see if all of their 8th bits match the argument. Call with 0 or 0200. Returns 1 if so, 0 if not. If we don't happen to have at least 4 more characters waiting in the input buffer, returns 1. Note that zinptr points two characters ahead of the current character because of repeat-count lookahead.*/#ifdef KANJIintkgetf(#ifdef CK_ANSIC VOID#endif /* CK_ANSIC */ ) { if (funcstr) return((*funcptr)()); else return(zminchar());}intkgetm(#ifdef CK_ANSIC VOID#endif /* CK_ANSIC */ ) { int x; if (x = *memptr++) return(x); else return(-1);}#endif /* KANJI */intlslook(b) unsigned int b; { /* Locking Shift Lookahead */ int i; if (zincnt < 3) /* If not enough chars in buffer, */ return(1); /* force shift-state switch. */ b &= 0200; /* Force argument to proper form. */ for (i = -1; i < 3; i++) /* Look at next 5 characters to */ if (((*(zinptr+i)) & 0200) != b) /* see if all their 8th bits match. */ return(0); /* They don't. */ return(1); /* They do. */}intgetpkt(bufmax,xlate) int bufmax, xlate; { /* Fill one packet buffer */ register CHAR rt = t, rnext; /* Register shadows of the globals */ register CHAR *dp, *odp, *odp2, *p1, *p2; /* pointers... */ register int x; /* Loop index. */ register int a7; /* Low 7 bits of character */ static CHAR leftover[9] = { '\0','\0','\0','\0','\0','\0','\0','\0','\0' }; CHAR xxls, xxdl, xxrc, xxss, xxcq; /* Pieces of prefixed sequence */ int n; /* worker */ long z; /* A long worker (for CRC) *//* Assume bufmax is the receiver's total receive-packet buffer length. Our whole packet has to fit into it, so we adjust the data field length. We also decide optimally whether it is better to use a short-format or long-format packet when we're near the borderline.*/ n = bufmax - 5; /* Space for Data and Checksum */ if (n > 92 && n < 96) n = 92; /* "Short" Long packets don't pay */ if (n > 92 && lpcapu == 0) /* If long packets needed, */ n = 92; /* make sure they've been negotiated */ bufmax = n - bctl; /* Space for data */ if (n > 92) bufmax -= 3; /* Long packet needs header chksum */ if (first == 1) { /* If first character of this file... */ if (!memstr && ! funcstr) /* and real file... */ ffc = 0L; /* reset file character counter */ first = 0; /* Next character won't be first */ *leftover = '\0'; /* Discard any interrupted leftovers */ /* get first character of file into rt, watching out for null file */#ifndef NOCSETS#ifdef KANJI if (!binary && tcharset == TC_JEUC && xlate) { x = zkanjf(); if ((x = zkanji(memstr ? kgetm : kgetf)) < 0) { first = -1; size = 0; if (x == -2) { debug(F100,"getpkt(zkanji): input error","",0); cxseen = 1; } else debug(F100,"getpkt(zkanji): empty string/file","",0); return (0); } rt = x; if (!memstr) { ffc++; if (docrc && what == W_SEND) { /* Accumulate file crc */ z = crc16 ^ (long)rt; crc16 = (crc16 >> 8) ^ (crcta[(z & 0xF0) >> 4] ^ crctb[z & 0x0F]); } } } else {#endif /* KANJI */#endif /* not NOCSETS */ if (memstr) { /* Reading data from memory string */ if ((rt = *memptr++) == '\0') { /* end of string ==> EOF */ first = -1; size = 0; debug(F100,"getpkt: empty string","",0); return (0); } } else if (funcstr) { /* Reading data from a function */ if ((x = (*funcptr)()) < 0) { /* End of input */ first = -1; size = 0; debug(F100,"getpkt: empty input function","",0); /* Empty */ return(0); } ffc++; /* Count a file character */ rt = (CHAR) x; /* Convert int to char */ debug(F101,"getpkt funcstr","",rt); } else { /* Reading data from a file */ if ((x = zminchar()) < 0) { /* End of file or input error */ first = -1; size = 0; if (x == -2) { /* Error */ debug(F100,"getpkt: input error","",0); cxseen = 1; /* Interrupt the file transfer */ } else { debug(F100,"getpkt empty file","",0); } return(0); } ffc++; /* Count a file character */ rt = (CHAR) x; /* Convert int to char */ debug(F101,"getpkt 1st char","",rt); if (docrc && what == W_SEND) { /* Accumulate file crc */ z = crc16 ^ (long)rt; crc16 = (crc16 >> 8) ^ (crcta[(z & 0xF0) >> 4] ^ crctb[z & 0x0F]); } }#ifndef NOCSETS#ifdef KANJI }#endif /* KANJI */#endif /* not NOCSETS */ rt &= fmask; /* Apply SET FILE BYTESIZE mask */ debug(F101,"getpkt fmask","",fmask); debug(F101,"getpkt new rt","",rt);#ifndef NOCSETS if (xlate) { debug(F101,"getpkt about to call translate function","",rt); debug(F101,"tcharset","",tcharset); debug(F101,"fcharset","",fcharset); }#ifdef KANJI if (tcharset != TC_JEUC)#endif /* KANJI */ if (!binary && sx && xlate) { rt = (*sx)(rt); /* Translate */ debug(F101," translate function returns","",rt); }#endif /* not NOCSETS */ /* PWP: handling of feol is done later (in the while loop)... */ } else if ((first == -1) && (*leftover == '\0')) { /* EOF from last time */ debug(F101,"getpkt eof crc16","",crc16); debug(F101,"getpkt eof ffc","",ffc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -