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

1.1     ! root        1: /* protf.c
        !             2:    The 'f' protocol.
        !             3: 
        !             4:    Copyright (C) 1991, 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 protf_rcsid[] = "$Id: protf.c,v 1.1 93/07/30 07:53:18 bin Exp Locker: bin $";
        !            30: #endif
        !            31: 
        !            32: #include <ctype.h>
        !            33: #include <errno.h>
        !            34: 
        !            35: #include "uudefs.h"
        !            36: #include "uuconf.h"
        !            37: #include "conn.h"
        !            38: #include "trans.h"
        !            39: #include "system.h"
        !            40: #include "prot.h"
        !            41: 
        !            42: /* This implementation is based on code by Piet Beertema, CWI,
        !            43:    Amsterdam, Sep 1984.
        !            44: 
        !            45:    This code implements the 'f' protocol, which requires a
        !            46:    flow-controlled error-free seven-bit data path.  It does check for
        !            47:    errors, but only at the end of each file transmission, so a noisy
        !            48:    line without error correcting modems will be unusable.
        !            49: 
        !            50:    The conversion to seven bit data is done as follows, where b
        !            51:    represents the character to convert:
        !            52: 
        !            53:       0 <= b <=  037: 0172, b + 0100 (0100 to 0137)
        !            54:     040 <= b <= 0171:       b        ( 040 to 0171)
        !            55:    0172 <= b <= 0177: 0173, b - 0100 ( 072 to 077)
        !            56:    0200 <= b <= 0237: 0174, b - 0100 (0100 to 0137)
        !            57:    0240 <= b <= 0371: 0175, b - 0200 ( 040 to 0171)
        !            58:    0372 <= b <= 0377: 0176, b - 0300 ( 072 to 077)
        !            59: 
        !            60:    This causes all output bytes to be in the range 040 to 0176; these
        !            61:    are the printable ASCII characters.  */
        !            62: 
        !            63: /* This structure is used to hold information when dealing with the
        !            64:    end of file acknowledgement.  */
        !            65: 
        !            66: struct sfinfo
        !            67: {
        !            68:   /* The functions from the generic code.  */
        !            69:   boolean (*psendfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon));
        !            70:   boolean (*precfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon,
        !            71:                       const char *zdata, size_t cdata));
        !            72:   /* The info pointer from the generic code.  */
        !            73:   pointer pinfo;
        !            74:   /* The character to send after receiving the checksum.  */
        !            75:   char bsend;
        !            76: };
        !            77: 
        !            78: /* Internal functions.  */
        !            79: static boolean ffprocess_data P((struct sdaemon *qdaemon,
        !            80:                                 boolean *pfexit, size_t *pcneed));
        !            81: static boolean ffawait_ack P((struct stransfer *qtrans,
        !            82:                              struct sdaemon *qdaemon,
        !            83:                              const char *zdata, size_t cdata));
        !            84: static boolean ffawait_cksum P((struct stransfer *qtrans,
        !            85:                                struct sdaemon *qdaemon,
        !            86:                                const char *zdata, size_t cdata));
        !            87: static boolean ffsend_ack P((struct stransfer *qtrans,
        !            88:                             struct sdaemon *qdaemon));
        !            89: 
        !            90: /* The size of the buffer we allocate to store outgoing data in.  */
        !            91: #define CFBUFSIZE (256)
        !            92: 
        !            93: /* The timeout to wait for data to arrive before giving up.  */
        !            94: static int cFtimeout = 120;
        !            95: 
        !            96: /* The maximum number of retries.  */
        !            97: static int cFmaxretries = 2;
        !            98: 
        !            99: /* The buffer we allocate for outgoing data.  */
        !           100: static char *zFbuf;
        !           101: 
        !           102: /* TRUE if we are receiving a file rather than a command.  */
        !           103: static boolean fFfile;
        !           104: 
        !           105: /* The checksum so far.  */
        !           106: static unsigned int iFcheck;
        !           107: 
        !           108: /* The last special byte (0172 to 0176) or 0 if none.  */
        !           109: static char bFspecial;
        !           110: 
        !           111: /* The number of times we have retried this file.  */
        !           112: static int cFretries;
        !           113: 
        !           114: /* Whether this file has been acknowledged.  */
        !           115: static boolean fFacked;
        !           116: 
        !           117: struct uuconf_cmdtab asFproto_params[] =
        !           118: {
        !           119:   { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cFtimeout, NULL },
        !           120:   { "retries", UUCONF_CMDTABTYPE_INT, (pointer) &cFmaxretries, NULL },
        !           121:   { NULL, 0, NULL, NULL }
        !           122: };
        !           123: 
        !           124: /* Statistics.  */
        !           125: 
        !           126: /* The number of data bytes sent in files.  */
        !           127: static long cFsent_data;
        !           128: 
        !           129: /* The number of actual bytes sent in files.  */
        !           130: static long cFsent_bytes;
        !           131: 
        !           132: /* The number of data bytes received in files.  */
        !           133: static long cFrec_data;
        !           134: 
        !           135: /* The number of actual bytes received in files.  */
        !           136: static long cFrec_bytes;
        !           137: 
        !           138: /* The number of file retries when sending.  */
        !           139: static long cFsend_retries;
        !           140: 
        !           141: /* The number of file retries when receiving.  */
        !           142: static long cFrec_retries;
        !           143: 
        !           144: /* Start the protocol.  */
        !           145: 
        !           146: boolean
        !           147: ffstart (qdaemon, pzlog)
        !           148:      struct sdaemon *qdaemon;
        !           149:      char **pzlog;
        !           150: {
        !           151:   *pzlog = NULL;
        !           152: 
        !           153:   cFsent_data = 0;
        !           154:   cFsent_bytes = 0;
        !           155:   cFrec_data = 0;
        !           156:   cFrec_bytes = 0;
        !           157:   cFsend_retries = 0;
        !           158:   cFrec_retries = 0;
        !           159: 
        !           160:   /* Use XON/XOFF handshaking.  */
        !           161:   if (! fconn_set (qdaemon->qconn, PARITYSETTING_DEFAULT,
        !           162:                   STRIPSETTING_SEVENBITS, XONXOFF_ON))
        !           163:     return FALSE;
        !           164: 
        !           165:   /* We sleep to allow the other side to reset the terminal; this is
        !           166:      what Mr. Beertema's code does.  */
        !           167:   usysdep_sleep (2);
        !           168: 
        !           169:   return TRUE;
        !           170: }
        !           171: 
        !           172: /* Shutdown the protocol.  */
        !           173: 
        !           174: /*ARGSIGNORED*/
        !           175: boolean
        !           176: ffshutdown (qdaemon)
        !           177:      struct sdaemon *qdaemon;
        !           178: {
        !           179:   xfree ((pointer) zFbuf);
        !           180:   zFbuf = NULL;
        !           181:   ulog (LOG_NORMAL,
        !           182:        "Protocol 'f': sent %ld bytes for %ld, received %ld bytes for %ld",
        !           183:        cFsent_bytes, cFsent_data, cFrec_bytes, cFrec_data);
        !           184:   if (cFsend_retries != 0 || cFrec_retries != 0)
        !           185:     ulog (LOG_NORMAL, "Protocol 'f' file retries: %ld sending, %ld receiving",
        !           186:          cFsend_retries, cFrec_retries);
        !           187:   cFtimeout = 120;
        !           188:   cFmaxretries = 2;
        !           189:   return TRUE;
        !           190: }
        !           191: 
        !           192: /* Send a command string.  We just send the string followed by a carriage
        !           193:    return.  */
        !           194: 
        !           195: /*ARGSUSED*/
        !           196: boolean
        !           197: ffsendcmd (qdaemon, z, ilocal, iremote)
        !           198:      struct sdaemon *qdaemon;
        !           199:      const char *z;
        !           200:      int ilocal;
        !           201:      int iremote;
        !           202: {
        !           203:   size_t clen;
        !           204:   char *zalc;
        !           205:   boolean fret;
        !           206: 
        !           207:   DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "ffsendcmd: Sending command \"%s\"", z);
        !           208: 
        !           209:   clen = strlen (z);
        !           210:   zalc = zbufalc (clen + 2);
        !           211:   memcpy (zalc, z, clen);
        !           212:   zalc[clen] = '\r';
        !           213:   zalc[clen + 1] = '\0';
        !           214:   fret = fsend_data (qdaemon->qconn, zalc, clen + 1, TRUE);
        !           215:   ubuffree (zalc);
        !           216:   return fret;
        !           217: }
        !           218: 
        !           219: /* Get space to be filled with data.  We allocate the space from the
        !           220:    heap.  */
        !           221: 
        !           222: /*ARGSIGNORED*/
        !           223: char *
        !           224: zfgetspace (qdaemon, pclen)
        !           225:      struct sdaemon *qdaemon;
        !           226:      size_t *pclen;
        !           227: {
        !           228:   *pclen = CFBUFSIZE;
        !           229:   if (zFbuf == NULL)
        !           230:     zFbuf = (char *) xmalloc (CFBUFSIZE);
        !           231:   return zFbuf;
        !           232: }
        !           233: 
        !           234: /* Send out a data packet.  We have to encode the data into seven bits
        !           235:    and accumulate a checksum.  */
        !           236: 
        !           237: /*ARGSIGNORED*/
        !           238: boolean
        !           239: ffsenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
        !           240:      struct sdaemon *qdaemon;
        !           241:      char *zdata;
        !           242:      size_t cdata;
        !           243:      int ilocal;
        !           244:      int iremote;
        !           245:      long ipos;
        !           246: {
        !           247:   char ab[CFBUFSIZE * 2];
        !           248:   char *ze;
        !           249:   register unsigned int itmpchk;
        !           250:       
        !           251:   cFsent_data += cdata;
        !           252: 
        !           253:   ze = ab;
        !           254:   itmpchk = iFcheck;
        !           255:   while (cdata-- > 0)
        !           256:     {
        !           257:       register int b;
        !           258: 
        !           259:       /* Rotate the checksum left.  */
        !           260:       if ((itmpchk & 0x8000) == 0)
        !           261:        itmpchk <<= 1;
        !           262:       else
        !           263:        {
        !           264:          itmpchk <<= 1;
        !           265:          ++itmpchk;
        !           266:        }
        !           267: 
        !           268:       /* Add the next byte into the checksum.  */
        !           269:       b = *zdata++ & 0xff;
        !           270:       itmpchk += b;
        !           271: 
        !           272:       /* Encode the byte.  */
        !           273:       if (b <= 0177)
        !           274:        {
        !           275:          if (b <= 037)
        !           276:            {
        !           277:              *ze++ = '\172';
        !           278:              *ze++ = (char) (b + 0100);
        !           279:            }
        !           280:          else if (b <= 0171)
        !           281:            *ze++ = (char) b;
        !           282:          else
        !           283:            {
        !           284:              *ze++ = '\173';
        !           285:              *ze++ = (char) (b - 0100);
        !           286:            }
        !           287:        }
        !           288:       else
        !           289:        {
        !           290:          if (b <= 0237)
        !           291:            {
        !           292:              *ze++ = '\174';
        !           293:              *ze++ = (char) (b - 0100);
        !           294:            }
        !           295:          else if (b <= 0371)
        !           296:            {
        !           297:              *ze++ = '\175';
        !           298:              *ze++ = (char) (b - 0200);
        !           299:            }
        !           300:          else
        !           301:            {
        !           302:              *ze++ = '\176';
        !           303:              *ze++ = (char) (b - 0300);
        !           304:            }
        !           305:        }
        !           306:     }
        !           307: 
        !           308:   iFcheck = itmpchk;
        !           309: 
        !           310:   cFsent_bytes += ze - ab;
        !           311: 
        !           312:   /* Passing FALSE tells fsend_data not to bother looking for incoming
        !           313:      information, since we really don't expect any.  */
        !           314:   return fsend_data (qdaemon->qconn, ab, (size_t) (ze - ab), FALSE);
        !           315: }
        !           316: 
        !           317: /* Process data and return the amount of data we are looking for in
        !           318:    *pcneed.  The 'f' protocol doesn't really reveal this, but when
        !           319:    transferring file we know that we need at least seven characters
        !           320:    for the checksum.  */
        !           321: 
        !           322: static boolean
        !           323: ffprocess_data (qdaemon, pfexit, pcneed)
        !           324:      struct sdaemon *qdaemon;
        !           325:      boolean *pfexit;
        !           326:      size_t *pcneed;
        !           327: {
        !           328:   int i;
        !           329:   register unsigned int itmpchk;
        !           330: 
        !           331:   *pfexit = FALSE;
        !           332:   if (pcneed != NULL)
        !           333:     *pcneed = 1;
        !           334: 
        !           335:   if (! fFfile)
        !           336:     {
        !           337:       /* A command continues until a '\r' character, which we turn
        !           338:         into '\0' before calling fgot_data.  */
        !           339:       while (iPrecstart != iPrecend)
        !           340:        {
        !           341:          for (i = iPrecstart; i < CRECBUFLEN && i != iPrecend; i++)
        !           342:            {
        !           343:              if (abPrecbuf[i] == '\r')
        !           344:                {
        !           345:                  int istart;
        !           346: 
        !           347:                  DEBUG_MESSAGE1 (DEBUG_PROTO,
        !           348:                                  "ffprocess_data: Got %d command bytes",
        !           349:                                  i - iPrecstart + 1);
        !           350: 
        !           351:                  abPrecbuf[i] = '\0';
        !           352:                  istart = iPrecstart;
        !           353:                  iPrecstart = (i + 1) % CRECBUFLEN;
        !           354:                  if (pcneed != NULL)
        !           355:                    *pcneed = 0;
        !           356:                  return fgot_data (qdaemon, abPrecbuf + istart,
        !           357:                                    (size_t) (i - istart + 1),
        !           358:                                    (const char *) NULL, (size_t) 0,
        !           359:                                    -1, -1, (long) -1, TRUE, pfexit);
        !           360:                }
        !           361:            }
        !           362: 
        !           363:          DEBUG_MESSAGE1 (DEBUG_PROTO,
        !           364:                          "ffprocess_data: Got %d command bytes",
        !           365:                          i - iPrecstart);
        !           366: 
        !           367:          if (! fgot_data (qdaemon, abPrecbuf + iPrecstart,
        !           368:                           (size_t) (i - iPrecstart),
        !           369:                           (const char *) NULL, (size_t) 0,
        !           370:                           -1, -1, (long) -1, TRUE, pfexit))
        !           371:            return FALSE;
        !           372: 
        !           373:          iPrecstart = i % CRECBUFLEN;
        !           374:        }
        !           375: 
        !           376:       return TRUE;
        !           377:     }
        !           378: 
        !           379:   /* Here the data is destined for a file, and we must decode it.  */
        !           380: 
        !           381:   itmpchk = iFcheck;
        !           382: 
        !           383:   while (iPrecstart != iPrecend)
        !           384:     {
        !           385:       char *zstart, *zto, *zfrom;
        !           386:       int c;
        !           387: 
        !           388:       zto = zfrom = zstart = abPrecbuf + iPrecstart;
        !           389: 
        !           390:       c = iPrecend - iPrecstart;
        !           391:       if (c < 0)
        !           392:        c = CRECBUFLEN - iPrecstart;
        !           393: 
        !           394:       while (c-- != 0)
        !           395:        {
        !           396:          int b;
        !           397: 
        !           398:          b = *zfrom++ & 0xff;
        !           399:          if (b < 040 || b > 0176)
        !           400:            {
        !           401:              ulog (LOG_ERROR, "Illegal byte %d", b);
        !           402:              continue;
        !           403:            }
        !           404: 
        !           405:          /* Characters >= 0172 are always special characters.  The
        !           406:             only legal pair of consecutive special characters
        !           407:             are 0176 0176 which immediately precede the four
        !           408:             digit checksum.  */
        !           409:          if (b >= 0172)
        !           410:            {
        !           411:              if (bFspecial != 0)
        !           412:                {
        !           413:                  if (bFspecial != 0176 || b != 0176)
        !           414:                    {
        !           415:                      ulog (LOG_ERROR, "Illegal bytes %d %d",
        !           416:                            bFspecial, b);
        !           417:                      bFspecial = 0;
        !           418:                      continue;
        !           419:                    }
        !           420: 
        !           421:                  /* Pass any initial data.  */
        !           422:                  if (zto != zstart)
        !           423:                    {
        !           424:                      /* Don't count the checksum in the received bytes.  */
        !           425:                      cFrec_bytes += zfrom - zstart - 2;
        !           426:                      cFrec_data += zto - zstart;
        !           427:                      if (! fgot_data (qdaemon, zstart,
        !           428:                                       (size_t) (zto - zstart),
        !           429:                                       (const char *) NULL, (size_t) 0,
        !           430:                                       -1, -1, (long) -1, TRUE, pfexit))
        !           431:                        return FALSE;
        !           432:                    }
        !           433: 
        !           434:                  /* The next characters we want to read are the
        !           435:                     checksum, so skip the second 0176.  */
        !           436:                  iPrecstart = (iPrecstart + zfrom - zstart) % CRECBUFLEN;
        !           437: 
        !           438:                  iFcheck = itmpchk;
        !           439: 
        !           440:                  /* Tell fgot_data that we've read the entire file by
        !           441:                     passing 0 length data.  This will wind up calling
        !           442:                     fffile to verify the checksum.  We set *pcneed to
        !           443:                     0 because we don't want to read any more data
        !           444:                     from the port, since we may have already read the
        !           445:                     checksum.  */
        !           446:                  if (pcneed != NULL)
        !           447:                    *pcneed = 0;
        !           448:                  return fgot_data (qdaemon, (const char *) NULL,
        !           449:                                    (size_t) 0, (const char *) NULL,
        !           450:                                    (size_t) 0, -1, -1, (long) -1,
        !           451:                                    TRUE, pfexit);
        !           452:                }
        !           453: 
        !           454:              /* Here we have encountered a special character that
        !           455:                 does not follow another special character.  */
        !           456:              bFspecial = (char) b;
        !           457:            }
        !           458:          else
        !           459:            {
        !           460:              int bnext;
        !           461: 
        !           462:              /* Here we have encountered a nonspecial character.  */
        !           463: 
        !           464:              switch (bFspecial)
        !           465:                {
        !           466:                default:
        !           467:                  bnext = b;
        !           468:                  break;
        !           469:                case 0172:
        !           470:                  bnext = b - 0100;
        !           471:                  break;
        !           472:                case 0173:
        !           473:                case 0174:
        !           474:                  bnext = b + 0100;
        !           475:                  break;
        !           476:                case 0175:
        !           477:                  bnext = b + 0200;
        !           478:                  break;
        !           479:                case 0176:
        !           480:                  bnext = b + 0300;
        !           481:                  break;
        !           482:                }
        !           483: 
        !           484:              *zto++ = (char) bnext;
        !           485:              bFspecial = 0;
        !           486: 
        !           487:              /* Rotate the checksum left.  */
        !           488:              if ((itmpchk & 0x8000) == 0)
        !           489:                itmpchk <<= 1;
        !           490:              else
        !           491:                {
        !           492:                  itmpchk <<= 1;
        !           493:                  ++itmpchk;
        !           494:                }
        !           495: 
        !           496:              /* Add the next byte into the checksum.  */
        !           497:              itmpchk += bnext;
        !           498:            }
        !           499:        }
        !           500: 
        !           501:       if (zto != zstart)
        !           502:        {
        !           503:          DEBUG_MESSAGE1 (DEBUG_PROTO,
        !           504:                          "ffprocess_data: Got %d bytes",
        !           505:                          zto - zstart);
        !           506: 
        !           507:          cFrec_data += zto - zstart;
        !           508:          if (! fgot_data (qdaemon, zstart, (size_t) (zto - zstart),
        !           509:                           (const char *) NULL, (size_t) 0,
        !           510:                           -1, -1, (long) -1, TRUE, pfexit))
        !           511:            return FALSE;
        !           512:        }
        !           513: 
        !           514:       cFrec_bytes += zfrom - zstart;
        !           515: 
        !           516:       iPrecstart = (iPrecstart + zfrom - zstart) % CRECBUFLEN;
        !           517:     }
        !           518: 
        !           519:   iFcheck = itmpchk;
        !           520: 
        !           521:   if (pcneed != NULL)
        !           522:     {
        !           523:       /* At this point we may have seen the first 0176 in the checksum
        !           524:         but not the second.  The checksum is at least seven
        !           525:         characters long (0176 0176 a b c d \r).  This won't help
        !           526:         much, but reading seven characters is a lot better than
        !           527:         reading two, which is what I saw in a 2400 baud log file.  */
        !           528:       if (bFspecial == 0176)
        !           529:        *pcneed = 6;
        !           530:       else
        !           531:        *pcneed = 7;
        !           532:     }
        !           533: 
        !           534:   return TRUE;
        !           535: }
        !           536: 
        !           537: /* Wait for data to come in and process it until we've finished a
        !           538:    command or a file.  */
        !           539: 
        !           540: boolean
        !           541: ffwait (qdaemon)
        !           542:      struct sdaemon *qdaemon;
        !           543: {
        !           544:   while (TRUE)
        !           545:     {
        !           546:       boolean fexit;
        !           547:       size_t cneed, crec;
        !           548: 
        !           549:       if (! ffprocess_data (qdaemon, &fexit, &cneed))
        !           550:        return FALSE;
        !           551:       if (fexit)
        !           552:        return TRUE;
        !           553: 
        !           554:       if (cneed > 0)
        !           555:        {
        !           556:          /* We really want to do something like get all available
        !           557:             characters, then sleep for half a second and get all
        !           558:             available characters again, and keep this up until we
        !           559:             don't get anything after sleeping.  */
        !           560:          if (! freceive_data (qdaemon->qconn, cneed, &crec, cFtimeout, TRUE))
        !           561:            return FALSE;
        !           562:          if (crec == 0)
        !           563:            {
        !           564:              ulog (LOG_ERROR, "Timed out waiting for data");
        !           565:              return FALSE;
        !           566:            }
        !           567:        }
        !           568:     }
        !           569: }
        !           570: 
        !           571: /* File level operations.  Reset the checksums when starting to send
        !           572:    or receive a file, and output the checksum when we've finished
        !           573:    sending a file.  */
        !           574: 
        !           575: /*ARGSUSED*/
        !           576: boolean
        !           577: fffile (qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
        !           578:      struct sdaemon *qdaemon;
        !           579:      struct stransfer *qtrans;
        !           580:      boolean fstart;
        !           581:      boolean fsend;
        !           582:      long cbytes;
        !           583:      boolean *pfhandled;
        !           584: {
        !           585:   DEBUG_MESSAGE3 (DEBUG_PROTO, "fffile: fstart %s; fsend %s; fFacked %s",
        !           586:                  fstart ? "true" : "false", fsend ? "true" : "false",
        !           587:                  fFacked ? "true" : "false");
        !           588: 
        !           589:   *pfhandled = FALSE;
        !           590: 
        !           591:   if (fstart)
        !           592:     {
        !           593:       iFcheck = 0xffff;
        !           594:       cFretries = 0;
        !           595:       fFacked = FALSE;
        !           596:       if (! fsend)
        !           597:        {
        !           598:          bFspecial = 0;
        !           599:          fFfile = TRUE;
        !           600:        }
        !           601:       return TRUE;
        !           602:     }
        !           603:   else
        !           604:     {
        !           605:       struct sfinfo *qinfo;
        !           606: 
        !           607:       /* We need to handle the checksum and the acknowledgement.  If
        !           608:         we get a successful ACK, we set fFacked to TRUE and call the
        !           609:         send or receive function by hand.  This will wind up calling
        !           610:         here again, so if fFacked is TRUE we just return out and let
        !           611:         the send or receive function do whatever it does.  This is a
        !           612:         bit of a hack.  */
        !           613:       if (fFacked)
        !           614:        {
        !           615:          fFacked = FALSE;
        !           616:          return TRUE;
        !           617:        }
        !           618: 
        !           619:       if (fsend)
        !           620:        {
        !           621:          char ab[sizeof "\176\176ABCD\r"];
        !           622: 
        !           623:          /* Send the final checksum.  */
        !           624:          sprintf (ab, "\176\176%04x\r", iFcheck & 0xffff);
        !           625:          if (! fsend_data (qdaemon->qconn, ab, (size_t) 7, TRUE))
        !           626:            return FALSE;
        !           627: 
        !           628:          /* Now wait for the acknowledgement.  */
        !           629:          fFfile = FALSE;
        !           630:          qinfo = (struct sfinfo *) xmalloc (sizeof (struct sfinfo));
        !           631:          qinfo->psendfn = qtrans->psendfn;
        !           632:          qinfo->precfn = qtrans->precfn;
        !           633:          qinfo->pinfo = qtrans->pinfo;
        !           634:          qtrans->psendfn = NULL;
        !           635:          qtrans->precfn = ffawait_ack;
        !           636:          qtrans->pinfo = (pointer) qinfo;
        !           637:          qtrans->fcmd = TRUE;
        !           638: 
        !           639:          *pfhandled = TRUE;
        !           640: 
        !           641:          return fqueue_receive (qdaemon, qtrans);
        !           642:        }
        !           643:       else
        !           644:        {
        !           645:          /* Wait for the checksum.  */
        !           646:          fFfile = FALSE;
        !           647:          qinfo = (struct sfinfo *) xmalloc (sizeof (struct sfinfo));
        !           648:          qinfo->psendfn = qtrans->psendfn;
        !           649:          qinfo->precfn = qtrans->precfn;
        !           650:          qinfo->pinfo = qtrans->pinfo;
        !           651:          qtrans->psendfn = NULL;
        !           652:          qtrans->precfn = ffawait_cksum;
        !           653:          qtrans->pinfo = (pointer) qinfo;
        !           654:          qtrans->fcmd = TRUE;
        !           655: 
        !           656:          *pfhandled = TRUE;
        !           657: 
        !           658:          return fqueue_receive (qdaemon, qtrans);
        !           659:        }
        !           660:     }
        !           661: }
        !           662: 
        !           663: /* Wait for the ack after sending a file and the checksum.  */
        !           664: 
        !           665: static boolean
        !           666: ffawait_ack (qtrans, qdaemon, zdata, cdata)
        !           667:      struct stransfer *qtrans;
        !           668:      struct sdaemon *qdaemon;
        !           669:      const char *zdata;
        !           670:      size_t cdata;
        !           671: {
        !           672:   struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
        !           673: 
        !           674:   qtrans->precfn = NULL;
        !           675: 
        !           676:   /* An R means to retry sending the file.  */
        !           677:   if (*zdata == 'R')
        !           678:     {
        !           679:       if (! ffileisopen (qtrans->e))
        !           680:        {
        !           681:          ulog (LOG_ERROR, "Request to resent non-file");
        !           682:          return FALSE;
        !           683:        }
        !           684: 
        !           685:       ++cFretries;
        !           686:       if (cFretries > cFmaxretries)
        !           687:        {
        !           688:          ulog (LOG_ERROR, "Too many retries");
        !           689:          return FALSE;
        !           690:        }
        !           691: 
        !           692:       ulog (LOG_NORMAL, "Resending file");
        !           693:       if (! ffilerewind (qtrans->e))
        !           694:        {
        !           695:          ulog (LOG_ERROR, "rewind: %s", strerror (errno));
        !           696:          return FALSE;
        !           697:        }
        !           698:       qtrans->ipos = (long) 0;
        !           699: 
        !           700:       iFcheck = 0xffff;
        !           701:       ++cFsend_retries;
        !           702: 
        !           703:       qtrans->psendfn = qinfo->psendfn;
        !           704:       qtrans->precfn = qinfo->precfn;
        !           705:       qtrans->pinfo = qinfo->pinfo;
        !           706:       xfree ((pointer) qinfo);
        !           707:       qtrans->fsendfile = TRUE;
        !           708: 
        !           709:       return fqueue_send (qdaemon, qtrans);
        !           710:     }
        !           711: 
        !           712:   if (*zdata != 'G')
        !           713:     {
        !           714:       DEBUG_MESSAGE1 (DEBUG_PROTO, "fffile: Got \"%s\"", zdata);
        !           715:       ulog (LOG_ERROR, "File send failed");
        !           716:       return FALSE;
        !           717:     }
        !           718: 
        !           719:   qtrans->psendfn = qinfo->psendfn;
        !           720:   qtrans->precfn = qinfo->precfn;
        !           721:   qtrans->pinfo = qinfo->pinfo;
        !           722:   xfree ((pointer) qinfo);
        !           723: 
        !           724:   /* Now call the send function by hand after setting fFacked to TRUE.
        !           725:      Since fFacked is true fffile will simply return out, and the send
        !           726:      function can do whatever it what was going to do.  */
        !           727:   fFacked = TRUE;
        !           728:   return (*qtrans->psendfn) (qtrans, qdaemon);
        !           729: }
        !           730: 
        !           731: /* This function is called when the checksum arrives.  */
        !           732: 
        !           733: /*ARGSUSED*/
        !           734: static boolean
        !           735: ffawait_cksum (qtrans, qdaemon, zdata, cdata)
        !           736:      struct stransfer *qtrans;
        !           737:      struct sdaemon *qdaemon;
        !           738:      const char *zdata;
        !           739:      size_t cdata;
        !           740: {
        !           741:   struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
        !           742:   unsigned int icheck;
        !           743: 
        !           744:   qtrans->precfn = NULL;
        !           745: 
        !           746:   if (! isxdigit (zdata[0])
        !           747:       || ! isxdigit (zdata[1])
        !           748:       || ! isxdigit (zdata[2])
        !           749:       || ! isxdigit (zdata[3])
        !           750:       || zdata[4] != '\0')
        !           751:     {
        !           752:       ulog (LOG_ERROR, "Bad checksum format");
        !           753:       xfree (qtrans->pinfo);
        !           754:       return FALSE;
        !           755:     }
        !           756:          
        !           757:   icheck = (unsigned int) strtol ((char *) zdata, (char **) NULL, 16);
        !           758: 
        !           759:   if (icheck != (iFcheck & 0xffff))
        !           760:     {
        !           761:       DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
        !           762:                      "Checksum failed; calculated 0x%x, got 0x%x",
        !           763:                      iFcheck & 0xffff, icheck);
        !           764: 
        !           765:       if (! ffileisopen (qtrans->e))
        !           766:        {
        !           767:          ulog (LOG_ERROR, "Failed to get non-file");
        !           768:          return FALSE;
        !           769:        }
        !           770: 
        !           771:       ++cFretries;
        !           772:       if (cFretries > cFmaxretries)
        !           773:        {
        !           774:          ulog (LOG_ERROR, "Too many retries");
        !           775:          qinfo->bsend = 'Q';
        !           776:        }
        !           777:       else
        !           778:        {
        !           779:          ulog (LOG_NORMAL, "File being resent");
        !           780: 
        !           781:          /* This bit of code relies on the receive code setting
        !           782:             qtrans->s.ztemp to the full name of the temporary file
        !           783:             being used.  */
        !           784:          qtrans->e = esysdep_truncate (qtrans->e, qtrans->s.ztemp);
        !           785:          if (! ffileisopen (qtrans->e))
        !           786:            return FALSE;
        !           787:          qtrans->ipos = (long) 0;
        !           788: 
        !           789:          iFcheck = 0xffff;
        !           790:          bFspecial = 0;
        !           791:          fFfile = TRUE;
        !           792:          ++cFrec_retries;
        !           793: 
        !           794:          /* Send an R to tell the other side to resend the file.  */
        !           795:          qinfo->bsend = 'R';
        !           796:        }
        !           797:     }
        !           798:   else
        !           799:     {
        !           800:       /* Send a G to tell the other side the file was received
        !           801:         correctly.  */
        !           802:       qinfo->bsend = 'G';
        !           803:     }
        !           804: 
        !           805:   qtrans->psendfn = ffsend_ack;
        !           806: 
        !           807:   return fqueue_send (qdaemon, qtrans);
        !           808: }
        !           809: 
        !           810: /* Send the acknowledgement, and then possible wait for the resent
        !           811:    file.  */
        !           812: 
        !           813: static boolean
        !           814: ffsend_ack (qtrans, qdaemon)
        !           815:      struct stransfer *qtrans;
        !           816:      struct sdaemon *qdaemon;
        !           817: {
        !           818:   struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
        !           819:   char ab[2];
        !           820: 
        !           821:   ab[0] = qinfo->bsend;
        !           822:   ab[1] = '\0';
        !           823:   if (! ffsendcmd (qdaemon, ab, 0, 0))
        !           824:     return FALSE;
        !           825: 
        !           826:   qtrans->psendfn = qinfo->psendfn;
        !           827:   qtrans->precfn = qinfo->precfn;
        !           828:   qtrans->pinfo = qinfo->pinfo;
        !           829:   xfree ((pointer) qinfo);
        !           830: 
        !           831:   if (ab[0] == 'Q')
        !           832:     return FALSE;
        !           833:   if (ab[0] == 'R')
        !           834:     {
        !           835:       qtrans->frecfile = TRUE;
        !           836:       return fqueue_receive (qdaemon, qtrans);
        !           837:     }
        !           838: 
        !           839:   fFacked = TRUE;
        !           840:   return (*qtrans->precfn) (qtrans, qdaemon, (const char *) NULL,
        !           841:                            (size_t) 0);
        !           842: }

unix.superglobalmegacorp.com

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