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
28 const char rec_rcsid[] = "$FreeBSD$";
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. */
46 struct 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. */
68 struct 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
80 static void urrec_free P((struct stransfer *qtrans));
81 static boolean flocal_rec_fail P((struct stransfer *qtrans,
82 struct scmd *qcmd,
83 const struct uuconf_system *qsys,
84 const char *zwhy));
85 static boolean flocal_rec_send_request P((struct stransfer *qtrans,
86 struct sdaemon *qdaemon));
87 static boolean flocal_rec_await_reply P((struct stransfer *qtrans,
88 struct sdaemon *qdaemon,
89 const char *zdata,
90 size_t cdata));
91 static boolean fremote_send_reply P((struct stransfer *qtrans,
92 struct sdaemon *qdaemon));
93 static boolean fremote_send_fail P((struct sdaemon *qdaemon,
94 struct scmd *qcmd,
95 enum tfailure twhy,
96 int iremote));
97 static boolean fremote_send_fail_send P((struct stransfer *qtrans,
98 struct sdaemon *qdaemon));
99 static boolean fremote_discard P((struct stransfer *qtrans,
100 struct sdaemon *qdaemon,
101 const char *zdata, size_t cdata));
102 static boolean frec_file_end P((struct stransfer *qtrans,
103 struct sdaemon *qdaemon,
104 const char *zdata, size_t cdata));
105 static boolean frec_file_send_confirm P((struct stransfer *qtrans,
106 struct sdaemon *qdaemon));
107
108 /* Free up a receive stransfer structure. */
109
110 static void
urrec_free(qtrans)111 urrec_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
140 boolean
flocal_rec_file_init(qdaemon,qcmd)141 flocal_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
275 static boolean
flocal_rec_fail(qtrans,qcmd,qsys,zwhy)276 flocal_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
299 static boolean
flocal_rec_send_request(qtrans,qdaemon)300 flocal_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*/
399 static boolean
flocal_rec_await_reply(qtrans,qdaemon,zdata,cdata)400 flocal_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
517 boolean
frec_check_free(qtrans,cfree_space)518 frec_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
567 boolean
fremote_send_file_init(qdaemon,qcmd,iremote)568 fremote_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
789 static boolean
fremote_send_reply(qtrans,qdaemon)790 fremote_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
848 static boolean
fremote_send_fail(qdaemon,qcmd,twhy,iremote)849 fremote_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
878 static boolean
fremote_send_fail_send(qtrans,qdaemon)879 fremote_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*/
941 static boolean
fremote_discard(qtrans,qdaemon,zdata,cdata)942 fremote_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*/
973 static boolean
frec_file_end(qtrans,qdaemon,zdata,cdata)974 frec_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
1305 static boolean
frec_file_send_confirm(qtrans,qdaemon)1306 frec_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
1349 boolean
frec_discard_temp(qdaemon,qtrans)1350 frec_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