Annotation of coherent/g/usr/lib/uucp/tay104/protj.c, revision 1.1.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.