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