1/* rec.c
2   Routines to receive a file.
3
4   Copyright (C) 1991, 1992, 1993, 1994, 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
28const char rec_rcsid[] = "$Id: rec.c,v 1.48 2002/03/05 19:10:41 ian Rel $";
29#endif
30
31#include <errno.h>
32
33#include "uudefs.h"
34#include "uuconf.h"
35#include "system.h"
36#include "prot.h"
37#include "trans.h"
38
39/* If the other side does not tell us the size of a file it wants to
40   send us, we assume it is this long.  This is only used for free
41   space checking.  */
42#define CASSUMED_FILE_SIZE (10240)
43
44/* We keep this information in the pinfo field of the stransfer
45   structure.  */
46struct srecinfo
47{
48  /* Local user to send mail to (may be NULL).  */
49  char *zmail;
50  /* Full file name.  */
51  char *zfile;
52  /* Temporary file name.  */
53  char *ztemp;
54  /* TRUE if this is a spool directory file.  */
55  boolean fspool;
56  /* TRUE if this was a local request.  */
57  boolean flocal;
58  /* TRUE if the file has been completely received.  */
59  boolean freceived;
60  /* TRUE if remote request has been replied to.  */
61  boolean freplied;
62  /* TRUE if we moved the file to the final destination.  */
63  boolean fmoved;
64};
65
66/* This structure is kept in the pinfo field if we are refusing a
67   remote request.  */
68struct srecfailinfo
69{
70  /* Reason for refusal.  */
71  enum tfailure twhy;
72  /* TRUE if we have sent the reason for refusal.  */
73  boolean fsent;
74  /* TRUE if we have seen the end of the file.  */
75  boolean freceived;
76};
77
78/* Local functions.  */
79
80static void urrec_free P((struct stransfer *qtrans));
81static boolean flocal_rec_fail P((struct stransfer *qtrans,
82				  struct scmd *qcmd,
83				  const struct uuconf_system *qsys,
84				  const char *zwhy));
85static boolean flocal_rec_send_request P((struct stransfer *qtrans,
86					  struct sdaemon *qdaemon));
87static boolean flocal_rec_await_reply P((struct stransfer *qtrans,
88					 struct sdaemon *qdaemon,
89					 const char *zdata,
90					 size_t cdata));
91static boolean fremote_send_reply P((struct stransfer *qtrans,
92				     struct sdaemon *qdaemon));
93static boolean fremote_send_fail P((struct sdaemon *qdaemon,
94				    struct scmd *qcmd,
95				    enum tfailure twhy,
96				    int iremote));
97static boolean fremote_send_fail_send P((struct stransfer *qtrans,
98					 struct sdaemon *qdaemon));
99static boolean fremote_discard P((struct stransfer *qtrans,
100				  struct sdaemon *qdaemon,
101				  const char *zdata, size_t cdata));
102static boolean frec_file_end P((struct stransfer *qtrans,
103				struct sdaemon *qdaemon,
104				const char *zdata, size_t cdata));
105static boolean frec_file_send_confirm P((struct stransfer *qtrans,
106					 struct sdaemon *qdaemon));
107
108/* Free up a receive stransfer structure.  */
109
110static void
111urrec_free (qtrans)
112     struct stransfer *qtrans;
113{
114  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
115
116  if (qinfo != NULL)
117    {
118      ubuffree (qinfo->zmail);
119      ubuffree (qinfo->zfile);
120      ubuffree (qinfo->ztemp);
121      xfree (qtrans->pinfo);
122    }
123
124  utransfree (qtrans);
125}
126
127/* Set up a request for a file from the remote system.  This may be
128   called before the remote system has been called.
129
130   This is the order of function calls:
131
132   flocal_rec_file_init --> fqueue_local
133   flocal_rec_send_request (send R ...) --> fqueue_receive
134   flocal_rec_await_reply (open file, call pffile) --> fqueue_receive
135   receive file
136   frec_file_end (close and move file, call pffile) --> fqueue_send
137   frec_file_send_confirm (send CY)
138   */
139
140boolean
141flocal_rec_file_init (qdaemon, qcmd)
142     struct sdaemon *qdaemon;
143     struct scmd *qcmd;
144{
145  const struct uuconf_system *qsys;
146  boolean fspool;
147  char *zfile;
148  struct srecinfo *qinfo;
149  struct stransfer *qtrans;
150
151  qsys = qdaemon->qsys;
152
153  /* Make sure we are permitted to transfer files.  */
154  if (qdaemon->fcaller
155      ? ! qsys->uuconf_fcall_transfer
156      : ! qsys->uuconf_fcalled_transfer)
157    {
158      /* This case will have been checked by uucp or uux, but it could
159	 have changed.  */
160      if (! qsys->uuconf_fcall_transfer
161	  && ! qsys->uuconf_fcalled_transfer)
162	return flocal_rec_fail ((struct stransfer *) NULL, qcmd, qsys,
163				"not permitted to request files");
164      return TRUE;
165    }
166
167  fspool = fspool_file (qcmd->zto);
168
169  if (fspool)
170    {
171      pointer puuconf;
172      int iuuconf;
173      const char *zlocalname;
174      struct uuconf_system slocalsys;
175
176      /* Normal users are not allowed to request files to be received
177	 into the spool directory.  To support uux forwarding, we use
178	 the special option '9'.  This permits a file to be received
179	 into the spool directory for the local system only without
180	 the usual checking.  This is only done for local requests, of
181	 course.  */
182      if (qcmd->zto[0] != 'D'
183	  || strchr (qcmd->zoptions, '9') == NULL)
184	return flocal_rec_fail ((struct stransfer *) NULL, qcmd, qsys,
185				"not permitted to receive");
186
187      puuconf = qdaemon->puuconf;
188      iuuconf = uuconf_localname (puuconf, &zlocalname);
189      if (iuuconf == UUCONF_NOT_FOUND)
190	{
191	  zlocalname = zsysdep_localname ();
192	  if (zlocalname == NULL)
193	    return FALSE;
194	}
195      else if (iuuconf != UUCONF_SUCCESS)
196	{
197	  ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
198	  return FALSE;
199	}
200
201      iuuconf = uuconf_system_info (puuconf, zlocalname, &slocalsys);
202      if (iuuconf == UUCONF_NOT_FOUND)
203	{
204	  iuuconf = uuconf_system_local (puuconf, &slocalsys);
205	  if (iuuconf != UUCONF_SUCCESS)
206	    {
207	      ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
208	      return FALSE;
209	    }
210	  slocalsys.uuconf_zname = (char *) zlocalname;
211	}
212      else if (iuuconf != UUCONF_SUCCESS)
213	{
214	  ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
215	  return FALSE;
216	}
217
218      zfile = zsysdep_spool_file_name (&slocalsys, qcmd->zto, qcmd->pseq);
219
220      (void) uuconf_system_free (puuconf, &slocalsys);
221
222      if (zfile == NULL)
223	return FALSE;
224    }
225  else
226    {
227      zfile = zsysdep_add_base (qcmd->zto, qcmd->zfrom);
228      if (zfile == NULL)
229	return FALSE;
230
231      /* Check permissions.  */
232      if (! fin_directory_list (zfile, qsys->uuconf_pzlocal_receive,
233				qsys->uuconf_zpubdir, TRUE,
234				FALSE, qcmd->zuser))
235	{
236	  ubuffree (zfile);
237	  return flocal_rec_fail ((struct stransfer *) NULL, qcmd, qsys,
238				  "not permitted to receive");
239	}
240
241      /* The 'f' option means that directories should not
242	 be created if they do not already exist.  */
243      if (strchr (qcmd->zoptions, 'f') == NULL)
244	{
245	  if (! fsysdep_make_dirs (zfile, TRUE))
246	    {
247	      ubuffree (zfile);
248	      return flocal_rec_fail ((struct stransfer *) NULL, qcmd,
249				      qsys, "cannot create directories");
250	    }
251	}
252    }
253
254  qinfo = (struct srecinfo *) xmalloc (sizeof (struct srecinfo));
255  if (strchr (qcmd->zoptions, 'm') == NULL)
256    qinfo->zmail = NULL;
257  else
258    qinfo->zmail = zbufcpy (qcmd->zuser);
259  qinfo->zfile = zfile;
260  qinfo->ztemp = NULL;
261  qinfo->fspool = fspool;
262  qinfo->flocal = TRUE;
263  qinfo->freceived = FALSE;
264  qinfo->freplied = TRUE;
265
266  qtrans = qtransalc (qcmd);
267  qtrans->psendfn = flocal_rec_send_request;
268  qtrans->pinfo = (pointer) qinfo;
269
270  return fqueue_local (qdaemon, qtrans);
271}
272
273/* Report an error for a local receive request.  */
274
275static boolean
276flocal_rec_fail (qtrans, qcmd, qsys, zwhy)
277     struct stransfer *qtrans;
278     struct scmd *qcmd;
279     const struct uuconf_system *qsys;
280     const char *zwhy;
281{
282  if (zwhy != NULL)
283    {
284      ulog (LOG_ERROR, "%s: %s", qcmd->zfrom, zwhy);
285      (void) fmail_transfer (FALSE, qcmd->zuser, (const char *) NULL, zwhy,
286			     qcmd->zfrom, qsys->uuconf_zname,
287			     qcmd->zto, (const char *) NULL,
288			     (const char *) NULL);
289      (void) fsysdep_did_work (qcmd->pseq);
290    }
291  if (qtrans != NULL)
292    urrec_free (qtrans);
293  return TRUE;
294}
295
296/* This is called when we are ready to send the actual request to the
297   other system.  */
298
299static boolean
300flocal_rec_send_request (qtrans, qdaemon)
301     struct stransfer *qtrans;
302     struct sdaemon *qdaemon;
303{
304  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
305  long cbytes, cbytes2;
306  boolean fquote;
307  const struct scmd *qcmd;
308  struct scmd squoted;
309  size_t clen;
310  char *zsend;
311  boolean fret;
312
313  qinfo->ztemp = zsysdep_receive_temp (qdaemon->qsys, qinfo->zfile,
314				       (const char *) NULL,
315				       (qdaemon->qproto->frestart
316					&& (qdaemon->ifeatures
317					    & FEATURE_RESTART) != 0));
318  if (qinfo->ztemp == NULL)
319    {
320      urrec_free (qtrans);
321      return FALSE;
322    }
323
324  qtrans->fcmd = TRUE;
325  qtrans->precfn = flocal_rec_await_reply;
326
327  if (! fqueue_receive (qdaemon, qtrans))
328    return FALSE;
329
330  /* Check the amount of free space available for both the temporary
331     file and the real file.  */
332  cbytes = csysdep_bytes_free (qinfo->ztemp);
333  cbytes2 = csysdep_bytes_free (qinfo->zfile);
334  if (cbytes < cbytes2)
335    cbytes = cbytes2;
336  if (cbytes != -1)
337    {
338      cbytes -= qdaemon->qsys->uuconf_cfree_space;
339      if (cbytes < 0)
340	cbytes = 0;
341    }
342
343  if (qdaemon->clocal_size != -1
344      && (cbytes == -1 || qdaemon->clocal_size < cbytes))
345    cbytes = qdaemon->clocal_size;
346
347  fquote = fcmd_needs_quotes (&qtrans->s);
348  if (! fquote)
349    qcmd = &qtrans->s;
350  else
351    {
352      if ((qdaemon->ifeatures & FEATURE_QUOTES) == 0)
353	return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys,
354				"remote system does not support required quoting");
355      uquote_cmd (&qtrans->s, &squoted);
356      qcmd = &squoted;
357    }
358
359  /* We send the string
360     R from to user options
361
362     We put a dash in front of options.  If we are talking to a
363     counterpart, we also send the maximum size file we are prepared
364     to accept, as returned by esysdep_open_receive.  */
365  clen = (strlen (qcmd->zfrom) + strlen (qcmd->zto)
366	  + strlen (qcmd->zuser) + strlen (qcmd->zoptions) + 30);
367  zsend = zbufalc (clen);
368  if ((qdaemon->ifeatures & FEATURE_SIZES) == 0)
369    sprintf (zsend, "R %s %s %s -%s", qcmd->zfrom, qcmd->zto,
370	     qcmd->zuser, qcmd->zoptions);
371  else if ((qdaemon->ifeatures & FEATURE_V103) == 0)
372    sprintf (zsend, "R %s %s %s -%s 0x%lx", qcmd->zfrom, qcmd->zto,
373	     qcmd->zuser, qcmd->zoptions, (unsigned long) cbytes);
374  else
375    sprintf (zsend, "R %s %s %s -%s %ld", qcmd->zfrom, qcmd->zto,
376	     qcmd->zuser, qcmd->zoptions, cbytes);
377
378  fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
379					qtrans->iremote);
380  ubuffree (zsend);
381
382  if (fquote)
383    ufree_quoted_cmd (&squoted);
384
385  /* There is a potential space leak here: if pfsendcmd fails, we
386     might need to free qtrans.  However, it is possible that by the
387     time pfsendcmd returns, a response will have been received which
388     led to the freeing of qtrans anyhow.  One way to fix this would
389     be some sort of counter in qtrans to track allocations, but since
390     the space leak is small, and the conversation has failed anyhow,
391     it doesn't seem worth it.  */
392
393  return fret;
394}
395
396/* This is called when a reply is received for the request.  */
397
398/*ARGSUSED*/
399static boolean
400flocal_rec_await_reply (qtrans, qdaemon, zdata, cdata)
401     struct stransfer *qtrans;
402     struct sdaemon *qdaemon;
403     const char *zdata;
404     size_t cdata ATTRIBUTE_UNUSED;
405{
406  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
407  const char *zlog;
408  char *zend;
409
410  if (zdata[0] != 'R'
411      || (zdata[1] != 'Y' && zdata[1] != 'N'))
412    {
413      ulog (LOG_ERROR, "%s: bad response to receive request: \"%s\"",
414	    qtrans->s.zfrom, zdata);
415      urrec_free (qtrans);
416      return FALSE;
417    }
418
419  if (zdata[1] == 'N')
420    {
421      boolean fnever;
422      const char *zerr;
423
424      fnever = TRUE;
425      if (zdata[2] == '2')
426	zerr = "no such file";
427      else if (zdata[2] == '6')
428	{
429	  /* We sent over the maximum file size we were prepared to
430	     receive, and the remote system is telling us that the
431	     file is larger than that.  Try again later.  It would be
432	     better if we could know whether there will ever be enough
433	     room.  */
434	  zerr = "too large to receive now";
435	  fnever = FALSE;
436	}
437      else if (zdata[2] == '9')
438	{
439	  /* Remote has run out of channels.  */
440	  zerr = "too many channels for remote";
441	  fnever = FALSE;
442
443	  /* Drop one channel; using exactly one channel causes
444	     slightly different behahaviour in a few places, so don't
445	     decrement to one.  */
446	  if (qdaemon->cchans > 2)
447	    --qdaemon->cchans;
448	}
449      else
450	zerr = "unknown reason";
451
452      if (fnever)
453	return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys, zerr);
454
455      ulog (LOG_ERROR, "%s: %s", qtrans->s.zfrom, zerr);
456
457      urrec_free (qtrans);
458
459      return TRUE;
460    }
461
462  /* The mode should have been sent as "RY 0%o".  If it wasn't, we use
463     0666.  */
464  qtrans->s.imode = (unsigned int) strtol ((char *) (zdata + 2),
465					   &zend, 8);
466  if (qtrans->s.imode == 0)
467    qtrans->s.imode = 0666;
468
469  /* If there is an M after the mode, the remote has requested a
470     hangup.  */
471  if (*zend == 'M' && qdaemon->fmaster)
472    {
473      DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
474		      "flocal_rec_await_reply: Remote has requested transfer of control");
475      qdaemon->fhangup_requested = TRUE;
476    }
477
478  /* Open the file to receive into.  We just ignore any restart count,
479     since we have no way to tell it to the other side.  SVR4 may have
480     some way to do this, but I don't know what it is.  */
481  qtrans->e = esysdep_open_receive (qdaemon->qsys, qinfo->zfile,
482				    (const char *) NULL, qinfo->ztemp,
483				    (long *) NULL);
484  if (! ffileisopen (qtrans->e))
485    return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys,
486			    "cannot open file");
487
488  if (qinfo->fspool)
489    zlog = qtrans->s.zto;
490  else
491    zlog = qinfo->zfile;
492  qtrans->zlog = zbufalc (sizeof "Receiving " + strlen (zlog));
493  sprintf (qtrans->zlog, "Receiving %s", zlog);
494
495  if (qdaemon->qproto->pffile != NULL)
496    {
497      boolean fhandled;
498
499      if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, FALSE,
500					(long) -1, &fhandled))
501	return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys,
502				(const char *) NULL);
503      if (fhandled)
504	return TRUE;
505    }
506
507  qtrans->frecfile = TRUE;
508  qtrans->psendfn = frec_file_send_confirm;
509  qtrans->precfn = frec_file_end;
510
511  return fqueue_receive (qdaemon, qtrans);
512}
513
514/* Make sure there is still enough disk space available to receive a
515   file.  */
516
517boolean
518frec_check_free (qtrans, cfree_space)
519     struct stransfer *qtrans;
520     long cfree_space;
521{
522  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
523  long cfree1, cfree2;
524
525  cfree1 = csysdep_bytes_free (qinfo->ztemp);
526  cfree2 = csysdep_bytes_free (qinfo->zfile);
527  if (cfree1 < cfree2)
528    cfree1 = cfree2;
529  if (cfree1 != -1 && cfree1 < cfree_space)
530    {
531      ulog (LOG_ERROR, "%s: too big to receive now", qinfo->zfile);
532      return FALSE;
533    }
534
535  return TRUE;
536}
537
538/* A remote request to send a file to the local system, meaning that
539   we are going to receive a file.
540
541   If we are using a protocol which does not support multiple
542   channels, the remote system will not start sending us the file
543   until it has received our confirmation.  In that case, the order of
544   functions is as follows:
545
546   fremote_send_file_init (open file) --> fqueue_remote
547   fremote_send_reply (send SY, call pffile) --> fqueue_receive
548   receive file
549   frec_file_end (close and move file, call pffile) --> fqueue_send
550   frec_file_send_confirm (send CY)
551
552   If the protocol supports multiple channels, then the remote system
553   will start sending the file immediately after the send request.
554   That means that the data may come in before remote_send_reply is
555   called, so frec_file_end may be called before fremote_send_reply.
556   Note that this means the pffile entry points may be called in
557   reverse order for such a protocol.
558
559   If the send request is rejected, via fremote_send_fail, and the
560   protocol supports multiple channels, we must accept and discard
561   data until a zero byte buffer is received from the other side,
562   indicating that it has received our rejection.
563
564   This code also handles execution requests, which are very similar
565   to send requests.  */
566
567boolean
568fremote_send_file_init (qdaemon, qcmd, iremote)
569     struct sdaemon *qdaemon;
570     struct scmd *qcmd;
571     int iremote;
572{
573  const struct uuconf_system *qsys;
574  boolean fspool;
575  char *zfile;
576  openfile_t e;
577  char *ztemp;
578  long cbytes, cbytes2;
579  long crestart;
580  struct srecinfo *qinfo;
581  struct stransfer *qtrans;
582  const char *zlog;
583
584  qsys = qdaemon->qsys;
585
586  if (! qsys->uuconf_frec_request)
587    {
588      ulog (LOG_ERROR, "%s: not permitted to receive files from remote",
589	    qcmd->zfrom);
590      return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
591    }
592
593  fspool = fspool_file (qcmd->zto);
594
595  /* We don't accept remote command files.  An execution request may
596     only send a simple data file.  */
597  if ((fspool && qcmd->zto[0] == 'C')
598      || (qcmd->bcmd == 'E'
599	  && (! fspool || qcmd->zto[0] != 'D')))
600    {
601      ulog (LOG_ERROR, "%s: not permitted to receive", qcmd->zfrom);
602      return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
603    }
604
605  /* See if we have already received this file in a previous
606     conversation.  */
607  if (fsysdep_already_received (qsys, qcmd->zto, qcmd->ztemp))
608    return fremote_send_fail (qdaemon, qcmd, FAILURE_RECEIVED, iremote);
609
610  if (fspool)
611    {
612      zfile = zsysdep_spool_file_name (qsys, qcmd->zto, (pointer) NULL);
613      if (zfile == NULL)
614	return FALSE;
615    }
616  else
617    {
618      boolean fbadname;
619
620      zfile = zsysdep_local_file (qcmd->zto, qsys->uuconf_zpubdir,
621				  &fbadname);
622      if (zfile == NULL && fbadname)
623	{
624	  ulog (LOG_ERROR, "%s: bad local file name", qcmd->zto);
625	  return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
626	}
627      if (zfile != NULL)
628	{
629	  char *zadd;
630
631	  zadd = zsysdep_add_base (zfile, qcmd->zfrom);
632	  ubuffree (zfile);
633	  zfile = zadd;
634	}
635      if (zfile == NULL)
636	return FALSE;
637
638      /* Check permissions.  */
639      if (! fin_directory_list (zfile, qsys->uuconf_pzremote_receive,
640				qsys->uuconf_zpubdir, TRUE,
641				FALSE, (const char *) NULL))
642	{
643	  ulog (LOG_ERROR, "%s: not permitted to receive", zfile);
644	  ubuffree (zfile);
645	  return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
646	}
647
648      if (strchr (qcmd->zoptions, 'f') == NULL)
649	{
650	  if (! fsysdep_make_dirs (zfile, TRUE))
651	    {
652	      ubuffree (zfile);
653	      return fremote_send_fail (qdaemon, qcmd, FAILURE_OPEN,
654					iremote);
655	    }
656	}
657    }
658
659  ztemp = zsysdep_receive_temp (qsys, zfile, qcmd->ztemp,
660				(qdaemon->qproto->frestart
661				 && (qdaemon->ifeatures
662				     & FEATURE_RESTART) != 0));
663
664  /* Adjust the number of bytes we are prepared to receive according
665     to the amount of free space we are supposed to leave available
666     and the maximum file size we are permitted to transfer.  */
667  cbytes = csysdep_bytes_free (ztemp);
668  cbytes2 = csysdep_bytes_free (zfile);
669  if (cbytes < cbytes2)
670    cbytes = cbytes2;
671
672  if (cbytes != -1)
673    {
674      cbytes -= qsys->uuconf_cfree_space;
675      if (cbytes < 0)
676	cbytes = 0;
677    }
678
679  if (qdaemon->cremote_size != -1
680      && (cbytes == -1 || qdaemon->cremote_size < cbytes))
681    cbytes = qdaemon->cremote_size;
682
683  /* If the number of bytes we are prepared to receive is less than
684     the file size, we must fail.  If the remote did not tell us the
685     file size, arbitrarily assumed that it is 10240 bytes.  */
686  if (cbytes != -1)
687    {
688      long csize;
689
690      csize = qcmd->cbytes;
691      if (csize == -1)
692	csize = CASSUMED_FILE_SIZE;
693      if (cbytes < csize)
694	{
695	  ulog (LOG_ERROR, "%s: too big to receive", zfile);
696	  ubuffree (ztemp);
697	  ubuffree (zfile);
698	  return fremote_send_fail (qdaemon, qcmd, FAILURE_SIZE, iremote);
699	}
700    }
701
702  /* Open the file to receive into.  This may find an old copy of the
703     file, which will be used for file restart if the other side
704     supports it.  */
705  crestart = -1;
706  e = esysdep_open_receive (qsys, zfile, qcmd->ztemp, ztemp,
707			    ((qdaemon->qproto->frestart
708			      && (qdaemon->ifeatures
709				  & FEATURE_RESTART) != 0)
710			     ? &crestart
711			     : (long *) NULL));
712  if (! ffileisopen (e))
713    {
714      ubuffree (ztemp);
715      ubuffree (zfile);
716      return fremote_send_fail (qdaemon, qcmd, FAILURE_OPEN, iremote);
717    }
718
719  if (crestart > 0)
720    {
721      DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
722		      "fremote_send_file_init: Restarting receive from %ld",
723		      crestart);
724      if (! ffileseek (e, crestart))
725	{
726	  ulog (LOG_ERROR, "seek: %s", strerror (errno));
727	  (void) ffileclose (e);
728	  ubuffree (ztemp);
729	  ubuffree (zfile);
730	  return FALSE;
731	}
732    }
733
734  qinfo = (struct srecinfo *) xmalloc (sizeof (struct srecinfo));
735  if (strchr (qcmd->zoptions, 'n') == NULL)
736    qinfo->zmail = NULL;
737  else
738    qinfo->zmail = zbufcpy (qcmd->znotify);
739  qinfo->zfile = zfile;
740  qinfo->ztemp = ztemp;
741  qinfo->fspool = fspool;
742  qinfo->flocal = FALSE;
743  qinfo->freceived = FALSE;
744  qinfo->freplied = FALSE;
745
746  qtrans = qtransalc (qcmd);
747  qtrans->psendfn = fremote_send_reply;
748  qtrans->precfn = frec_file_end;
749  qtrans->iremote = iremote;
750  qtrans->pinfo = (pointer) qinfo;
751  qtrans->frecfile = TRUE;
752  qtrans->e = e;
753  if (crestart > 0)
754    qtrans->ipos = crestart;
755
756  if (qcmd->bcmd == 'E')
757    zlog = qcmd->zcmd;
758  else
759    {
760      if (qinfo->fspool)
761	zlog = qcmd->zto;
762      else
763	zlog = qinfo->zfile;
764    }
765  qtrans->zlog = zbufalc (sizeof "Receiving ( bytes resume at )"
766			  + strlen (zlog) + 50);
767  sprintf (qtrans->zlog, "Receiving %s", zlog);
768  if (crestart > 0 || qcmd->cbytes > 0)
769    {
770      strcat (qtrans->zlog, " (");
771      if (qcmd->cbytes > 0)
772	{
773	  sprintf (qtrans->zlog + strlen (qtrans->zlog), "%ld bytes",
774		   qcmd->cbytes);
775	  if (crestart > 0)
776	    strcat (qtrans->zlog, " ");
777	}
778      if (crestart > 0)
779	sprintf (qtrans->zlog + strlen (qtrans->zlog), "resume at %ld",
780		 crestart);
781      strcat (qtrans->zlog, ")");
782    }
783
784  return fqueue_remote (qdaemon, qtrans);
785}
786
787/* Reply to a send request, and prepare to receive the file.  */
788
789static boolean
790fremote_send_reply (qtrans, qdaemon)
791     struct stransfer *qtrans;
792     struct sdaemon *qdaemon;
793{
794  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
795  boolean fret;
796  char ab[50];
797
798  /* If the file has been completely received, we just want to send
799     the final confirmation.  Otherwise, we must wait for the file
800     first.  */
801  qtrans->psendfn = frec_file_send_confirm;
802  if (qinfo->freceived)
803    fret = fqueue_send (qdaemon, qtrans);
804  else
805    fret = fqueue_receive (qdaemon, qtrans);
806  if (! fret)
807    return FALSE;
808
809  ab[0] = qtrans->s.bcmd;
810  ab[1] = 'Y';
811  if (qtrans->ipos <= 0)
812    ab[2] = '\0';
813  else
814    sprintf (ab + 2, " 0x%lx", (unsigned long) qtrans->ipos);
815
816  qinfo->freplied = TRUE;
817
818  if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, qtrans->ilocal,
819				       qtrans->iremote))
820    {
821      (void) ffileclose (qtrans->e);
822      qtrans->e = EFILECLOSED;
823      (void) remove (qinfo->ztemp);
824      /* Should probably free qtrans here, but see the comment at the
825         end of flocal_rec_send_request.  */
826      return FALSE;
827    }
828
829  if (qdaemon->qproto->pffile != NULL)
830    {
831      boolean fhandled;
832
833      if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, FALSE,
834					(long) -1, &fhandled))
835	{
836	  (void) remove (qinfo->ztemp);
837	  urrec_free (qtrans);
838	  return FALSE;
839	}
840    }
841
842  return TRUE;
843}
844
845/* If we can't receive a file, queue up a response to the remote
846   system.  */
847
848static boolean
849fremote_send_fail (qdaemon, qcmd, twhy, iremote)
850     struct sdaemon *qdaemon;
851     struct scmd *qcmd;
852     enum tfailure twhy;
853     int iremote;
854{
855  struct srecfailinfo *qinfo;
856  struct stransfer *qtrans;
857
858  qinfo = (struct srecfailinfo *) xmalloc (sizeof (struct srecfailinfo));
859  qinfo->twhy = twhy;
860  qinfo->fsent = FALSE;
861
862  /* If the protocol does not support multiple channels (cchans <= 1),
863     then we have essentially already received the entire file.  */
864  qinfo->freceived = qdaemon->cchans <= 1;
865
866  qtrans = qtransalc (qcmd);
867  qtrans->psendfn = fremote_send_fail_send;
868  qtrans->precfn = fremote_discard;
869  qtrans->iremote = iremote;
870  qtrans->pinfo = (pointer) qinfo;
871
872  return fqueue_remote (qdaemon, qtrans);
873}
874
875/* Send a failure string for a send command to the remote system;
876   this is called when we are ready to reply to the command.  */
877
878static boolean
879fremote_send_fail_send (qtrans, qdaemon)
880     struct stransfer *qtrans;
881     struct sdaemon *qdaemon;
882{
883  struct srecfailinfo *qinfo = (struct srecfailinfo *) qtrans->pinfo;
884  char ab[4];
885  int ilocal, iremote;
886
887  ab[0] = qtrans->s.bcmd;
888  ab[1] = 'N';
889
890  switch (qinfo->twhy)
891    {
892    case FAILURE_PERM:
893      ab[2] = '2';
894      break;
895    case FAILURE_OPEN:
896      ab[2] = '4';
897      break;
898    case FAILURE_SIZE:
899      ab[2] = '6';
900      break;
901    case FAILURE_RECEIVED:
902      /* Remember this file as though we successfully received it;
903	 when the other side acknowledges our rejection, we know that
904	 we no longer have to remember that we received this file.  */
905      usent_receive_ack (qdaemon, qtrans);
906      ab[2] = '8';
907      break;
908    default:
909      ab[2] = '\0';
910      break;
911    }
912
913  ab[3] = '\0';
914
915  ilocal = qtrans->ilocal;
916  iremote = qtrans->iremote;
917
918  /* Wait for the end of file marker if we haven't gotten it yet.  */
919  if (! qinfo->freceived)
920    {
921      qinfo->fsent = TRUE;
922      if (! fqueue_receive (qdaemon, qtrans))
923	return FALSE;
924    }
925  else
926    {
927      xfree (qtrans->pinfo);
928      utransfree (qtrans);
929    }
930
931  return (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, ilocal, iremote);
932}
933
934/* Discard data until we reach the end of the file.  This is used for
935   a protocol with multiple channels, since the remote system may
936   start sending the file before the confirmation is sent.  If we
937   refuse the file, the remote system will get us back in synch by
938   sending an empty buffer, which is what we look for here.  */
939
940/*ARGSUSED*/
941static boolean
942fremote_discard (qtrans, qdaemon, zdata, cdata)
943     struct stransfer *qtrans;
944     struct sdaemon *qdaemon ATTRIBUTE_UNUSED;
945     const char *zdata ATTRIBUTE_UNUSED;
946     size_t cdata;
947{
948  struct srecfailinfo *qinfo = (struct srecfailinfo *) qtrans->pinfo;
949
950  DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
951		  "fremote_discard: Discarding %lu bytes",
952		  (unsigned long) cdata);
953
954  if (cdata != 0)
955    return TRUE;
956
957  qinfo->freceived = TRUE;
958
959  /* If we have already sent the denial, we are done.  */
960  if (qinfo->fsent)
961    {
962      xfree (qtrans->pinfo);
963      utransfree (qtrans);
964    }
965
966  return TRUE;
967}
968
969/* This is called when a file has been completely received.  It sends
970   a response to the remote system.  */
971
972/*ARGSUSED*/
973static boolean
974frec_file_end (qtrans, qdaemon, zdata, cdata)
975     struct stransfer *qtrans;
976     struct sdaemon *qdaemon;
977     const char *zdata ATTRIBUTE_UNUSED;
978     size_t cdata ATTRIBUTE_UNUSED;
979{
980  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
981  char *zalc;
982  const char *zerr;
983  boolean fnever;
984
985  DEBUG_MESSAGE3 (DEBUG_UUCP_PROTO, "frec_file_end: %s to %s (freplied %s)",
986		  qtrans->s.zfrom, qtrans->s.zto,
987		  qinfo->freplied ? "TRUE" : "FALSE");
988
989  if (qdaemon->qproto->pffile != NULL)
990    {
991      boolean fhandled;
992
993      if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, FALSE, FALSE,
994					(long) -1, &fhandled))
995	{
996	  (void) remove (qinfo->ztemp);
997	  urrec_free (qtrans);
998	  return FALSE;
999	}
1000      if (fhandled)
1001	return TRUE;
1002    }
1003
1004  qinfo->freceived = TRUE;
1005
1006  fnever = FALSE;
1007
1008  zalc = NULL;
1009
1010  if (! fsysdep_sync (qtrans->e, qtrans->s.zto))
1011    {
1012      zerr = strerror (errno);
1013      (void) ffileclose (qtrans->e);
1014      qtrans->e = EFILECLOSED;
1015      (void) remove (qinfo->ztemp);
1016    }
1017  else if (! ffileclose (qtrans->e))
1018    {
1019      zerr = strerror (errno);
1020      ulog (LOG_ERROR, "%s: close: %s", qtrans->s.zto, zerr);
1021      (void) remove (qinfo->ztemp);
1022      qtrans->e = EFILECLOSED;
1023    }
1024  else
1025    {
1026      qtrans->e = EFILECLOSED;
1027      if (! fsysdep_move_file (qinfo->ztemp, qinfo->zfile, qinfo->fspool,
1028			       FALSE, ! qinfo->fspool,
1029			       (qinfo->flocal
1030				? qtrans->s.zuser
1031				: (const char *) NULL)))
1032	{
1033	  long cspace;
1034
1035	  /* Keep the temporary file if there is 1.5 times the amount
1036	     of required free space.  This is just a random guess, to
1037	     make an unusual situtation potentially less painful.  */
1038	  cspace = csysdep_bytes_free (qinfo->ztemp);
1039	  if (cspace == -1)
1040	    cspace = FREE_SPACE_DELTA;
1041	  cspace -= (qdaemon->qsys->uuconf_cfree_space
1042		     + qdaemon->qsys->uuconf_cfree_space / 2);
1043	  if (cspace < 0)
1044	    {
1045	      (void) remove (qinfo->ztemp);
1046	      zerr = "could not move to final location";
1047	    }
1048	  else
1049	    {
1050	      const char *az[20];
1051	      int i;
1052
1053	      zalc = zbufalc (sizeof "could not move to final location (left as )"
1054			      + strlen (qinfo->ztemp));
1055	      sprintf (zalc, "could not move to final location (left as %s)",
1056		       qinfo->ztemp);
1057	      zerr = zalc;
1058
1059	      i = 0;
1060	      az[i++] = "The file\n\t";
1061	      az[i++] = qinfo->ztemp;
1062	      az[i++] =
1063		"\nwas saved because the move to the final location failed.\n";
1064	      az[i++] = "See the UUCP logs for more details.\n";
1065	      az[i++] = "The file transfer was from\n\t";
1066	      az[i++] = qdaemon->qsys->uuconf_zname;
1067	      az[i++] = "!";
1068	      az[i++] = qtrans->s.zfrom;
1069	      az[i++] = "\nto\n\t";
1070	      az[i++] = qtrans->s.zto;
1071	      az[i++] = "\nand was requested by\n\t";
1072	      az[i++] = qtrans->s.zuser;
1073	      az[i++] = "\n";
1074	      (void) fsysdep_mail (OWNER, "UUCP temporary file saved", i, az);
1075	    }
1076	  ulog (LOG_ERROR, "%s: %s", qinfo->zfile, zerr);
1077	  fnever = TRUE;
1078	}
1079      else
1080	{
1081	  if (! qinfo->fspool)
1082	    {
1083	      unsigned int imode;
1084
1085	      /* Unless we can change the ownership of the file, the
1086		 only choice to make about these bits is whether to
1087		 set the execute bit or not.  */
1088	      if ((qtrans->s.imode & 0111) != 0)
1089		imode = 0777;
1090	      else
1091		imode = 0666;
1092	      (void) fsysdep_change_mode (qinfo->zfile, imode);
1093	    }
1094
1095	  zerr = NULL;
1096	}
1097    }
1098
1099  ustats (zerr == NULL, qtrans->s.zuser, qdaemon->qsys->uuconf_zname,
1100	  FALSE, qtrans->cbytes, qtrans->isecs, qtrans->imicros,
1101	  qdaemon->fcaller);
1102  qdaemon->creceived += qtrans->cbytes;
1103
1104  if (zerr == NULL)
1105    {
1106      if (qinfo->zmail != NULL && *qinfo->zmail != '\0')
1107	(void) fmail_transfer (TRUE, qtrans->s.zuser, qinfo->zmail,
1108			       (const char *) NULL,
1109			       qtrans->s.zfrom, qdaemon->qsys->uuconf_zname,
1110			       qtrans->s.zto, (const char *) NULL,
1111			       (const char *) NULL);
1112
1113      if (qtrans->s.pseq != NULL)
1114	(void) fsysdep_did_work (qtrans->s.pseq);
1115
1116      if (! qinfo->flocal)
1117	{
1118	  /* Remember that we have received this file, so that if the
1119	     connection drops at this point we won't receive it again.
1120	     We could check the return value here, but if we return
1121	     FALSE we couldn't do anything but drop the connection,
1122	     which would hardly be reasonable.  Instead we trust that
1123	     the administrator will notice and handle any error
1124	     messages, which are very unlikely to occur if everything
1125	     is set up correctly.  */
1126	  (void) fsysdep_remember_reception (qdaemon->qsys, qtrans->s.zto,
1127					     qtrans->s.ztemp);
1128	}
1129    }
1130  else
1131    {
1132      /* If the transfer failed, we send mail if it was requested
1133	 locally and if it can never succeed.  */
1134      if (qinfo->flocal && fnever)
1135	{
1136	  (void) fmail_transfer (FALSE, qtrans->s.zuser, qinfo->zmail,
1137				 zerr, qtrans->s.zfrom,
1138				 qdaemon->qsys->uuconf_zname,
1139				 qtrans->s.zto, (const char *) NULL,
1140				 (const char *) NULL);
1141	  (void) fsysdep_did_work (qtrans->s.pseq);
1142	}
1143    }
1144
1145  ubuffree (zalc);
1146
1147  /* If this is an execution request, we must create the execution
1148     file itself.  */
1149  if (qtrans->s.bcmd == 'E' && zerr == NULL)
1150    {
1151      char *zxqt, *zxqtfile, *ztemp;
1152      FILE *e;
1153      boolean fbad;
1154
1155      /* We get an execution file name by simply replacing the leading
1156	 D in the received file name with an X.  This pretty much
1157	 always has to work since we can always receive a file name
1158	 starting with X, so the system dependent code must be
1159	 prepared to see one.  */
1160      zxqt = zbufcpy (qtrans->s.zto);
1161      zxqt[0] = 'X';
1162      zxqtfile = zsysdep_spool_file_name (qdaemon->qsys, zxqt,
1163					  (pointer) NULL);
1164      ubuffree (zxqt);
1165
1166      if (zxqtfile == NULL)
1167	{
1168	  urrec_free (qtrans);
1169	  return FALSE;
1170	}
1171
1172      /* We have to write via a temporary file, because otherwise
1173	 uuxqt might pick up the file before we have finished writing
1174	 it.  */
1175      e = NULL;
1176      ztemp = zsysdep_receive_temp (qdaemon->qsys, zxqtfile, "D.0",
1177				    (qdaemon->qproto->frestart
1178				     && (qdaemon->ifeatures
1179					 & FEATURE_RESTART) != 0));
1180      if (ztemp != NULL)
1181	e = esysdep_fopen (ztemp, FALSE, FALSE, TRUE);
1182
1183      if (e == NULL)
1184	{
1185	  ubuffree (zxqtfile);
1186	  ubuffree (ztemp);
1187	  urrec_free (qtrans);
1188	  return FALSE;
1189	}
1190
1191      if (! fcmd_needs_quotes (&qtrans->s))
1192	{
1193	  fprintf (e, "U %s %s\n", qtrans->s.zuser,
1194		   qdaemon->qsys->uuconf_zname);
1195	  fprintf (e, "F %s\n", qtrans->s.zto);
1196	  fprintf (e, "I %s\n", qtrans->s.zto);
1197	  if (strchr (qtrans->s.zoptions, 'R') != NULL)
1198	    fprintf (e, "R %s\n", qtrans->s.znotify);
1199	  fprintf (e, "C %s\n", qtrans->s.zcmd);
1200	}
1201      else
1202	{
1203	  char *z1;
1204	  char *z2;
1205
1206	  fprintf (e, "Q\n");
1207
1208	  z1 = zquote_cmd_string (qtrans->s.zuser, FALSE);
1209	  z2 = zquote_cmd_string (qdaemon->qsys->uuconf_zname, FALSE);
1210	  fprintf (e, "U %s %s\n", z1, z2);
1211	  ubuffree (z1);
1212	  ubuffree (z2);
1213
1214	  z1 = zquote_cmd_string (qtrans->s.zto, FALSE);
1215	  fprintf (e, "F %s\n", z1);
1216	  fprintf (e, "I %s\n", z1);
1217	  ubuffree (z1);
1218
1219	  if (strchr (qtrans->s.zoptions, 'R') != NULL)
1220	    {
1221	      z1 = zquote_cmd_string (qtrans->s.znotify, FALSE);
1222	      fprintf (e, "R %s\n", z1);
1223	      ubuffree (z1);
1224	    }
1225
1226	  z1 = zquote_cmd_string (qtrans->s.zcmd, TRUE);
1227	  fprintf (e, "C %s\n", z1);
1228	  ubuffree (z1);
1229	}
1230
1231      if (strchr (qtrans->s.zoptions, 'N') != NULL)
1232	fprintf (e, "N\n");
1233      if (strchr (qtrans->s.zoptions, 'Z') != NULL)
1234	fprintf (e, "Z\n");
1235      if (strchr (qtrans->s.zoptions, 'e') != NULL)
1236	fprintf (e, "e\n");
1237
1238      fbad = FALSE;
1239
1240      if (! fstdiosync (e, ztemp))
1241	{
1242	  (void) fclose (e);
1243	  (void) remove (ztemp);
1244	  fbad = TRUE;
1245	}
1246
1247      if (! fbad)
1248	{
1249	  if (fclose (e) == EOF)
1250	    {
1251	      ulog (LOG_ERROR, "fclose: %s", strerror (errno));
1252	      (void) remove (ztemp);
1253	      fbad = TRUE;
1254	    }
1255	}
1256
1257      if (! fbad)
1258	{
1259	  if (! fsysdep_move_file (ztemp, zxqtfile, TRUE, FALSE, FALSE,
1260				   (const char *) NULL))
1261	    {
1262	      (void) remove (ztemp);
1263	      fbad = TRUE;
1264	    }
1265	}
1266
1267      ubuffree (zxqtfile);
1268      ubuffree (ztemp);
1269
1270      if (fbad)
1271	{
1272	  urrec_free (qtrans);
1273	  return FALSE;
1274	}
1275    }
1276
1277  /* See if we should spawn a uuxqt process.  */
1278  if (zerr == NULL
1279      && (qtrans->s.bcmd == 'E'
1280	  || (qinfo->fspool && qtrans->s.zto[0] == 'X')))
1281    {
1282      ++qdaemon->cxfiles_received;
1283      if (qdaemon->irunuuxqt > 0
1284	  && qdaemon->cxfiles_received >= qdaemon->irunuuxqt)
1285	{
1286	  if (fspawn_uuxqt (TRUE, qdaemon->qsys->uuconf_zname,
1287			    qdaemon->zconfig))
1288	    qdaemon->cxfiles_received = 0;
1289	}
1290    }
1291
1292  /* Prepare to send the completion string to the remote system.  If
1293     we have not yet replied to the remote send request, we leave the
1294     transfer structure on the remote queue.  Otherwise we add it to
1295     the send queue.  The psendfn field will already be set.  */
1296  qinfo->fmoved = zerr == NULL;
1297  if (qinfo->freplied)
1298    return fqueue_send (qdaemon, qtrans);
1299
1300  return TRUE;
1301}
1302
1303/* Send the final confirmation string to the remote system.  */
1304
1305static boolean
1306frec_file_send_confirm (qtrans, qdaemon)
1307     struct stransfer *qtrans;
1308     struct sdaemon *qdaemon;
1309{
1310  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
1311  const char *zsend;
1312  int ilocal, iremote;
1313
1314  if (! qinfo->fmoved)
1315    zsend = "CN5";
1316  else if (! qdaemon->frequest_hangup)
1317    zsend = "CY";
1318  else
1319    {
1320#if DEBUG > 0
1321      if (qdaemon->fmaster)
1322	ulog (LOG_FATAL, "frec_file_send_confirm: Can't happen");
1323#endif
1324
1325      DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
1326		      "frec_send_file_confirm: Requesting remote to transfer control");
1327      zsend = "CYM";
1328    }
1329
1330  /* If that was a remote command, then, when the confirmation message
1331     is acked, we no longer have to remember that we received that
1332     file.  */
1333  if (! qinfo->flocal && qinfo->fmoved)
1334    usent_receive_ack (qdaemon, qtrans);
1335
1336  ilocal = qtrans->ilocal;
1337  iremote = qtrans->iremote;
1338
1339  urrec_free (qtrans);
1340
1341  return (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, ilocal, iremote);
1342}
1343
1344/* Discard a temporary file if it is not useful.  A temporary file is
1345   useful if it could be used to restart a receive.  This is called if
1346   the connection is lost.  It is only called if qtrans->frecfile is
1347   TRUE.  */
1348
1349boolean
1350frec_discard_temp (qdaemon, qtrans)
1351     struct sdaemon *qdaemon;
1352     struct stransfer *qtrans;
1353{
1354  struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
1355
1356  if ((qdaemon->ifeatures & FEATURE_RESTART) == 0
1357      || qtrans->s.ztemp == NULL
1358      || qtrans->s.ztemp[0] != 'D'
1359      || strcmp (qtrans->s.ztemp, "D.0") == 0)
1360    (void) remove (qinfo->ztemp);
1361  return TRUE;
1362}
1363