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