Annotation of coherent/g/usr/lib/uucp/tay104/protj.c, revision 1.1

1.1     ! root        1: /* protj.c
        !             2:    The 'j' protocol.
        !             3: 
        !             4:    Copyright (C) 1992 Ian Lance Taylor
        !             5: 
        !             6:    This file is part of the Taylor UUCP package.
        !             7: 
        !             8:    This program is free software; you can redistribute it and/or
        !             9:    modify it under the terms of the GNU General Public License as
        !            10:    published by the Free Software Foundation; either version 2 of the
        !            11:    License, or (at your option) any later version.
        !            12: 
        !            13:    This program is distributed in the hope that it will be useful, but
        !            14:    WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            16:    General Public License for more details.
        !            17: 
        !            18:    You should have received a copy of the GNU General Public License
        !            19:    along with this program; if not, write to the Free Software
        !            20:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            21: 
        !            22:    The author of the program may be contacted at [email protected] or
        !            23:    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
        !            24:    */
        !            25: 
        !            26: #include "uucp.h"
        !            27: 
        !            28: #if USE_RCS_ID
        !            29: const char protj_rcsid[] = "$Id: protj.c,v 1.1 93/07/30 07:53:35 bin Exp Locker: bin $";
        !            30: #endif
        !            31: 
        !            32: #include <ctype.h>
        !            33: #include <errno.h>
        !            34: 
        !            35: #include "uudefs.h"
        !            36: #include "conn.h"
        !            37: #include "trans.h"
        !            38: #include "system.h"
        !            39: #include "prot.h"
        !            40: 
        !            41: /* The 'j' protocol.
        !            42: 
        !            43:    The 'j' protocol is a wrapper around the 'i' protocol, which avoids
        !            44:    the use of certain characters, such as XON and XOFF.
        !            45: 
        !            46:    Each 'j' protocol packet begins with a '^' character, followed by a
        !            47:    two byte encoded size giving the total number of bytes in the
        !            48:    packet.  The first byte is HIGH, the second byte is LOW, and the
        !            49:    number of bytes is (HIGH - 32) * 64 + (LOW - 32), where 32 <= HIGH
        !            50:    < 127 and 32 <= LOW < 96 (i.e., HIGH and LOW are printable ASCII
        !            51:    characters).  This is followed by a '=' character.  The next two
        !            52:    bytes are the number of data bytes in the packet, using the same
        !            53:    encoding.  This is followed by a '@' character, and then that
        !            54:    number of data bytes.  The remaining bytes in the packet are
        !            55:    indices of bytes which must be transformed, followed by a trailing
        !            56:    '~' character.  The indices are encoded in the following overly
        !            57:    complex format.
        !            58: 
        !            59:    Each byte index is two bytes long.  The first byte in the index is
        !            60:    INDEX-HIGH and the second is INDEX-LOW.  If 32 <= INDEX-HIGH < 126,
        !            61:    the byte index refers to the byte at position (INDEX-HIGH - 32) *
        !            62:    32 + INDEX-LOW % 32 in the actual data, where 32 <= INDEX-LOW <
        !            63:    127.  If 32 <= INDEX-LOW < 64, then 128 must be added to the
        !            64:    indexed byte.  If 64 <= INDEX-LOW < 96, then the indexed byte must
        !            65:    be exclusive or'red with 32.  If 96 <= INDEX-LOW < 127, both
        !            66:    operations must be performed.  If INDEX-HIGH == 126, then the byte
        !            67:    index refers to the byte at position (INDEX-LOW - 32) * 32 + 31,
        !            68:    where 32 <= INDEX-LOW < 126.  128 must be added to the byte, and it
        !            69:    must be exclusive or'red with 32.  This unfortunately requires a
        !            70:    special test (when encoding INDEX-LOW must be checked for 127; when
        !            71:    decoding INDEX-HIGH must be checked for 126).  It does, however,
        !            72:    permit the byte indices field to consist exclusively of printable
        !            73:    ASCII characters.
        !            74: 
        !            75:    The maximum value for a byte index is (125 - 32) * 32 + 31 == 3007,
        !            76:    so the is the maximum number of data bytes permitted.  Since it is
        !            77:    convenient to have each 'j' protocol packet correspond to each 'i'
        !            78:    protocol packet, we restrict the 'i' protocol accordingly.
        !            79: 
        !            80:    Note that this encoding method assumes that we can send all
        !            81:    printable ASCII characters.  */
        !            82: 
        !            83: /* The first byte of each packet.  I just picked these values
        !            84:    randomly, trying to get characters that were perhaps slightly less
        !            85:    likely to appear in normal text.  */
        !            86: #define FIRST '\136'
        !            87: 
        !            88: /* The fourth byte of each packet.  */
        !            89: #define FOURTH '\075'
        !            90: 
        !            91: /* The seventh byte of each packet.  */
        !            92: #define SEVENTH '\100'
        !            93: 
        !            94: /* The trailing byte of each packet.  */
        !            95: #define TRAILER '\176'
        !            96: 
        !            97: /* The length of the header.  */
        !            98: #define CHDRLEN (7)
        !            99: 
        !           100: /* Get a number of bytes encoded in a two byte length at the start of
        !           101:    a packet.  */
        !           102: #define CGETLENGTH(b1, b2) (((b1) - 32) * 64 + ((b2) - 32))
        !           103: 
        !           104: /* Set the high and low bytes of a two byte length at the start of a
        !           105:    packet.  */
        !           106: #define ISETLENGTH_FIRST(i) ((i) / 64 + 32)
        !           107: #define ISETLENGTH_SECOND(i) ((i) % 64 + 32)
        !           108: 
        !           109: /* The maximum packet size we support, as determined by the byte
        !           110:    indices.  */
        !           111: #define IMAXPACKSIZE ((125 - 32) * 32 + 31)
        !           112: 
        !           113: /* Amount to offset the bytes in the byte index by.  */
        !           114: #define INDEX_OFFSET (32)
        !           115: 
        !           116: /* Maximum value of INDEX-LOW, before offsetting.  */
        !           117: #define INDEX_MAX_LOW (32)
        !           118: 
        !           119: /* Maximum value of INDEX-HIGH, before offsetting. */
        !           120: #define INDEX_MAX_HIGH (94)
        !           121: 
        !           122: /* The set of characters to avoid.  */
        !           123: static char *zJavoid;
        !           124: 
        !           125: /* The number of characters to avoid.  */
        !           126: static size_t cJavoid;
        !           127: 
        !           128: /* A buffer used when sending data.  */
        !           129: static char *zJbuf;
        !           130: 
        !           131: /* The end of the undecoded data in abPrecbuf.  */
        !           132: static int iJrecend;
        !           133: 
        !           134: /* Local functions.  */
        !           135: static boolean fjsend_data P((struct sconnection *qconn, const char *zsend,
        !           136:                              size_t csend, boolean fdoread));
        !           137: static boolean fjreceive_data P((struct sconnection *qconn, size_t cneed,
        !           138:                                 size_t *pcrec, int ctimeout,
        !           139:                                 boolean freport));
        !           140: static boolean fjprocess_data P((size_t *pcneed));
        !           141: 
        !           142: /* Start the protocol.  We first send over the list of characters to
        !           143:    avoid as an escape sequence, starting with FIRST and ending with
        !           144:    TRAILER.  There is no error checking done on this string.  */
        !           145: 
        !           146: boolean
        !           147: fjstart (qdaemon, pzlog)
        !           148:      struct sdaemon *qdaemon;
        !           149:      char **pzlog;
        !           150: {
        !           151:   size_t clen;
        !           152:   char *zsend;
        !           153:   int b;
        !           154:   size_t cbuf, cgot;
        !           155:   char *zbuf;
        !           156:   int i;
        !           157: 
        !           158:   /* Send the characters we want to avoid to the other side.  */
        !           159:   clen = strlen (zJavoid_parameter);
        !           160:   zsend = zbufalc (clen + 3);
        !           161:   zsend[0] = FIRST;
        !           162:   memcpy (zsend + 1, zJavoid_parameter, clen);
        !           163:   zsend[clen + 1] = TRAILER;
        !           164:   zsend[clen + 2] = '\0';
        !           165:   if (! fsend_data (qdaemon->qconn, zsend, clen + 2, TRUE))
        !           166:     {
        !           167:       ubuffree (zsend);
        !           168:       return FALSE;
        !           169:     }
        !           170:   ubuffree (zsend);
        !           171: 
        !           172:   /* Read the characters the other side wants to avoid.  */
        !           173:   while ((b = breceive_char (qdaemon->qconn, cIsync_timeout, TRUE))
        !           174:         != FIRST)
        !           175:     {
        !           176:       if (b < 0)
        !           177:        {
        !           178:          if (b == -1)
        !           179:            ulog (LOG_ERROR, "Timed out in 'j' protocol startup");
        !           180:          return FALSE;
        !           181:        }
        !           182:     }
        !           183: 
        !           184:   cbuf = 20;
        !           185:   zbuf = zbufalc (cbuf);
        !           186:   cgot = 0;
        !           187:   while ((b = breceive_char (qdaemon->qconn, cIsync_timeout, TRUE))
        !           188:         != TRAILER)
        !           189:     {
        !           190:       if (b < 0)
        !           191:        {
        !           192:          ubuffree (zbuf);
        !           193:          if (b == -1)
        !           194:            ulog (LOG_ERROR, "Timed out in 'j' protocol startup");
        !           195:          return FALSE;
        !           196:        }
        !           197:       if (cgot + 1 >= cbuf)
        !           198:        {
        !           199:          char *znew;
        !           200: 
        !           201:          cbuf += 20;
        !           202:          znew = zbufalc (cbuf);
        !           203:          memcpy (znew, zbuf, cgot);
        !           204:          ubuffree (zbuf);
        !           205:          zbuf = znew;
        !           206:        }
        !           207:       zbuf[cgot] = b;
        !           208:       ++cgot;
        !           209:     }
        !           210:   zbuf[cgot] = '\0';
        !           211: 
        !           212:   /* Merge the local and remote avoid bytes into one list, translated
        !           213:      into bytes.  */
        !           214:   cgot = cescape (zbuf);
        !           215: 
        !           216:   clen = strlen (zJavoid_parameter);
        !           217:   zJavoid = zbufalc (clen + cgot + 1);
        !           218:   memcpy (zJavoid, zJavoid_parameter, clen + 1);
        !           219:   cJavoid = cescape (zJavoid);
        !           220: 
        !           221:   for (i = 0; i < cgot; i++)
        !           222:     {
        !           223:       if (memchr (zJavoid, zbuf[i], cJavoid) == NULL)
        !           224:        {
        !           225:          zJavoid[cJavoid] = zbuf[i];
        !           226:          ++cJavoid;
        !           227:        }
        !           228:     }
        !           229: 
        !           230:   ubuffree (zbuf);
        !           231: 
        !           232:   /* We can't avoid ASCII printable characters, since the encoding
        !           233:      method assumes that they can always be sent.  If it ever turns
        !           234:      out to be important, a different encoding method could be used,
        !           235:      perhaps keyed by a different FIRST character.  */
        !           236:   if (cJavoid == 0)
        !           237:     {
        !           238:       ulog (LOG_ERROR, "No characters to avoid in 'j' protocol");
        !           239:       return FALSE;
        !           240:     }
        !           241:   for (i = 0; i < cJavoid; i++)
        !           242:     {
        !           243:       if (zJavoid[i] >= 32 && zJavoid[i] <= 126)
        !           244:        {
        !           245:          ulog (LOG_ERROR, "'j' protocol can't avoid character '\\%03o'",
        !           246:                zJavoid[i]);
        !           247:          return FALSE;
        !           248:        }
        !           249:     }
        !           250: 
        !           251:   /* If we are avoiding XON and XOFF, use XON/XOFF handshaking.  */
        !           252:   if (memchr (zJavoid, '\021', cJavoid) != NULL
        !           253:       && memchr (zJavoid, '\023', cJavoid) != NULL)
        !           254:     {
        !           255:       if (! fconn_set (qdaemon->qconn, PARITYSETTING_NONE,
        !           256:                       STRIPSETTING_EIGHTBITS, XONXOFF_ON))
        !           257:        return FALSE;
        !           258:     }
        !           259: 
        !           260:   /* Let the port settle.  */
        !           261:   usysdep_sleep (2);
        !           262: 
        !           263:   /* Allocate a buffer we use when sending data.  We will probably
        !           264:      never actually need one this big; if this code is ported to a
        !           265:      computer with small amounts of memory, this should be changed to
        !           266:      increase the buffer size as needed.  */
        !           267:   zJbuf = zbufalc (CHDRLEN + IMAXPACKSIZE * 3 + 1);
        !           268:   zJbuf[0] = FIRST;
        !           269:   zJbuf[3] = FOURTH;
        !           270:   zJbuf[6] = SEVENTH;
        !           271: 
        !           272:   /* iJrecend is the end of the undecoded data, and iPrecend is the
        !           273:      end of the decoded data.  At this point there is no decoded data,
        !           274:      and we must initialize the variables accordingly.  */
        !           275:   iJrecend = iPrecend;
        !           276:   iPrecend = iPrecstart;
        !           277: 
        !           278:   /* Now do the 'i' protocol startup.  */
        !           279:   return fijstart (qdaemon, pzlog, IMAXPACKSIZE, fjsend_data,
        !           280:                   fjreceive_data);
        !           281: }
        !           282: 
        !           283: /* Shut down the protocol.  */
        !           284: 
        !           285: boolean
        !           286: fjshutdown (qdaemon)
        !           287:      struct sdaemon *qdaemon;
        !           288: {
        !           289:   boolean fret;
        !           290: 
        !           291:   fret = fishutdown (qdaemon);
        !           292:   ubuffree (zJavoid);
        !           293:   ubuffree (zJbuf);
        !           294:   return fret;
        !           295: }
        !           296: 
        !           297: /* Encode a packet of data and send it.  This copies the data, which
        !           298:    is a waste of time, but calling fsend_data three times (for the
        !           299:    header, the body, and the trailer) would waste even more time.  */
        !           300: 
        !           301: static boolean
        !           302: fjsend_data (qconn, zsend, csend, fdoread)
        !           303:      struct sconnection *qconn;
        !           304:      const char *zsend;
        !           305:      size_t csend;
        !           306:      boolean fdoread;
        !           307: {
        !           308:   char *zput, *zindex;
        !           309:   const char *zfrom, *zend;
        !           310:   char bfirst, bsecond;
        !           311:   int iprecendhold;
        !           312:   boolean fret;
        !           313: 
        !           314:   zput = zJbuf + CHDRLEN;
        !           315:   zindex = zput + csend;
        !           316:   zfrom = zsend;
        !           317:   zend = zsend + csend;
        !           318: 
        !           319:   /* Optimize for the common case of avoiding two characters.  */
        !           320:   bfirst = zJavoid[0];
        !           321:   if (cJavoid <= 1)
        !           322:     bsecond = bfirst;
        !           323:   else
        !           324:     bsecond = zJavoid[1];
        !           325:   while (zfrom < zend)
        !           326:     {
        !           327:       char b;
        !           328:       boolean f128, f32;
        !           329:       int i, ihigh, ilow;
        !           330: 
        !           331:       b = *zfrom++;
        !           332:       if (b != bfirst && b != bsecond)
        !           333:        {
        !           334:          int ca;
        !           335:          char *za;
        !           336: 
        !           337:          if (cJavoid <= 2)
        !           338:            {
        !           339:              *zput++ = b;
        !           340:              continue;
        !           341:            }
        !           342: 
        !           343:          ca = cJavoid - 2;
        !           344:          za = zJavoid + 2;
        !           345:          while (ca-- != 0)
        !           346:            if (*za++ == b)
        !           347:              break;
        !           348: 
        !           349:          if (ca < 0)
        !           350:            {
        !           351:              *zput++ = b;
        !           352:              continue;
        !           353:            }
        !           354:        }
        !           355: 
        !           356:       if ((b & 0x80) == 0)
        !           357:        f128 = FALSE;
        !           358:       else
        !           359:        {
        !           360:          b &=~ 0x80;
        !           361:          f128 = TRUE;
        !           362:        }
        !           363:       if (b >= 32 && b != 127)
        !           364:        f32 = FALSE;
        !           365:       else
        !           366:        {
        !           367:          b ^= 0x20;
        !           368:          f32 = TRUE;
        !           369:        }
        !           370: 
        !           371:       /* We must now put the byte index into the buffer.  The byte
        !           372:         index is encoded similarly to the length of the actual data,
        !           373:         but the byte index also encodes the operations that must be
        !           374:         performed on the byte.  The first byte in the index is the
        !           375:         most significant bits.  If we only had to subtract 128 from
        !           376:         the byte, we use the second byte directly.  If we had to xor
        !           377:         the byte with 32, we add 32 to the second byte index.  If we
        !           378:         had to perform both operations, we add 64 to the second byte
        !           379:         index.  However, if we had to perform both operations, and
        !           380:         the second byte index was 31, then after adding 64 and
        !           381:         offsetting by 32 we would come up with 127, which we are not
        !           382:         permitted to use.  Therefore, in this special case we set the
        !           383:         first byte of the index to 126 and put the original first
        !           384:         byte into the second byte position instead.  This is why we
        !           385:         could not permit the high byte of the length of the actual
        !           386:         data to be 126.  We can get away with the switch because both
        !           387:         the value of the second byte index (31) and the operations to
        !           388:         perform (both) are known.  */
        !           389:       i = zput - (zJbuf + CHDRLEN);
        !           390:       ihigh = i / INDEX_MAX_LOW;
        !           391:       ilow = i % INDEX_MAX_LOW;
        !           392: 
        !           393:       if (f128 && ! f32)
        !           394:        ;
        !           395:       else if (f32 && ! f128)
        !           396:        ilow += INDEX_MAX_LOW;
        !           397:       else
        !           398:        {
        !           399:          /* Both operations had to be performed.  */
        !           400:          if (ilow != INDEX_MAX_LOW - 1)
        !           401:            ilow += 2 * INDEX_MAX_LOW;
        !           402:          else
        !           403:            {
        !           404:              ilow = ihigh;
        !           405:              ihigh = INDEX_MAX_HIGH;
        !           406:            }
        !           407:        }
        !           408: 
        !           409:       *zindex++ = ihigh + INDEX_OFFSET;
        !           410:       *zindex++ = ilow + INDEX_OFFSET;
        !           411:       *zput++ = b;
        !           412:     }
        !           413: 
        !           414:   *zindex++ = TRAILER;
        !           415: 
        !           416:   /* Set the lengths into the buffer.  zJbuf[0,3,6] were set when
        !           417:      zJbuf was allocated, and are never changed thereafter.  */
        !           418:   zJbuf[1] = ISETLENGTH_FIRST (zindex - zJbuf);
        !           419:   zJbuf[2] = ISETLENGTH_SECOND (zindex - zJbuf);
        !           420:   zJbuf[4] = ISETLENGTH_FIRST (csend);
        !           421:   zJbuf[5] = ISETLENGTH_SECOND (csend);
        !           422: 
        !           423:   /* Send the data over the line.  We must preserve iPrecend as
        !           424:      discussed in fjreceive_data.  */
        !           425:   iprecendhold = iPrecend;
        !           426:   iPrecend = iJrecend;
        !           427:   fret = fsend_data (qconn, zJbuf, (size_t) (zindex - zJbuf), fdoread);
        !           428:   iJrecend = iPrecend;
        !           429:   iPrecend = iprecendhold;
        !           430: 
        !           431:   /* Process any bytes that may have been placed in abPrecbuf.  */
        !           432:   if (fret && iPrecend != iJrecend)
        !           433:     {
        !           434:       if (! fjprocess_data ((size_t *) NULL))
        !           435:        return FALSE;
        !           436:     }
        !           437: 
        !           438:   return fret;
        !           439: }
        !           440: 
        !           441: /* Receive and decode data.  This is called by fiwait_for_packet.  We
        !           442:    need to be able to return decoded data between iPrecstart and
        !           443:    iPrecend, while not losing any undecoded partial packets we may
        !           444:    have read.  We use iJrecend as a pointer to the end of the
        !           445:    undecoded data, and set iPrecend for the decoded data.  iPrecend
        !           446:    points to the start of the undecoded data.  */
        !           447: 
        !           448: static boolean
        !           449: fjreceive_data (qconn, cineed, pcrec, ctimeout, freport)
        !           450:      struct sconnection *qconn;
        !           451:      size_t cineed;
        !           452:      size_t *pcrec;
        !           453:      int ctimeout;
        !           454:      boolean freport;
        !           455: {
        !           456:   int iprecendstart;
        !           457:   size_t cjneed;
        !           458:   size_t crec;
        !           459:   int cnew;
        !           460: 
        !           461:   iprecendstart = iPrecend;
        !           462: 
        !           463:   /* Figure out how many bytes we need to decode the next packet.  */
        !           464:   if (! fjprocess_data (&cjneed))
        !           465:     return FALSE;
        !           466: 
        !           467:   /* As we long as we read some data but don't have enough to decode a
        !           468:      packet, we try to read some more.  We decrease the timeout each
        !           469:      time so that we will not wait forever if the connection starts
        !           470:      dribbling data.  */
        !           471:   do
        !           472:     {
        !           473:       int iprecendhold;
        !           474:       size_t cneed;
        !           475: 
        !           476:       if (cjneed > cineed)
        !           477:        cneed = cjneed;
        !           478:       else
        !           479:        cneed = cineed;
        !           480: 
        !           481:       /* We are setting iPrecend to the end of the decoded data for
        !           482:         the 'i' protocol.  When we do the actual read, we have to set
        !           483:         it to the end of the undecoded data so that any undecoded
        !           484:         data we have received is not overwritten.  */
        !           485:       iprecendhold = iPrecend;
        !           486:       iPrecend = iJrecend;
        !           487:       if (! freceive_data (qconn, cneed, &crec, ctimeout, freport))
        !           488:        return FALSE;
        !           489:       iJrecend = iPrecend;
        !           490:       iPrecend = iprecendhold;
        !           491: 
        !           492:       /* Process any data we have received.  This will set iPrecend to
        !           493:         the end of the new decoded data.  */
        !           494:       if (! fjprocess_data (&cjneed))
        !           495:        return FALSE;
        !           496: 
        !           497:       cnew = iPrecend - iprecendstart;
        !           498:       if (cnew < 0)
        !           499:        cnew += CRECBUFLEN;
        !           500: 
        !           501:       if (cnew > cineed)
        !           502:        cineed = 0;
        !           503:       else
        !           504:        cineed -= cnew;
        !           505: 
        !           506:       --ctimeout;
        !           507:     }
        !           508:   while (cnew == 0 && crec > 0 && ctimeout > 0);
        !           509: 
        !           510:   DEBUG_MESSAGE1 (DEBUG_PROTO, "fjreceive_data: Got %d decoded bytes",
        !           511:                  cnew);
        !           512: 
        !           513:   *pcrec = cnew;
        !           514:   return TRUE;
        !           515: }
        !           516: 
        !           517: /* Decode the data in the buffer, optionally returning the number of
        !           518:    bytes needed to complete the next packet.  */
        !           519: 
        !           520: static boolean
        !           521: fjprocess_data (pcneed)
        !           522:      size_t *pcneed;
        !           523: {
        !           524:   int istart;
        !           525: 
        !           526:   istart = iPrecend;
        !           527:   while (istart != iJrecend)
        !           528:     {
        !           529:       int i, iget;
        !           530:       char ab[CHDRLEN];
        !           531:       int cpacket, cdata, chave;
        !           532:       int iindex, iendindex;
        !           533: 
        !           534:       /* Find the next occurrence of FIRST.  If we have to skip some
        !           535:         garbage bytes to get to it, zero them out (so they don't
        !           536:         confuse the 'i' protocol) and advance iPrecend.  This will
        !           537:         save us from looking at them again.  */
        !           538:       if (abPrecbuf[istart] != FIRST)
        !           539:        {
        !           540:          int cintro;
        !           541:          char *zintro;
        !           542:          size_t cskipped;
        !           543: 
        !           544:          cintro = iJrecend - istart;
        !           545:          if (cintro < 0)
        !           546:            cintro = CRECBUFLEN - istart;
        !           547: 
        !           548:          zintro = memchr (abPrecbuf + istart, FIRST, (size_t) cintro);
        !           549:          if (zintro == NULL)
        !           550:            {
        !           551:              bzero (abPrecbuf + istart, (size_t) cintro);
        !           552:              istart = (istart + cintro) % CRECBUFLEN;
        !           553:              iPrecend = istart;
        !           554:              continue;
        !           555:            }
        !           556: 
        !           557:          cskipped = zintro - (abPrecbuf + istart);
        !           558:          bzero (abPrecbuf + istart, cskipped);
        !           559:          istart += cskipped;
        !           560:          iPrecend = istart;
        !           561:        }
        !           562: 
        !           563:       for (i = 0, iget = istart;
        !           564:           i < CHDRLEN && iget != iJrecend;
        !           565:           ++i, iget = (iget + 1) % CRECBUFLEN)
        !           566:        ab[i] = abPrecbuf[iget];
        !           567: 
        !           568:       if (i < CHDRLEN)
        !           569:        {
        !           570:          if (pcneed != NULL)
        !           571:            *pcneed = CHDRLEN - i;
        !           572:          return TRUE;
        !           573:        }
        !           574: 
        !           575:       cpacket = CGETLENGTH (ab[1], ab[2]);
        !           576:       cdata = CGETLENGTH (ab[4], ab[5]);
        !           577: 
        !           578:       /* Make sure the header has the right magic characters, that the
        !           579:         data is not larger than the packet, and that we have an even
        !           580:         number of byte index characters.  */
        !           581:       if (ab[3] != FOURTH
        !           582:          || ab[6] != SEVENTH
        !           583:          || cdata > cpacket - CHDRLEN - 1
        !           584:          || (cpacket - cdata - CHDRLEN - 1) % 2 == 1)
        !           585:        {
        !           586:          istart = (istart + 1) % CRECBUFLEN;
        !           587:          continue;
        !           588:        }
        !           589: 
        !           590:       chave = iJrecend - istart;
        !           591:       if (chave < 0)
        !           592:        chave += CRECBUFLEN;
        !           593: 
        !           594:       if (chave < cpacket)
        !           595:        {
        !           596:          if (pcneed != NULL)
        !           597:            *pcneed = cpacket - chave;
        !           598:          return TRUE;
        !           599:        }
        !           600: 
        !           601:       /* Figure out where the byte indices start and end.  */
        !           602:       iindex = (istart + CHDRLEN + cdata) % CRECBUFLEN;
        !           603:       iendindex = (istart + cpacket - 1) % CRECBUFLEN;
        !           604: 
        !           605:       /* Make sure the magic trailer character is there.  */
        !           606:       if (abPrecbuf[iendindex] != TRAILER)
        !           607:        {
        !           608:          istart = (istart + 1) % CRECBUFLEN;
        !           609:          continue;
        !           610:        }
        !           611: 
        !           612:       /* We have a packet to decode.  The decoding process is simpler
        !           613:         than the encoding process, since all we have to do is examine
        !           614:         the byte indices.  We zero out the byte indices as we go, so
        !           615:         that they will not confuse the 'i' protocol.  */
        !           616:       while (iindex != iendindex)
        !           617:        {
        !           618:          int ihigh, ilow;
        !           619:          boolean f32, f128;
        !           620:          int iset;
        !           621: 
        !           622:          ihigh = abPrecbuf[iindex] - INDEX_OFFSET;
        !           623:          abPrecbuf[iindex] = 0;
        !           624:          iindex = (iindex + 1) % CRECBUFLEN;
        !           625:          ilow = abPrecbuf[iindex] - INDEX_OFFSET;
        !           626:          abPrecbuf[iindex] = 0;
        !           627:          iindex = (iindex + 1) % CRECBUFLEN;
        !           628: 
        !           629:          /* Now we must undo the encoding, by adding 128 and xoring
        !           630:             with 32 as appropriate.  Which to do is encoded in the
        !           631:             low byte, except that if the high byte is the special
        !           632:             value 126, then the low byte is actually the high byte
        !           633:             and both operations are performed.  */
        !           634:          f128 = TRUE;
        !           635:          f32 = TRUE;
        !           636:          if (ihigh == INDEX_MAX_HIGH)
        !           637:            iset = ilow * INDEX_MAX_LOW + INDEX_MAX_LOW - 1;
        !           638:          else
        !           639:            {
        !           640:              iset = ihigh * INDEX_MAX_LOW + ilow % INDEX_MAX_LOW;
        !           641:              if (ilow < INDEX_MAX_LOW)
        !           642:                f32 = FALSE;
        !           643:              else if (ilow < 2 * INDEX_MAX_LOW)
        !           644:                f128 = FALSE;
        !           645:            }
        !           646: 
        !           647:          /* Now iset is the index from the start of the data to the
        !           648:             byte to modify; adjust it to an index in abPrecbuf.  */
        !           649:          iset = (istart + CHDRLEN + iset) % CRECBUFLEN;
        !           650: 
        !           651:          if (f128)
        !           652:            abPrecbuf[iset] |= 0x80;
        !           653:          if (f32)
        !           654:            abPrecbuf[iset] ^= 0x20;
        !           655:        }
        !           656: 
        !           657:       /* Zero out the header and trailer to avoid confusing the 'i'
        !           658:         protocol, and update iPrecend to the end of decoded data.  */
        !           659:       for (i = 0, iget = istart;
        !           660:           i < CHDRLEN && iget != iJrecend;
        !           661:           ++i, iget = (iget + 1) % CRECBUFLEN)
        !           662:        abPrecbuf[iget] = 0;
        !           663:       abPrecbuf[iendindex] = 0;
        !           664:       iPrecend = (iendindex + 1) % CRECBUFLEN;
        !           665:       istart = iPrecend;
        !           666:     }
        !           667: 
        !           668:   if (pcneed != NULL)
        !           669:     *pcneed = CHDRLEN + 1;
        !           670:   return TRUE;
        !           671: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.