📄 ckcfns.c
字号:
} else if (eu.x_char[byteorder] == 0x8e) { /* Kana */ jx = 0; switch (jstate) { case 2: /* from Kanji */ jbuf[jx++] = 0x1b; /* ESC */ jbuf[jx++] = 0x28; /* ( */ jbuf[jx++] = 0x4a; /* J */ case 0: /* from Roman */ jbuf[jx++] = 0x0e; /* SO */ default: /* State is already Kana*/ jbuf[jx++] = (a & 0x7f); /* and the char */ break; } jstate = 1; /* New state is Katakana */ } else { /* Kanji */ jx = 0; switch (jstate) { case 1: /* Current state is Katakana */ jbuf[jx++] = 0x0f; /* SI */ case 0: /* Current state is Roman */ jbuf[jx++] = 0x1b; /* ESC */ jbuf[jx++] = 0x24; /* $ */ jbuf[jx++] = 0x42; /* B */ default: /* Current state is already Kanji */ jbuf[jx++] = eu.x_char[byteorder] & 0x7f; jbuf[jx++] = eu.x_char[1-byteorder] & 0x7f; break; } jstate = 2; /* Set state to Kanji */ } for (i = 0; i < jx; i++) /* Output the result */ if ((rc = pnbyte(jbuf[i],fn)) < 0) return(rc); return(jx); /* Return its length */ } default: if (sj.x_short < 0x80) return(sj.x_short); else return('?'); } }#endif /* KANJI */#endif /* UNICODE */ debug(F100,"xpnbyte BAD FALLTHRU","",0); return(-1);}#ifndef NOXFER/* D E C O D E -- Kermit Data-packet decoder */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 */ int len; 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);#ifdef COMMENT#ifdef CKTUNING if (binary && !parity) return(bdecode(buf,fn));#endif /* CKTUNING */#endif /* COMMENT */ debug(F100,"DECODE","",0); xdbuf = buf; /* Make global copy of pointer. */ rpt = 0; /* Initialize repeat count. */ len = rln; /* Number of bytes in data field */ while (len > 0) { /* Loop for each byte */ a = *xdbuf++ & 0xff; /* Get next character */ len--; 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. */ len -= 2; } 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. */ len--; } else ssflg = 0; ccpflg = 0; if (a == ctlq) { /* If control prefix, */ a = *xdbuf++ & 0xFF; /* get its operand */ len--; 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 */#ifndef NOCSETS if (!binary) { /* If in text mode, */ if (tcharset != TC_UCS2) { if (feol && a == CR) /* Convert CRLF to newline char */ continue; if (feol && a == LF) a = feol; } if (xlatype == XLA_BYTE) /* Byte-for-byte - do it now */ if (xlate && rx) a = (*rx)((CHAR) a); }#endif /* NOCSETS */ /* (PWP) Decoding speedup via buffered output and a macro... */ if (fn == putfil) { for (; rpt > 0; rpt--) { /* Output the char RPT times */#ifdef CALIBRATE if (calibrate) { ffc++; continue; }#endif /* CALIBRATE *//* Note: The Unicode and Kanji sections can probably be combined now; *//* the Unicode method (xpnbyte()) covers Kanji too. */#ifdef UNICODE if (!binary && xlatype == XLA_UNICODE) t = xpnbyte((unsigned)((unsigned)a & 0xff), tcharset, fcharset, fn ); else#endif /* UNICODE */#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 */ {#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 errno","",errno); return(-1); }#ifdef UNICODE if (xlatype != XLA_UNICODE || binary) { 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]); } }#endif /* UNICODE */ } } else { /* Output to something else. */ a &= fmask; /* Apply file mask */ for (; rpt > 0; rpt--) { /* Output the char RPT times */#ifdef CALIBRATE if (calibrate) { ffc++; continue; }#endif /* CALIBRATE */ if ((*fn)((char) a) < 0) return(-1); /* Send to output func. */ } }#ifdef CK_CTRLZ lastchar = a;#endif /* CK_CTRLZ */ } 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 function Returns: The size as value of the function, and also sets global "size", and fills (and null-terminates) the global data array. Returns: 0 on EOF. -1 on fatal (internal) error. -3 on timeout (e.g. when reading data from a pipe). 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 some confusion with line termination (CRLF vs LF vs CR). Rewritten again by Frank da Cruz to incorporate locking shift mechanism, May 1991. And again in 1998 for efficiency, etc, with a separate bgetpkt() split out for binary-mode no-parity transfers.*//* Note: Separate Kanji support dates from circa 1991 and now (1999) can most likely be combined with the the Unicode support: the xgnbyte()/xpnbyte() mechanism works for both Unicode and Kanji.*/#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 *//* 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 on match, 0 if they don't match. 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.*/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. */}/* Routine to compute maximum data length for packet to be filled */intmaxdata() { /* Get maximum data length */ int n, len; debug(F101,"maxdata spsiz 1","",spsiz); if (spsiz < 0) /* How could this happen? */ spsiz = DSPSIZ; debug(F101,"maxdata spsiz 2","",spsiz); n = spsiz - 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 */ len = n - bctl; /* Space for data */ if (n > 92) len -= 3; /* Long packet needs header chksum */ debug(F101,"maxdata len 1","",len); if (len < 0) len = 10; debug(F101,"maxdata len 2","",len); return(len);}static CHAR leftover[9] = { '\0','\0','\0','\0','\0','\0','\0','\0','\0' };static int nleft = 0;#ifdef CKTUNING/* When CKTUNING is defined we use this special trimmed-down version of getpkt to speed up binary-mode no-parity transfers. When CKTUNING is not defined, or for text-mode or parity transfers, we use the regular getpkt() function. Call just like getpkt() but test first for transfer mode and parity. NOTE: This routine is only to be called when sending a real file -- not for filenames, server responses, etc, because it only reads from the input file. See getpkt() for more detailed commentary.*/static intbgetpkt(bufmax) int bufmax; { register CHAR rt = t, rnext; register CHAR *dp, *odp, *p1, *p2; register int x = 0, a7; CHAR xxrc, xxcq; /* Pieces of prefixed sequence */ long z; /* A long worker (for CRC) */ if (!binary || parity || memstr) /* JUST IN CASE caller didn't test */ return(getpkt(bufmax,!binary)); if (!data) { debug(F100,"SERIOUS ERROR: bgetpkt data == NULL","",0); return(-1); } dp = data; /* Point to packet data buffer */ size = 0; /* And initialize its size */ bufmax = maxdata(); /* Get maximum data length */#ifdef DEBUG if (deblog) debug(F101,"bgetpkt bufmax","",bufmax);#endif /* DEBUG */ if (first == 1) { /* If first character of this file.. */ ffc = 0L; /* reset file character counter */#ifdef COMMENT/* Moved to below */ first = 0; /* Next character won't be first */#endif /* COMMENT */ *leftover = '\0'; /* Discard any interrupted leftovers */ nleft = 0; /* Get first character of file into rt, watching out for null file */#ifdef CALIBRATE if (calibrate) {#ifdef NORANDOM rt = 17;#else rt = cal_a[rand() & 0xff];#endif /* NORANDOM */ first = 0; } else#endif /* CALIBRATE */ if ((x = zminchar()) < 0) { /* EOF or error */ if (x == -3) { /* Timeout. */ size = (dp - data); debug(F101,"bgetpkt timeout size","",size); return((size == 0) ? x : size); } first = -1; size = 0; if (x == -2) { /* Error */ debug(F100,"bgetpkt: input error","",0); cxseen = 1; /* Interrupt the file transfer */ } else { debug(F100,"bgetpkt empty file","",0); } return(0); } first = 0; /* Next char will not be the first */ ffc++; /* Count a file character */ rt = (CHAR) x; /* Convert int to char */ if (docrc && (what & W_SEND)) { /* Accumulate file crc */ z = crc16 ^ (long)rt; crc16 = (crc16 >> 8) ^ (crcta[(z & 0xF0) >> 4] ^ crctb[z & 0x0F]); } rt &= fmask; /* Apply SET FILE BYTESIZE mask */ } else if (first == -1 && nleft == 0) { /* EOF from last time */ return(size = 0); }/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -