|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.