Annotation of coherent/g/usr/lib/uucp/tay104/trans.c, revision 1.1.1.1

1.1       root        1: /* trans.c
                      2:    Routines to handle file transfers.
                      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 trans_rcsid[] = "$Id: trans.c,v 1.1 93/07/30 07:54:20 bin Exp Locker: bin $";
                     30: #endif
                     31: 
                     32: #include <errno.h>
                     33: 
                     34: #include "uudefs.h"
                     35: #include "uuconf.h"
                     36: #include "prot.h"
                     37: #include "system.h"
                     38: #include "trans.h"
                     39: 
                     40: /* Local functions.  */
                     41: 
                     42: static void utqueue P((struct stransfer **, struct stransfer *,
                     43:                       boolean fhead));
                     44: static void utdequeue P((struct stransfer *));
                     45: static void utchanalc P((struct sdaemon *qdaemon, struct stransfer *qtrans));
                     46: __inline__ static struct stransfer *qtchan P((int ichan));
                     47: __inline__ static void utchanfree P((struct stransfer *qtrans));
                     48: static boolean ftcharge P((struct sdaemon *qdaemon,
                     49:                           struct stransfer *qtrans,
                     50:                           boolean fsend, boolean fforce));
                     51: static boolean fcheck_queue P((struct sdaemon *qdaemon));
                     52: static boolean ftadd_cmd P((struct sdaemon *qdaemon, const char *z,
                     53:                            size_t cdata, int iremote, boolean flast));
                     54: static boolean fremote_hangup_reply P((struct stransfer *qtrans,
                     55:                                       struct sdaemon *qdaemon));
                     56: static boolean flocal_poll_file P((struct stransfer *qtrans,
                     57:                                   struct sdaemon *qdaemon));
                     58: 
                     59: /* Queue of transfer structures that are ready to start which have
                     60:    been requested by the local system.  These are only permitted to
                     61:    start when the local system is the master.  */
                     62: static struct stransfer *qTlocal;
                     63: 
                     64: /* Queue of transfer structures that are ready to start which have
                     65:    been requested by the remote system.  These are responses to
                     66:    commands received from the remote system, and should be started as
                     67:    soon as possible.  */
                     68: static struct stransfer *qTremote;
                     69: 
                     70: /* Queue of transfer structures that have been started and want to
                     71:    send information.  This should be static, but the 'a' protocol
                     72:    looks at it, at least for now.  */
                     73: struct stransfer *qTsend;
                     74: 
                     75: /* Queue of transfer structures that have been started and are waiting
                     76:    to receive information.  */
                     77: static struct stransfer *qTreceive;
                     78: 
                     79: /* Queue of free transfer structures.  */
                     80: static struct stransfer *qTavail;
                     81: 
                     82: /* Array of transfer structures indexed by local channel number.  This
                     83:    is maintained for local jobs.  */
                     84: static struct stransfer *aqTchan[IMAX_CHAN + 1];
                     85: 
                     86: /* Number of local channel numbers currently allocated.  */
                     87: static int cTchans;
                     88: 
                     89: /* Next channel number to allocate.  */
                     90: static int iTchan;
                     91: 
                     92: /* Array of transfer structures indexed by remote channel number.
                     93:    This is maintained for remote jobs.  */
                     94: static struct stransfer *aqTremote[IMAX_CHAN + 1];
                     95: 
                     96: /* A structure used to charge time to file transfers.  */
                     97: struct scharge
                     98: {
                     99:   /* The transfer we are currently charging.  */
                    100:   struct stransfer *qtrans;
                    101:   /* The time at the last update.  */
                    102:   long isecs;
                    103:   long imicros;
                    104: };
                    105: 
                    106: /* We are always charging one send and one receive.  */
                    107: static struct scharge sTsend;
                    108: static struct scharge sTreceive;
                    109: 
                    110: /* The minimum amount of time, in seconds, to wait between times we
                    111:    check the spool directory, if we are busy transferring data.  If we
                    112:    have nothing to do, we will check the spool directory regardless of
                    113:    how long ago the last check was.  This should probably be
                    114:    configurable.  */
                    115: #define CCHECKWAIT (600)
                    116: 
                    117: /* The time we last checked the spool directory for work.  This is set
                    118:    from the return value of ixsysdep_process_time, not ixsysdep_time,
                    119:    for convenience in the routines which use it.  */
                    120: static long iTchecktime;
                    121: 
                    122: /* The size of the command we have read so far in ftadd_cmd.  */
                    123: static size_t cTcmdlen;
                    124: 
                    125: /* The structure we use when waiting for an acknowledgement of a
                    126:    confirmed received file in fsent_receive_ack, and a list of those
                    127:    structures.  */
                    128: 
                    129: struct sreceive_ack
                    130: {
                    131:   struct sreceive_ack *qnext;
                    132:   char *zto;
                    133:   char *ztemp;
                    134:   boolean fmarked;
                    135: };
                    136: 
                    137: static struct sreceive_ack *qTreceive_ack;
                    138: 
                    139: /* Queue up a transfer structure before *pq.  This puts it at the head
                    140:    or the tail of the list headed by *pq.  */
                    141: 
                    142: static void
                    143: utqueue (pq, q, fhead)
                    144:      struct stransfer **pq;
                    145:      struct stransfer *q;
                    146:      boolean fhead;
                    147: {
                    148:   if (*pq == NULL)
                    149:     {
                    150:       *pq = q;
                    151:       q->qprev = q->qnext = q;
                    152:     }
                    153:   else
                    154:     {
                    155:       q->qnext = *pq;
                    156:       q->qprev = (*pq)->qprev;
                    157:       q->qprev->qnext = q;
                    158:       q->qnext->qprev = q;
                    159:       if (fhead)
                    160:        *pq = q;
                    161:     }
                    162:   q->pqqueue = pq;
                    163: }
                    164: 
                    165: /* Dequeue a transfer structure.  */
                    166: 
                    167: static void
                    168: utdequeue (q)
                    169:      struct stransfer *q;
                    170: {
                    171:   if (q->pqqueue != NULL)
                    172:     {
                    173:       if (*(q->pqqueue) == q)
                    174:        {
                    175:          if (q->qnext == q)
                    176:            *(q->pqqueue) = NULL;
                    177:          else
                    178:            *(q->pqqueue) = q->qnext;
                    179:        }
                    180:       q->pqqueue = NULL;
                    181:     }
                    182:   if (q->qprev != NULL)
                    183:     q->qprev->qnext = q->qnext;
                    184:   if (q->qnext != NULL)
                    185:     q->qnext->qprev = q->qprev;
                    186:   q->qprev = NULL;
                    187:   q->qnext = NULL;
                    188: }
                    189: 
                    190: /* Queue up a transfer structure requested by the local system.  */
                    191: 
                    192: /*ARGSIGNORED*/
                    193: boolean
                    194: fqueue_local (qdaemon, qtrans)
                    195:      struct sdaemon *qdaemon;
                    196:      struct stransfer *qtrans;
                    197: {
                    198:   utdequeue (qtrans);
                    199:   utqueue (&qTlocal, qtrans, FALSE);
                    200:   return TRUE;
                    201: }
                    202: 
                    203: /* Queue up a transfer structure requested by the remote system.  The
                    204:    stransfer structure should have the iremote field set.  We need to
                    205:    record it, so that any subsequent data associated with this
                    206:    channel can be routed to the right place.  */
                    207: 
                    208: boolean
                    209: fqueue_remote (qdaemon, qtrans)
                    210:      struct sdaemon *qdaemon;
                    211:      struct stransfer *qtrans;
                    212: {
                    213:   DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "fqueue_remote: Channel %d",
                    214:                  qtrans->iremote);
                    215:   if (qtrans->iremote > 0)
                    216:     aqTremote[qtrans->iremote] = qtrans;
                    217:   utdequeue (qtrans);
                    218:   utqueue (&qTremote, qtrans, FALSE);
                    219: 
                    220:   /* We just received data for this transfer, so start charging.  */
                    221:   return ftcharge (qdaemon, qtrans, FALSE, FALSE);
                    222: }
                    223: 
                    224: /* Queue up a transfer with something to send.  */
                    225: 
                    226: boolean
                    227: fqueue_send (qdaemon, qtrans)
                    228:      struct sdaemon *qdaemon;
                    229:      struct stransfer *qtrans;
                    230: {
                    231: #if DEBUG > 0
                    232:   if (qtrans->psendfn == NULL)
                    233:     ulog (LOG_FATAL, "fqueue_send: Bad call");
                    234: #endif
                    235:   utdequeue (qtrans);
                    236:   utqueue (&qTsend, qtrans, FALSE);
                    237: 
                    238:   /* Since we're now going to wait to send data, don't charge this
                    239:      transfer for receive time.  */
                    240:   if (qtrans == sTreceive.qtrans)
                    241:     return ftcharge (qdaemon, (struct stransfer *) NULL, FALSE, FALSE);
                    242:   return TRUE;
                    243: }
                    244: 
                    245: /* Queue up a transfer with something to receive.  */
                    246: 
                    247: boolean
                    248: fqueue_receive (qdaemon, qtrans)
                    249:      struct sdaemon *qdaemon;
                    250:      struct stransfer *qtrans;
                    251: {
                    252: #if DEBUG > 0
                    253:   if (qtrans->precfn == NULL)
                    254:     ulog (LOG_FATAL, "fqueue_receive: Bad call");
                    255: #endif
                    256:   utdequeue (qtrans);
                    257:   utqueue (&qTreceive, qtrans, FALSE);
                    258: 
                    259:   /* Since we are now going to wait to receive data, don't charge this
                    260:      transfer for send time.  */
                    261:   if (qtrans == sTsend.qtrans)
                    262:     return ftcharge (qdaemon, (struct stransfer *) NULL, TRUE, FALSE);
                    263:   return TRUE;
                    264: }
                    265: 
                    266: /* Get a new local channel number.  */
                    267: 
                    268: static void
                    269: utchanalc (qdaemon, qtrans)
                    270:      struct sdaemon *qdaemon;
                    271:      struct stransfer *qtrans;
                    272: {
                    273:   do
                    274:     {
                    275:       ++iTchan;
                    276:       if (iTchan > qdaemon->qproto->cchans)
                    277:        iTchan = 1;
                    278:     }
                    279:   while (aqTchan[iTchan] != NULL);
                    280: 
                    281:   qtrans->ilocal = iTchan;
                    282:   aqTchan[iTchan] = qtrans;
                    283:   ++cTchans;
                    284: }
                    285: 
                    286: /* Return the transfer for a channel number.  */
                    287: 
                    288: __inline__
                    289: static struct stransfer *
                    290: qtchan (ic)
                    291:      int ic;
                    292: {
                    293:   return aqTchan[ic];
                    294: }
                    295: 
                    296: /* Clear the channel number for a transfer.  */
                    297: 
                    298: __inline__
                    299: static void
                    300: utchanfree (qt)
                    301:      struct stransfer *qt;
                    302: {
                    303:   if (qt->ilocal != 0)
                    304:     {
                    305:       aqTchan[qt->ilocal] = NULL;
                    306:       qt->ilocal = 0;
                    307:       --cTchans;
                    308:     }
                    309: }
                    310: 
                    311: /* Allocate a new transfer structure.  */
                    312: 
                    313: struct stransfer *
                    314: qtransalc (qcmd)
                    315:      struct scmd *qcmd;
                    316: {
                    317:   register struct stransfer *q;
                    318: 
                    319:   q = qTavail;
                    320:   if (q != NULL)
                    321:     utdequeue (q);
                    322:   else
                    323:     q = (struct stransfer *) xmalloc (sizeof (struct stransfer));
                    324:   q->qnext = NULL;
                    325:   q->qprev = NULL;
                    326:   q->pqqueue = NULL;
                    327:   q->psendfn = NULL;
                    328:   q->precfn = NULL;
                    329:   q->pinfo = NULL;
                    330:   q->fsendfile = FALSE;
                    331:   q->frecfile = FALSE;
                    332:   q->e = EFILECLOSED;
                    333:   q->ipos = 0;
                    334:   q->fcmd = FALSE;
                    335:   q->zcmd = NULL;
                    336:   q->ccmd = 0;
                    337:   q->ilocal = 0;
                    338:   q->iremote = 0;
                    339:   if (qcmd != NULL)
                    340:     {
                    341:       q->s = *qcmd;
                    342:       q->s.zfrom = zbufcpy (qcmd->zfrom);
                    343:       q->s.zto = zbufcpy (qcmd->zto);
                    344:       q->s.zuser = zbufcpy (qcmd->zuser);
                    345:       q->s.zoptions = zbufcpy (qcmd->zoptions);
                    346:       q->s.ztemp = zbufcpy (qcmd->ztemp);
                    347:       q->s.znotify = zbufcpy (qcmd->znotify);
                    348:       q->s.zcmd = zbufcpy (qcmd->zcmd);
                    349:     }
                    350:   else
                    351:     {
                    352:       q->s.zfrom = NULL;
                    353:       q->s.zto = NULL;
                    354:       q->s.zuser = NULL;
                    355:       q->s.zoptions = NULL;
                    356:       q->s.ztemp = NULL;
                    357:       q->s.znotify = NULL;
                    358:       q->s.zcmd = NULL;
                    359:     }
                    360:   q->isecs = 0;
                    361:   q->imicros = 0;
                    362:   q->cbytes = 0;
                    363: 
                    364:   return q;
                    365: }
                    366: 
                    367: /* Free a transfer structure.  This does not free any pinfo
                    368:    information that may have been allocated.  */
                    369: 
                    370: void
                    371: utransfree (q)
                    372:      struct stransfer *q;
                    373: {
                    374:   ubuffree (q->zcmd);
                    375:   ubuffree ((char *) q->s.zfrom);
                    376:   ubuffree ((char *) q->s.zto);
                    377:   ubuffree ((char *) q->s.zuser);
                    378:   ubuffree ((char *) q->s.zoptions);
                    379:   ubuffree ((char *) q->s.ztemp);
                    380:   ubuffree ((char *) q->s.znotify);
                    381:   ubuffree ((char *) q->s.zcmd);
                    382:   
                    383:   utchanfree (q);    
                    384:   if (q->iremote > 0)
                    385:     {
                    386:       aqTremote[q->iremote] = NULL;
                    387:       q->iremote = 0;
                    388:     }
                    389: 
                    390: #if DEBUG > 0
                    391:   q->zcmd = NULL;
                    392:   q->s.zfrom = NULL;
                    393:   q->s.zto = NULL;
                    394:   q->s.zuser = NULL;
                    395:   q->s.zoptions = NULL;
                    396:   q->s.ztemp = NULL;
                    397:   q->s.znotify = NULL;
                    398:   q->s.zcmd = NULL;
                    399:   q->psendfn = NULL;
                    400:   q->precfn = NULL;
                    401: #endif
                    402: 
                    403:   /* Don't try to charge time to this structure any longer.  */
                    404:   if (sTsend.qtrans == q)
                    405:     sTsend.qtrans = NULL;
                    406:   if (sTreceive.qtrans == q)
                    407:     sTreceive.qtrans = NULL;
                    408: 
                    409:   utdequeue (q);
                    410:   utqueue (&qTavail, q, FALSE);
                    411: }
                    412: 
                    413: /* Handle timing of file tranfers.  This is called when processing
                    414:    starts for a transfer structure.  All time up to the next call to
                    415:    this function is charged to that transfer structure.  Sending time
                    416:    and receiving time are charged separately.  Normally if we are
                    417:    about to start charging the same structure we are already charging,
                    418:    we do nothing; but if the fforce argument is TRUE, we charge the
                    419:    time anyhow.  */
                    420: 
                    421: static boolean
                    422: ftcharge (qdaemon, qtrans, fsend, fforce)
                    423:      struct sdaemon *qdaemon;
                    424:      struct stransfer *qtrans;
                    425:      boolean fsend;
                    426:      boolean fforce;
                    427: {
                    428:   struct scharge *qcharge, *qother;
                    429:   long inextsecs, inextmicros;
                    430: 
                    431:   if (fsend)
                    432:     {
                    433:       qcharge = &sTsend;
                    434:       qother = &sTreceive;
                    435:     }
                    436:   else
                    437:     {
                    438:       qcharge = &sTreceive;
                    439:       qother = &sTsend;
                    440:     }
                    441: 
                    442:   if (! fforce && qtrans == qcharge->qtrans)
                    443:     return TRUE;
                    444: 
                    445:   inextsecs = ixsysdep_process_time (&inextmicros);
                    446:   if (qcharge->qtrans != NULL)
                    447:     {
                    448:       qcharge->qtrans->isecs += inextsecs - qcharge->isecs;
                    449:       qcharge->qtrans->imicros += inextmicros - qcharge->imicros;
                    450: 
                    451:       /* If we are charging the same structure for both send and
                    452:         receive, update the time we are not currently charging so
                    453:         that we don't charge twice for the same time.  */
                    454:       if (qcharge->qtrans == qother->qtrans)
                    455:        {
                    456:          qother->isecs = inextsecs;
                    457:          qother->imicros = inextmicros;
                    458:        }         
                    459:     }
                    460:   
                    461:   qcharge->qtrans = qtrans;
                    462:   qcharge->isecs = inextsecs;
                    463:   qcharge->imicros = inextmicros;
                    464: 
                    465:   /* If enough time has elapsed since the last time we checked the
                    466:      queue, check it again.  We do this here because we have already
                    467:      gone to the trouble of getting the time.  */
                    468:   if (inextsecs - iTchecktime >= CCHECKWAIT)
                    469:     {
                    470:       if (! fcheck_queue (qdaemon))
                    471:        return FALSE;
                    472:     }
                    473: 
                    474:   return TRUE;
                    475: }
                    476: 
                    477: 
                    478: /* Gather local commands and queue them up for later processing.  Also
                    479:    recompute time based control values.  */
                    480: 
                    481: boolean
                    482: fqueue (qdaemon, pfany)
                    483:      struct sdaemon *qdaemon;
                    484:      boolean *pfany;
                    485: {
                    486:   const struct uuconf_system *qsys;
                    487:   int bgrade;
                    488:   struct uuconf_timespan *qlocal_size, *qremote_size;
                    489: 
                    490:   if (pfany != NULL)
                    491:     *pfany = FALSE;
                    492: 
                    493:   qsys = qdaemon->qsys;
                    494: 
                    495:   /* If we are not the caller, the grade will be set during the
                    496:      initial handshake.  */
                    497:   if (! qdaemon->fcaller)
                    498:     bgrade = qdaemon->bgrade;
                    499:   else
                    500:     {
                    501:       long ival;
                    502: 
                    503:       if (! ftimespan_match (qsys->uuconf_qtimegrade, &ival,
                    504:                             (int *) NULL))
                    505:        bgrade = '\0';
                    506:       else
                    507:        bgrade = (char) ival;
                    508:     }
                    509: 
                    510:   /* Determine the maximum sizes we can send and receive.  */
                    511:   if (qdaemon->fcaller)
                    512:     {
                    513:       qlocal_size = qsys->uuconf_qcall_local_size;
                    514:       qremote_size = qsys->uuconf_qcall_remote_size;
                    515:     }
                    516:   else
                    517:     {
                    518:       qlocal_size = qsys->uuconf_qcalled_local_size;
                    519:       qremote_size = qsys->uuconf_qcalled_remote_size;
                    520:     }
                    521: 
                    522:   if (! ftimespan_match (qlocal_size, &qdaemon->clocal_size, (int *) NULL))
                    523:     qdaemon->clocal_size = (long) -1;
                    524:   if (! ftimespan_match (qremote_size, &qdaemon->cremote_size, (int *) NULL))
                    525:     qdaemon->cremote_size = (long) -1;
                    526: 
                    527:   if (bgrade == '\0')
                    528:     return TRUE;
                    529: 
                    530:   if (! fsysdep_get_work_init (qsys, bgrade))
                    531:     return FALSE;
                    532: 
                    533:   while (TRUE)
                    534:     {
                    535:       struct scmd s;
                    536: 
                    537:       if (! fsysdep_get_work (qsys, bgrade, &s))
                    538:        return FALSE;
                    539: 
                    540:       if (s.bcmd == 'H')
                    541:        {
                    542:          ulog_user ((const char *) NULL);
                    543:          break;
                    544:        }
                    545: 
                    546:       if (s.bcmd == 'P')
                    547:        {
                    548:          struct stransfer *qtrans;
                    549: 
                    550:          /* A poll file.  */
                    551:          ulog_user ((const char *) NULL);
                    552:          qtrans = qtransalc (&s);
                    553:          qtrans->psendfn = flocal_poll_file;
                    554:          if (! fqueue_local (qdaemon, qtrans))
                    555:            return FALSE;
                    556:          continue;
                    557:        }
                    558: 
                    559:       ulog_user (s.zuser);
                    560: 
                    561:       switch (s.bcmd)
                    562:        {
                    563:        case 'S':
                    564:        case 'E':
                    565:          if (! flocal_send_file_init (qdaemon, &s))
                    566:            return FALSE;
                    567:          break;
                    568:        case 'R':
                    569:          if (! flocal_rec_file_init (qdaemon, &s))
                    570:            return FALSE;
                    571:          break;
                    572:        case 'X':
                    573:          if (! flocal_xcmd_init (qdaemon, &s))
                    574:            return FALSE;
                    575:          break;
                    576: #if DEBUG > 0
                    577:        default:
                    578:          ulog (LOG_FATAL, "fqueue: Can't happen");
                    579:          break;
                    580: #endif
                    581:        }
                    582:     }    
                    583: 
                    584:   if (pfany != NULL)
                    585:     *pfany = qTlocal != NULL;
                    586: 
                    587:   iTchecktime = ixsysdep_process_time ((long *) NULL);
                    588: 
                    589:   return TRUE;
                    590: }
                    591: 
                    592: /* Clear everything off the work queue.  This is used when the call is
                    593:    complete, or if the call is never made.  */
                    594: 
                    595: void
                    596: uclear_queue (qdaemon)
                    597:      struct sdaemon *qdaemon;
                    598: {
                    599:   int i;
                    600: 
                    601:   usysdep_get_work_free (qdaemon->qsys);
                    602: 
                    603:   qTlocal = NULL;
                    604:   qTremote = NULL;
                    605:   qTsend = NULL;
                    606:   qTreceive = NULL;
                    607:   cTchans = 0;
                    608:   iTchan = 0;
                    609:   sTsend.qtrans = NULL;
                    610:   sTreceive.qtrans = NULL;
                    611:   cTcmdlen = 0;
                    612:   qTreceive_ack = NULL;
                    613:   for (i = 0; i < IMAX_CHAN + 1; i++)
                    614:     {
                    615:       aqTchan[i] = NULL;
                    616:       aqTremote[i] = NULL;
                    617:     }
                    618: }
                    619: 
                    620: /* Recheck the work queue during a conversation.  This is only called
                    621:    if it's been more than CCHECKWAIT seconds since the last time the
                    622:    queue was checked.  */
                    623: 
                    624: static boolean
                    625: fcheck_queue (qdaemon)
                    626:      struct sdaemon *qdaemon;
                    627: {
                    628:   int cchans;
                    629: 
                    630:   /* Only check if we are the master, or if there are multiple
                    631:      channels, or if we aren't already trying to get the other side to
                    632:      hang up.  Otherwise, there's nothing we can do with any new jobs
                    633:      we might find.  */
                    634:   if ((qdaemon->ireliable & UUCONF_RELIABLE_FULLDUPLEX) == 0)
                    635:     cchans = 1;
                    636:   else
                    637:     cchans = qdaemon->qproto->cchans;
                    638:   if (qdaemon->fmaster
                    639:       || cchans > 1
                    640:       || ! qdaemon->frequest_hangup)
                    641:     {
                    642:       boolean fany;
                    643: 
                    644:       DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
                    645:                      "fcheck_queue: Rechecking work queue");
                    646:       if (! fqueue (qdaemon, &fany))
                    647:        return FALSE;
                    648: 
                    649:       /* If we found something to do, and we're not the master, and we
                    650:         don't have multiple channels to send new jobs over, try to
                    651:         get the other side to hang up.  */
                    652:       if (fany && ! qdaemon->fmaster && cchans <= 1)
                    653:        qdaemon->frequest_hangup = TRUE;
                    654:     }
                    655: 
                    656:   return TRUE;
                    657: }
                    658: 
                    659: /* The main transfer loop.  The uucico daemon spends essentially all
                    660:    its time in this function.  */
                    661: 
                    662: boolean
                    663: floop (qdaemon)
                    664:      struct sdaemon *qdaemon;
                    665: {
                    666:   int cchans;
                    667:   boolean fret;
                    668: 
                    669:   /* If we are using a half-duplex line, act as though we have only a
                    670:      single channel; otherwise we might start a send and a receive at
                    671:      the same time.  */
                    672:   if ((qdaemon->ireliable & UUCONF_RELIABLE_FULLDUPLEX) == 0)
                    673:     cchans = 1;
                    674:   else
                    675:     cchans = qdaemon->qproto->cchans;
                    676: 
                    677:   fret = TRUE;
                    678: 
                    679:   while (! qdaemon->fhangup)
                    680:     {
                    681:       register struct stransfer *q;
                    682: 
                    683: #if DEBUG > 1
                    684:       /* If we're doing any debugging, close the log and debugging
                    685:         files regularly.  This will let people copy them off and
                    686:         remove them while the conversation is in progresss.  */
                    687:       if (iDebug != 0)
                    688:        {
                    689:          ulog_close ();
                    690:          ustats_close ();
                    691:        }
                    692: #endif
                    693: 
                    694:       if (qdaemon->fmaster)
                    695:        {
                    696:          boolean fhangup;
                    697: 
                    698:          /* We've managed to become the master, so we no longer want
                    699:             to request a hangup.  */
                    700:          qdaemon->frequest_hangup = FALSE;
                    701: 
                    702:          fhangup = FALSE;
                    703: 
                    704:          if (qdaemon->fhangup_requested
                    705:              && qTsend == NULL)
                    706:            {
                    707:              /* The remote system has requested that we transfer
                    708:                 control by sending CYM after receiving a file.  */
                    709:              DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
                    710:                              "floop: Transferring control at remote request");
                    711:              fhangup = TRUE;
                    712:            }
                    713:          else if (qTremote == NULL
                    714:                   && qTlocal == NULL
                    715:                   && qTsend == NULL
                    716:                   && qTreceive == NULL)
                    717:            {
                    718:              /* We don't have anything to do.  Try to find some new
                    719:                 jobs.  If we can't, transfer control.  */
                    720:              if (! fqueue (qdaemon, (boolean *) NULL))
                    721:                {
                    722:                  fret = FALSE;
                    723:                  break;
                    724:                }
                    725:              if (qTlocal == NULL)
                    726:                {
                    727:                  DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
                    728:                                  "floop: No work for master");
                    729:                  fhangup = TRUE;
                    730:                }
                    731:            }
                    732: 
                    733:          if (fhangup)
                    734:            {
                    735:              if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, "H", 0, 0))
                    736:                {
                    737:                  fret = FALSE;
                    738:                  break;
                    739:                }
                    740:              qdaemon->fmaster = FALSE;
                    741:            }
                    742:        }
                    743: 
                    744:       /* If we are no long the master, clear any requested hangup.  We
                    745:         may have already hung up before checking this variable in the
                    746:         block above.  */
                    747:       if (! qdaemon->fmaster)
                    748:        qdaemon->fhangup_requested = FALSE;
                    749: 
                    750:       /* Immediately queue up any remote jobs.  We don't need local
                    751:         channel numbers for them, since we can disambiguate based on
                    752:         the remote channel number.  */
                    753:       while (qTremote != NULL)
                    754:        {
                    755:          q = qTremote;
                    756:          utdequeue (q);
                    757:          utqueue (&qTsend, q, TRUE);
                    758:        }
                    759: 
                    760:       /* If we are the master, or if we have multiple channels, try to
                    761:         queue up additional local jobs.  */
                    762:       if (qdaemon->fmaster || cchans > 1)
                    763:        {
                    764:          while (qTlocal != NULL && cTchans < cchans)
                    765:            {
                    766:              /* We have room for an additional channel.  */
                    767:              q = qTlocal;
                    768:              if (! fqueue_send (qdaemon, q))
                    769:                {
                    770:                  fret = FALSE;
                    771:                  break;
                    772:                }
                    773:              utchanalc (qdaemon, q);
                    774:            }
                    775:          if (! fret)
                    776:            break;
                    777:        }
                    778: 
                    779:       q = qTsend;
                    780: 
                    781:       if (q == NULL)
                    782:        {
                    783:          ulog_user ((const char *) NULL);
                    784:          DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO, "floop: Waiting for data");
                    785:          if (! (*qdaemon->qproto->pfwait) (qdaemon))
                    786:            {
                    787:              fret = FALSE;
                    788:              break;
                    789:            }
                    790:        }
                    791:       else
                    792:        {
                    793:          ulog_user (q->s.zuser);
                    794: 
                    795:          if (! q->fsendfile)
                    796:            {
                    797:              if (! ftcharge (qdaemon, q, TRUE, TRUE))
                    798:                {
                    799:                  fret = FALSE;
                    800:                  break;
                    801:                }
                    802: 
                    803:              if (! (*q->psendfn) (q, qdaemon))
                    804:                {
                    805:                  fret = FALSE;
                    806:                  break;
                    807:                }
                    808:            }
                    809:          else
                    810:            {
                    811:              if (! ftcharge (qdaemon, q, TRUE, FALSE))
                    812:                {
                    813:                  fret = FALSE;
                    814:                  break;
                    815:                }
                    816: 
                    817:              if (q->zlog != NULL)
                    818:                {
                    819:                  ulog (LOG_NORMAL, "%s", q->zlog);
                    820:                  ubuffree (q->zlog);
                    821:                  q->zlog = NULL;
                    822:                }
                    823: 
                    824:              /* We can read the file in a tight loop until qTremote
                    825:                 changes or until we have transferred the entire file.
                    826:                 We can disregard any changes to qTlocal since we
                    827:                 already have something to send anyhow.  */
                    828:              while (qTremote == NULL)
                    829:                {
                    830:                  char *zdata;
                    831:                  size_t cdata;
                    832:                  long ipos;
                    833: 
                    834:                  zdata = (*qdaemon->qproto->pzgetspace) (qdaemon, &cdata);
                    835:                  if (zdata == NULL)
                    836:                    {
                    837:                      fret = FALSE;
                    838:                      break;
                    839:                    }
                    840: 
                    841:                  if (ffileeof (q->e))
                    842:                    cdata = 0;
                    843:                  else
                    844:                    {
                    845:                      cdata = cfileread (q->e, zdata, cdata);
                    846:                      if (ffilereaderror (q->e, cdata))
                    847:                        {
                    848:                          /* There is no way to report a file reading
                    849:                             error, so we just drop the connection.  */
                    850:                          ulog (LOG_ERROR, "read: %s", strerror (errno));
                    851:                          fret = FALSE;
                    852:                          break;
                    853:                        }
                    854:                    }
                    855: 
                    856:                  ipos = q->ipos;
                    857:                  q->ipos += cdata;
                    858:                  q->cbytes += cdata;
                    859: 
                    860:                  if (! (*qdaemon->qproto->pfsenddata) (qdaemon, zdata,
                    861:                                                        cdata, q->ilocal,
                    862:                                                        q->iremote, ipos))
                    863:                    {
                    864:                      fret = FALSE;
                    865:                      break;
                    866:                    }
                    867: 
                    868:                  /* It is possible that this transfer has just been
                    869:                     cancelled.  */
                    870:                  if (q != qTsend || ! q->fsendfile)
                    871:                    break;
                    872: 
                    873:                  if (cdata == 0)
                    874:                    {
                    875:                      /* We must update the time now, because this
                    876:                         call may make an entry in the statistics
                    877:                         file.  */
                    878:                      if (! ftcharge (qdaemon, q, TRUE, TRUE))
                    879:                        fret = FALSE;
                    880:                      q->fsendfile = FALSE;
                    881:                      if (! (*q->psendfn) (q, qdaemon))
                    882:                        fret = FALSE;
                    883:                      break;
                    884:                    }
                    885:                }
                    886: 
                    887:              if (! fret)
                    888:                break;
                    889:            }
                    890:        }
                    891:     }
                    892: 
                    893:   ulog_user ((const char *) NULL);
                    894: 
                    895:   (void) (*qdaemon->qproto->pfshutdown) (qdaemon);
                    896: 
                    897:   if (fret)
                    898:     uwindow_acked (qdaemon, TRUE);
                    899:   else
                    900:     ufailed (qdaemon);
                    901: 
                    902:   return fret;
                    903: }
                    904: 
                    905: /* This is called by the protocol routines when they have received
                    906:    some data.  If pfexit is not NULL, *pfexit should be set to TRUE if
                    907:    the protocol receive loop should exit back to the main floop
                    908:    routine, above.  It is only important to set *pfexit to TRUE if the
                    909:    main loop called the pfwait entry point, so we need never set it to
                    910:    TRUE if we just receive data for a file.  This routine never sets
                    911:    *pfexit to FALSE.  */
                    912: 
                    913: boolean 
                    914: fgot_data (qdaemon, zfirst, cfirst, zsecond, csecond, ilocal, iremote, ipos,
                    915:           fallacked, pfexit)
                    916:      struct sdaemon *qdaemon;
                    917:      const char *zfirst;
                    918:      size_t cfirst;
                    919:      const char *zsecond;
                    920:      size_t csecond;
                    921:      int ilocal;
                    922:      int iremote;
                    923:      long ipos;
                    924:      boolean fallacked;
                    925:      boolean *pfexit;
                    926: {
                    927:   struct stransfer *q;
                    928:   int cwrote;
                    929:   boolean fret;
                    930: 
                    931:   if (fallacked && qTreceive_ack != NULL)
                    932:     uwindow_acked (qdaemon, TRUE);
                    933: 
                    934:   /* Now we have to decide which transfer structure gets the data.  If
                    935:      ilocal is -1, it means that the protocol does not know where to
                    936:      route the data.  In that case we route it to the first transfer
                    937:      that is waiting for data, or, if none, as a new command.  If
                    938:      ilocal is 0, we either select based on the remote channel number
                    939:      or we have a new command.  */
                    940:   if (ilocal == -1 && qTreceive != NULL)
                    941:     q = qTreceive;
                    942:   else if (ilocal == 0 && iremote > 0 && aqTremote[iremote] != NULL)
                    943:     q = aqTremote[iremote];
                    944:   else if (ilocal <= 0)
                    945:     {
                    946:       const char *znull;
                    947: 
                    948:       ulog_user ((const char *) NULL);
                    949: 
                    950:       /* This data is part of a command.  If there is no null
                    951:         character in the data, this string will be continued by the
                    952:         next packet.  Otherwise this must be the last string in the
                    953:         command, and we don't care about what comes after the null
                    954:         byte.  */
                    955:       znull = (const char *) memchr (zfirst, '\0', cfirst);
                    956:       if (znull != NULL)
                    957:        fret = ftadd_cmd (qdaemon, zfirst, (size_t) (znull - zfirst),
                    958:                          iremote, TRUE);
                    959:       else
                    960:        {
                    961:          fret = ftadd_cmd (qdaemon, zfirst, cfirst, iremote, FALSE);
                    962:          if (fret && csecond > 0)
                    963:            {
                    964:              znull = (const char *) memchr (zsecond, '\0', csecond);
                    965:              if (znull != NULL)
                    966:                fret = ftadd_cmd (qdaemon, zsecond,
                    967:                                  (size_t) (znull - zsecond), iremote, TRUE);
                    968:              else
                    969:                fret = ftadd_cmd (qdaemon, zsecond, csecond, iremote, FALSE);
                    970:            }
                    971:        }
                    972: 
                    973:       if (pfexit != NULL && (qdaemon->fhangup || qTremote != NULL))
                    974:        *pfexit = TRUE;
                    975: 
                    976:       return fret;
                    977:     }
                    978:   else
                    979:     {
                    980:       /* Get the transfer structure this data is intended for.  */
                    981: 
                    982:       q = qtchan (ilocal);
                    983:     }
                    984: 
                    985: #if DEBUG > 0
                    986:   if (q == NULL || q->precfn == NULL)
                    987:     {
                    988:       ulog (LOG_ERROR, "Protocol error: %lu bytes remote %d local %d",
                    989:            (unsigned long) (cfirst + csecond),
                    990:            iremote, ilocal);
                    991:       return FALSE;
                    992:     }
                    993: #endif
                    994: 
                    995:   ulog_user (q->s.zuser);
                    996: 
                    997:   fret = TRUE;
                    998: 
                    999:   /* If we're receiving a command, then accumulate it up to the null
                   1000:      byte.  */
                   1001:   if (q->fcmd)
                   1002:     {
                   1003:       const char *znull;
                   1004: 
                   1005:       znull = NULL;
                   1006:       while (cfirst > 0)
                   1007:        {
                   1008:          size_t cnew;
                   1009:          char *znew;
                   1010: 
                   1011:          znull = (const char *) memchr (zfirst, '\0', cfirst);
                   1012:          if (znull != NULL)
                   1013:            cnew = znull - zfirst;
                   1014:          else
                   1015:            cnew = cfirst;
                   1016:          znew = zbufalc (q->ccmd + cnew + 1);
                   1017:          memcpy (znew, q->zcmd, q->ccmd);
                   1018:          memcpy (znew + q->ccmd, zfirst, cnew);
                   1019:          znew[q->ccmd + cnew] = '\0';
                   1020:          ubuffree (q->zcmd);
                   1021:          q->zcmd = znew;
                   1022:          q->ccmd += cnew;
                   1023: 
                   1024:          if (znull != NULL)
                   1025:            break;
                   1026: 
                   1027:          zfirst = zsecond;
                   1028:          cfirst = csecond;
                   1029:          csecond = 0;
                   1030:        }
                   1031: 
                   1032:       if (znull != NULL)
                   1033:        {
                   1034:          char *zcmd;
                   1035:          size_t ccmd;
                   1036: 
                   1037:          if (! ftcharge (qdaemon, q, FALSE, TRUE))
                   1038:            fret = FALSE;
                   1039:          zcmd = q->zcmd;
                   1040:          ccmd = q->ccmd;
                   1041:          q->fcmd = FALSE;
                   1042:          q->zcmd = NULL;
                   1043:          q->ccmd = 0;
                   1044:          if (! (*q->precfn) (q, qdaemon, zcmd, ccmd + 1))
                   1045:            fret = FALSE;
                   1046:          ubuffree (zcmd);
                   1047:        }
                   1048:       else
                   1049:        {
                   1050:          if (! ftcharge (qdaemon, q, FALSE, FALSE))
                   1051:            fret = FALSE;
                   1052:        }
                   1053: 
                   1054:       if (pfexit != NULL
                   1055:          && (qdaemon->fhangup
                   1056:              || qdaemon->fmaster
                   1057:              || qTsend != NULL))
                   1058:        *pfexit = TRUE;
                   1059:     }
                   1060:   else if (! q->frecfile || cfirst == 0)
                   1061:     {
                   1062:       /* We're either not receiving a file or the file transfer is
                   1063:         complete.  */
                   1064:       if (! ftcharge (qdaemon, q, FALSE, TRUE))
                   1065:        fret = FALSE;
                   1066:       q->frecfile = FALSE;
                   1067:       if (! (*q->precfn) (q, qdaemon, zfirst, cfirst))
                   1068:        fret = FALSE;
                   1069:       if (fret && csecond > 0)
                   1070:        return fgot_data (qdaemon, zsecond, csecond,
                   1071:                          (const char *) NULL, (size_t) 0,
                   1072:                          ilocal, iremote, ipos + (long) cfirst,
                   1073:                          FALSE, pfexit);
                   1074:       if (pfexit != NULL
                   1075:          && (qdaemon->fhangup
                   1076:              || qdaemon->fmaster
                   1077:              || qTsend != NULL))
                   1078:        *pfexit = TRUE;
                   1079:     }
                   1080:   else
                   1081:     {
                   1082:       if (! ftcharge (qdaemon, q, FALSE, FALSE))
                   1083:        fret = FALSE;
                   1084: 
                   1085:       if (q->zlog != NULL)
                   1086:        {
                   1087:          ulog (LOG_NORMAL, "%s", q->zlog);
                   1088:          ubuffree (q->zlog);
                   1089:          q->zlog = NULL;
                   1090:        }
                   1091: 
                   1092:       if (ipos != -1 && ipos != q->ipos)
                   1093:        {
                   1094:          DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
                   1095:                          "fgot_data: Seeking to %ld", ipos);
                   1096:          if (! ffileseek (q->e, ipos))
                   1097:            {
                   1098:              ulog (LOG_ERROR, "seek: %s", strerror (errno));
                   1099:              fret = FALSE;
                   1100:            }
                   1101:          q->ipos = ipos;
                   1102:        }
                   1103: 
                   1104:       if (fret)
                   1105:        {
                   1106:          while (cfirst > 0)
                   1107:            {
                   1108:              cwrote = cfilewrite (q->e, (char *) zfirst, cfirst);
                   1109:              if (cwrote == cfirst)
                   1110:                {
                   1111: #if FREE_SPACE_DELTA > 0
                   1112:                  long cfree_space;
                   1113: 
                   1114:                  /* Check that there is still enough space on the
                   1115:                     disk.  If there isn't, we drop the connection,
                   1116:                     because we have no way to abort a file transfer
                   1117:                     in progress.  */
                   1118:                  cfree_space = qdaemon->qsys->uuconf_cfree_space;
                   1119:                  if (cfree_space > 0
                   1120:                      && ((q->cbytes / FREE_SPACE_DELTA)
                   1121:                          != (q->cbytes + cfirst) / FREE_SPACE_DELTA)
                   1122:                      && ! frec_check_free (q, cfree_space))
                   1123:                    {
                   1124:                      fret = FALSE;
                   1125:                      break;
                   1126:                    }
                   1127: #endif
                   1128:                  q->cbytes += cfirst;
                   1129:                  q->ipos += cfirst;
                   1130:                }
                   1131:              else
                   1132:                {
                   1133:                  if (cwrote < 0)
                   1134:                    ulog (LOG_ERROR, "write: %s", strerror (errno));
                   1135:                  else
                   1136:                    ulog (LOG_ERROR,
                   1137:                          "Wrote %d to file when trying to write %lu",
                   1138:                          cwrote, (unsigned long) cfirst);
                   1139: 
                   1140:                  /* Any write error is almost certainly a temporary
                   1141:                     condition, or else UUCP would not be functioning
                   1142:                     at all.  If we continue to accept the file, we
                   1143:                     will wind up rejecting it at the end (what else
                   1144:                     could we do?)  and the remote system will throw
                   1145:                     away the request.  We're better off just dropping
                   1146:                     the connection, which is what happens when we
                   1147:                     return FALSE, and trying again later.  */
                   1148:                  fret = FALSE;
                   1149:                  break;
                   1150:                }
                   1151: 
                   1152:              zfirst = zsecond;
                   1153:              cfirst = csecond;
                   1154:              csecond = 0;
                   1155:            }
                   1156:        }
                   1157: 
                   1158:       if (pfexit != NULL && qdaemon->fhangup)
                   1159:        *pfexit = TRUE;
                   1160:     }
                   1161: 
                   1162:   return fret;
                   1163: }
                   1164: 
                   1165: /* Accumulate a string into a command.  If the command is complete,
                   1166:    start up a new transfer.  */
                   1167: 
                   1168: static boolean
                   1169: ftadd_cmd (qdaemon, z, clen, iremote, flast)
                   1170:      struct sdaemon *qdaemon;
                   1171:      const char *z;
                   1172:      size_t clen;
                   1173:      int iremote;
                   1174:      boolean flast;
                   1175: {
                   1176:   static char *zbuf;
                   1177:   static size_t cbuf;
                   1178:   size_t cneed;
                   1179:   struct scmd s;
                   1180: 
                   1181:   cneed = cTcmdlen + clen + 1;
                   1182:   if (cneed > cbuf)
                   1183:     {
                   1184:       zbuf = (char *) xrealloc ((pointer) zbuf, cneed);
                   1185:       cbuf = cneed;
                   1186:     }
                   1187: 
                   1188:   memcpy (zbuf + cTcmdlen, z, clen);
                   1189:   zbuf[cTcmdlen + clen] = '\0';
                   1190: 
                   1191:   if (! flast)
                   1192:     {
                   1193:       cTcmdlen += clen;
                   1194:       return TRUE;
                   1195:     }
                   1196: 
                   1197:   /* Don't save this string for next time.  */
                   1198:   cTcmdlen = 0;
                   1199: 
                   1200:   DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
                   1201:                  "ftadd_cmd: Got command \"%s\"", zbuf);
                   1202: 
                   1203:   if (! fparse_cmd (zbuf, &s))
                   1204:     {
                   1205:       ulog (LOG_ERROR, "Received garbled command \"%s\"", zbuf);
                   1206:       return TRUE;
                   1207:     }
                   1208: 
                   1209:   if (s.bcmd != 'H' && s.bcmd != 'Y' && s.bcmd != 'N')
                   1210:     ulog_user (s.zuser);
                   1211:   else
                   1212:     ulog_user ((const char *) NULL);
                   1213: 
                   1214:   switch (s.bcmd)
                   1215:     {
                   1216:     case 'S':
                   1217:     case 'E':
                   1218:       return fremote_send_file_init (qdaemon, &s, iremote);
                   1219:     case 'R':
                   1220:       return fremote_rec_file_init (qdaemon, &s, iremote);
                   1221:     case 'X':
                   1222:       return fremote_xcmd_init (qdaemon, &s, iremote);
                   1223:     case 'H':
                   1224:       /* This is a remote request for a hangup.  We close the log
                   1225:         files so that they may be moved at this point.  */
                   1226:       ulog_close ();
                   1227:       ustats_close ();
                   1228:       {
                   1229:        struct stransfer *q;
                   1230: 
                   1231:        q = qtransalc ((struct scmd *) NULL);
                   1232:        q->psendfn = fremote_hangup_reply;
                   1233:        q->iremote = iremote;
                   1234:        return fqueue_remote (qdaemon, q);
                   1235:       }
                   1236:     case 'N':
                   1237:       /* This means a hangup request is being denied; we just ignore
                   1238:         this and wait for further commands.  */
                   1239:       return TRUE;
                   1240:     case 'Y':
                   1241:       /* This is a remote confirmation of a hangup.  We reconfirm.  */
                   1242:       if (qdaemon->fhangup)
                   1243:        return TRUE;
                   1244: #if DEBUG > 0
                   1245:       if (qdaemon->fmaster)
                   1246:        ulog (LOG_ERROR, "Got hangup reply as master");
                   1247: #endif
                   1248:       /* Don't check errors rigorously here, since the other side
                   1249:         might jump the gun and hang up.  The fLog_sighup variable
                   1250:         will get set TRUE again when the port is closed.  */
                   1251:       fLog_sighup = FALSE;
                   1252:       (void) (*qdaemon->qproto->pfsendcmd) (qdaemon, "HY", 0, iremote);
                   1253:       qdaemon->fhangup = TRUE;
                   1254:       return TRUE;
                   1255: #if DEBUG > 0
                   1256:     default:
                   1257:       ulog (LOG_FATAL, "ftadd_cmd: Can't happen");
                   1258:       return FALSE;
                   1259: #endif
                   1260:     }
                   1261: }
                   1262: 
                   1263: /* The remote system is requesting a hang up.  If we have something to
                   1264:    do, send an HN.  Otherwise send two HY commands (the other side is
                   1265:    presumed to send an HY command between the first and second, but we
                   1266:    don't bother to wait for it) and hang up.  */
                   1267: 
                   1268: static boolean
                   1269: fremote_hangup_reply (qtrans, qdaemon)
                   1270:      struct stransfer *qtrans;
                   1271:      struct sdaemon *qdaemon;
                   1272: {
                   1273:   boolean fret;
                   1274: 
                   1275:   utransfree (qtrans);
                   1276: 
                   1277:   if (qTremote == NULL
                   1278:       && qTlocal == NULL
                   1279:       && qTsend == NULL
                   1280:       && qTreceive == NULL)
                   1281:     {
                   1282:       if (! fqueue (qdaemon, (boolean *) NULL))
                   1283:        return FALSE;
                   1284: 
                   1285:       if (qTlocal == NULL)
                   1286:        {
                   1287:          DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO, "fremote_hangup_reply: No work");
                   1288:          fret = ((*qdaemon->qproto->pfsendcmd) (qdaemon, "HY", 0, 0)
                   1289:                  && (*qdaemon->qproto->pfsendcmd) (qdaemon, "HY", 0, 0));
                   1290:          qdaemon->fhangup = TRUE;
                   1291:          return fret;
                   1292:        }
                   1293:     }
                   1294: 
                   1295:   DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO, "fremote_hangup_reply: Found work");
                   1296:   fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, "HN", 0, 0);
                   1297:   qdaemon->fmaster = TRUE;
                   1298:   return fret;
                   1299: }
                   1300: 
                   1301: /* As described in system.h, we need to keep track of which files have
                   1302:    been successfully received for which we do not know that the other
                   1303:    system has received our acknowledgement.  This routine is called to
                   1304:    keep a list of such files.  */
                   1305: 
                   1306: static struct sreceive_ack *qTfree_receive_ack;
                   1307: 
                   1308: void
                   1309: usent_receive_ack (qdaemon, qtrans)
                   1310:      struct sdaemon *qdaemon;
                   1311:      struct stransfer *qtrans;
                   1312: {
                   1313:   struct sreceive_ack *q;
                   1314: 
                   1315:   if (qTfree_receive_ack == NULL)
                   1316:     q = (struct sreceive_ack *) xmalloc (sizeof (struct sreceive_ack));
                   1317:   else
                   1318:     {
                   1319:       q = qTfree_receive_ack;
                   1320:       qTfree_receive_ack = q->qnext;
                   1321:     }
                   1322: 
                   1323:   q->qnext = qTreceive_ack;
                   1324:   q->zto = zbufcpy (qtrans->s.zto);
                   1325:   q->ztemp = zbufcpy (qtrans->s.ztemp);
                   1326:   q->fmarked = FALSE;
                   1327: 
                   1328:   qTreceive_ack = q;
                   1329: }
                   1330: 
                   1331: /* This routine is called by the protocol code when either all
                   1332:    outstanding data has been acknowledged or one complete window has
                   1333:    passed.  It may be called directly by the protocol, or it may be
                   1334:    called via fgot_data.  If one complete window has passed, then all
                   1335:    unmarked receives are marked, and we know that all marked ones have
                   1336:    been acked.  */
                   1337: 
                   1338: void
                   1339: uwindow_acked (qdaemon, fallacked)
                   1340:      struct sdaemon *qdaemon;
                   1341:      boolean fallacked;
                   1342: {
                   1343:   register struct sreceive_ack **pq;
                   1344: 
                   1345:   pq = &qTreceive_ack;
                   1346:   while (*pq != NULL)
                   1347:     {
                   1348:       if (fallacked || (*pq)->fmarked)
                   1349:        {
                   1350:          struct sreceive_ack *q;
                   1351: 
                   1352:          q = *pq;
                   1353:          (void) fsysdep_forget_reception (qdaemon->qsys, q->zto,
                   1354:                                           q->ztemp);
                   1355:          ubuffree (q->zto);
                   1356:          ubuffree (q->ztemp);
                   1357:          *pq = q->qnext;
                   1358:          q->qnext = qTfree_receive_ack;
                   1359:          qTfree_receive_ack = q;
                   1360:        }
                   1361:       else
                   1362:        {
                   1363:          (*pq)->fmarked = TRUE;
                   1364:          pq = &(*pq)->qnext;
                   1365:        }
                   1366:     }
                   1367: }
                   1368: 
                   1369: /* This routine is called when an error occurred and we are crashing
                   1370:    out of the connection.  It is used to report statistics on failed
                   1371:    transfers to the statistics file, and it also discards useless
                   1372:    temporary files for file receptions.  Note that the number of bytes
                   1373:    we report as having been sent has little or nothing to do with the
                   1374:    number of bytes the remote site actually received.  */
                   1375: 
                   1376: void
                   1377: ufailed (qdaemon)
                   1378:      struct sdaemon *qdaemon;
                   1379: {
                   1380:   register struct stransfer *q;
                   1381: 
                   1382:   /* Update the transfer times, but avoid looking in the queue.  */
                   1383:   iTchecktime = ixsysdep_process_time ((long *) NULL);
                   1384:   (void) ftcharge (qdaemon, (struct stransfer *) NULL, TRUE, TRUE);
                   1385:   (void) ftcharge (qdaemon, (struct stransfer *) NULL, FALSE, TRUE);
                   1386: 
                   1387:   if (qTsend != NULL)
                   1388:     {
                   1389:       q = qTsend;
                   1390:       do
                   1391:        {
                   1392:          if ((q->fsendfile || q->frecfile)
                   1393:              && q->cbytes > 0)
                   1394:            ustats (FALSE, q->s.zuser, qdaemon->qsys->uuconf_zname,
                   1395:                    q->fsendfile, q->cbytes, q->isecs, q->imicros,
                   1396:                    FALSE);
                   1397:          if (q->frecfile)
                   1398:            (void) frec_discard_temp (qdaemon, q);
                   1399:          q = q->qnext;
                   1400:        }
                   1401:       while (q != qTsend);
                   1402:     }
                   1403: 
                   1404:   if (qTreceive != NULL)
                   1405:     {
                   1406:       q = qTreceive;
                   1407:       do
                   1408:        {
                   1409:          if ((q->fsendfile || q->frecfile)
                   1410:              && q->cbytes > 0)
                   1411:            ustats (FALSE, q->s.zuser, qdaemon->qsys->uuconf_zname,
                   1412:                    q->fsendfile, q->cbytes, q->isecs, q->imicros,
                   1413:                    FALSE);
                   1414:          if (q->frecfile)
                   1415:            (void) frec_discard_temp (qdaemon, q);
                   1416:          q = q->qnext;
                   1417:        }
                   1418:       while (q != qTreceive);
                   1419:     }
                   1420: }
                   1421: 
                   1422: /* When a local poll file is found, it is entered on the queue like
                   1423:    any other job.  When it is pulled off the queue, this function is
                   1424:    called.  It just calls fsysdep_did_work, which will remove the poll
                   1425:    file.  This ensures that poll files are only removed if the system
                   1426:    is actually called.  */
                   1427: 
                   1428: /*ARGSUSED*/
                   1429: static boolean
                   1430: flocal_poll_file (qtrans, qdaemon)
                   1431:      struct stransfer *qtrans;
                   1432:      struct sdaemon *qdaemon;
                   1433: {
                   1434:   boolean fret;
                   1435: 
                   1436:   fret = fsysdep_did_work (qtrans->s.pseq);
                   1437:   utransfree (qtrans);
                   1438:   return fret;
                   1439: }

unix.superglobalmegacorp.com

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