|
|
1.1 root 1: /* rec.c
2: Routines to receive a file.
3:
4: Copyright (C) 1991, 1992 Ian Lance Taylor
5:
6: This file is part of the Taylor UUCP package.
7:
8: This program is free software; you can redistribute it and/or
9: modify it under the terms of the GNU General Public License as
10: published by the Free Software Foundation; either version 2 of the
11: License, or (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16: General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21:
22: The author of the program may be contacted at [email protected] or
23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24: */
25:
26: #include "uucp.h"
27:
28: #if USE_RCS_ID
29: const char rec_rcsid[] = "$Id: rec.c,v 1.1 93/07/30 07:53:56 bin Exp Locker: bin $";
30: #endif
31:
32: #include <errno.h>
33:
34: #include "uudefs.h"
35: #include "uuconf.h"
36: #include "system.h"
37: #include "prot.h"
38: #include "trans.h"
39:
40: /* If the other side does not tell us the size of a file it wants to
41: send us, we assume it is this long. This is only used for free
42: space checking. */
43: #define CASSUMED_FILE_SIZE (10240)
44:
45: /* We keep this information in the pinfo field of the stransfer
46: structure. */
47: struct srecinfo
48: {
49: /* Local user to send mail to (may be NULL). */
50: char *zmail;
51: /* Full file name. */
52: char *zfile;
53: /* Temporary file name. */
54: char *ztemp;
55: /* TRUE if this is a spool directory file. */
56: boolean fspool;
57: /* TRUE if this was a local request. */
58: boolean flocal;
59: /* TRUE if the file has been completely received. */
60: boolean freceived;
61: /* TRUE if remote request has been replied to. */
62: boolean freplied;
63: /* TRUE if we moved the file to the final destination. */
64: boolean fmoved;
65: };
66:
67: /* This structure is kept in the pinfo field if we are refusing a
68: remote request. */
69: struct srecfailinfo
70: {
71: /* Reason for refusal. */
72: enum tfailure twhy;
73: /* TRUE if we have sent the reason for refusal. */
74: boolean fsent;
75: /* TRUE if we have seen the end of the file. */
76: boolean freceived;
77: };
78:
79: /* Local functions. */
80:
81: static void urrec_free P((struct stransfer *qtrans));
82: static boolean flocal_rec_fail P((struct stransfer *qtrans,
83: struct scmd *qcmd,
84: const struct uuconf_system *qsys,
85: const char *zwhy));
86: static boolean flocal_rec_send_request P((struct stransfer *qtrans,
87: struct sdaemon *qdaemon));
88: static boolean flocal_rec_await_reply P((struct stransfer *qtrans,
89: struct sdaemon *qdaemon,
90: const char *zdata,
91: size_t cdata));
92: static boolean fremote_send_reply P((struct stransfer *qtrans,
93: struct sdaemon *qdaemon));
94: static boolean fremote_send_fail P((struct sdaemon *qdaemon,
95: struct scmd *qcmd,
96: enum tfailure twhy,
97: int iremote));
98: static boolean fremote_send_fail_send P((struct stransfer *qtrans,
99: struct sdaemon *qdaemon));
100: static boolean fremote_discard P((struct stransfer *qtrans,
101: struct sdaemon *qdaemon,
102: const char *zdata, size_t cdata));
103: static boolean frec_file_end P((struct stransfer *qtrans,
104: struct sdaemon *qdaemon,
105: const char *zdata, size_t cdata));
106: static boolean frec_file_send_confirm P((struct stransfer *qtrans,
107: struct sdaemon *qdaemon));
108:
109: /* Free up a receive stransfer structure. */
110:
111: static void
112: urrec_free (qtrans)
113: struct stransfer *qtrans;
114: {
115: struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
116:
117: if (qinfo != NULL)
118: {
119: ubuffree (qinfo->zmail);
120: ubuffree (qinfo->zfile);
121: ubuffree (qinfo->ztemp);
122: xfree (qtrans->pinfo);
123: }
124:
125: utransfree (qtrans);
126: }
127:
128: /* Set up a request for a file from the remote system. This may be
129: called before the remote system has been called.
130:
131: This is the order of function calls:
132:
133: flocal_rec_file_init --> fqueue_local
134: flocal_rec_send_request (send R ...) --> fqueue_receive
135: flocal_rec_await_reply (open file, call pffile) --> fqueue_receive
136: receive file
137: frec_file_end (close and move file, call pffile) --> fqueue_send
138: frec_file_send_confirm (send CY)
139: */
140:
141: boolean
142: flocal_rec_file_init (qdaemon, qcmd)
143: struct sdaemon *qdaemon;
144: struct scmd *qcmd;
145: {
146: const struct uuconf_system *qsys;
147: boolean fspool;
148: char *zfile;
149: struct srecinfo *qinfo;
150: struct stransfer *qtrans;
151:
152: qsys = qdaemon->qsys;
153:
154: /* Make sure we are permitted to transfer files. */
155: if (qdaemon->fcaller
156: ? ! qsys->uuconf_fcall_transfer
157: : ! qsys->uuconf_fcalled_transfer)
158: {
159: /* This case will have been checked by uucp or uux, but it could
160: have changed. */
161: if (! qsys->uuconf_fcall_transfer
162: && ! qsys->uuconf_fcalled_transfer)
163: return flocal_rec_fail ((struct stransfer *) NULL, qcmd, qsys,
164: "not permitted to request files");
165: return TRUE;
166: }
167:
168: fspool = fspool_file (qcmd->zto);
169:
170: if (fspool)
171: {
172: pointer puuconf;
173: int iuuconf;
174: const char *zlocalname;
175: struct uuconf_system slocalsys;
176:
177: /* Normal users are not allowed to request files to be received
178: into the spool directory. To support uux forwarding, we use
179: the special option '9'. This permits a file to be received
180: into the spool directory for the local system only without
181: the usual checking. This is only done for local requests, of
182: course. */
183: if (qcmd->zto[0] != 'D'
184: || strchr (qcmd->zoptions, '9') == NULL)
185: return flocal_rec_fail ((struct stransfer *) NULL, qcmd, qsys,
186: "not permitted to receive");
187:
188: puuconf = qdaemon->puuconf;
189: iuuconf = uuconf_localname (puuconf, &zlocalname);
190: if (iuuconf == UUCONF_NOT_FOUND)
191: {
192: zlocalname = zsysdep_localname ();
193: if (zlocalname == NULL)
194: return FALSE;
195: }
196: else if (iuuconf != UUCONF_SUCCESS)
197: {
198: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
199: return FALSE;
200: }
201:
202: iuuconf = uuconf_system_info (puuconf, zlocalname, &slocalsys);
203: if (iuuconf == UUCONF_NOT_FOUND)
204: {
205: iuuconf = uuconf_system_local (puuconf, &slocalsys);
206: if (iuuconf != UUCONF_SUCCESS)
207: {
208: ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
209: return FALSE;
210: }
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
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
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: size_t clen;
307: char *zsend;
308: boolean fret;
309:
310: qinfo->ztemp = zsysdep_receive_temp (qdaemon->qsys, qinfo->zfile,
311: (const char *) NULL);
312: if (qinfo->ztemp == NULL)
313: {
314: urrec_free (qtrans);
315: return FALSE;
316: }
317:
318: /* Check the amount of free space available for both the temporary
319: file and the real file. */
320: cbytes = csysdep_bytes_free (qinfo->ztemp);
321: cbytes2 = csysdep_bytes_free (qinfo->zfile);
322: if (cbytes < cbytes2)
323: cbytes = cbytes2;
324: if (cbytes != -1)
325: {
326: cbytes -= qdaemon->qsys->uuconf_cfree_space;
327: if (cbytes < 0)
328: cbytes = 0;
329: }
330:
331: if (qdaemon->clocal_size != -1
332: && (cbytes == -1 || qdaemon->clocal_size < cbytes))
333: cbytes = qdaemon->clocal_size;
334:
335: /* We send the string
336: R from to user options
337:
338: We put a dash in front of options. If we are talking to a
339: counterpart, we also send the maximum size file we are prepared
340: to accept, as returned by esysdep_open_receive. */
341: clen = (strlen (qtrans->s.zfrom) + strlen (qtrans->s.zto)
342: + strlen (qtrans->s.zuser) + strlen (qtrans->s.zoptions) + 30);
343: zsend = zbufalc (clen);
344: if ((qdaemon->ifeatures & FEATURE_SIZES) == 0)
345: sprintf (zsend, "R %s %s %s -%s", qtrans->s.zfrom, qtrans->s.zto,
346: qtrans->s.zuser, qtrans->s.zoptions);
347: else if ((qdaemon->ifeatures & FEATURE_V103) == 0)
348: sprintf (zsend, "R %s %s %s -%s 0x%lx", qtrans->s.zfrom, qtrans->s.zto,
349: qtrans->s.zuser, qtrans->s.zoptions, (unsigned long) cbytes);
350: else
351: sprintf (zsend, "R %s %s %s -%s %ld", qtrans->s.zfrom, qtrans->s.zto,
352: qtrans->s.zuser, qtrans->s.zoptions, cbytes);
353:
354: fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
355: qtrans->iremote);
356: ubuffree (zsend);
357: if (! fret)
358: {
359: urrec_free (qtrans);
360: return FALSE;
361: }
362:
363: qtrans->fcmd = TRUE;
364: qtrans->precfn = flocal_rec_await_reply;
365:
366: return fqueue_receive (qdaemon, qtrans);
367: }
368:
369: /* This is called when a reply is received for the request. */
370:
371: /*ARGSUSED*/
372: static boolean
373: flocal_rec_await_reply (qtrans, qdaemon, zdata, cdata)
374: struct stransfer *qtrans;
375: struct sdaemon *qdaemon;
376: const char *zdata;
377: size_t cdata;
378: {
379: struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
380: long crestart;
381: const char *zlog;
382:
383: if (zdata[0] != 'R'
384: || (zdata[1] != 'Y' && zdata[1] != 'N'))
385: {
386: ulog (LOG_ERROR, "%s: bad response to receive request: \"%s\"",
387: qtrans->s.zfrom, zdata);
388: urrec_free (qtrans);
389: return FALSE;
390: }
391:
392: if (zdata[1] == 'N')
393: {
394: boolean fnever;
395: const char *zerr;
396:
397: fnever = TRUE;
398: if (zdata[2] == '2')
399: zerr = "no such file";
400: else if (zdata[2] == '6')
401: {
402: /* We sent over the maximum file size we were prepared to
403: receive, and the remote system is telling us that the
404: file is larger than that. Try again later. It would be
405: better if we could know whether there will ever be enough
406: room. */
407: zerr = "too large to receive now";
408: fnever = FALSE;
409: }
410: else
411: zerr = "unknown reason";
412:
413: if (fnever)
414: return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys, zerr);
415:
416: ulog (LOG_ERROR, "%s: %s", qtrans->s.zfrom, zerr);
417:
418: urrec_free (qtrans);
419:
420: return TRUE;
421: }
422:
423: /* The mode should have been sent as "RY 0%o". If it wasn't, we use
424: 0666. */
425: qtrans->s.imode = (unsigned int) strtol ((char *) (zdata + 2),
426: (char **) NULL, 8);
427: if (qtrans->s.imode == 0)
428: qtrans->s.imode = 0666;
429:
430: /* Open the file to receive into. We just ignore any restart count,
431: since we have no way to tell it to the other side. SVR4 may have
432: some way to do this, but I don't know what it is. */
433: qtrans->e = esysdep_open_receive (qdaemon->qsys, qinfo->zfile,
434: (const char *) NULL, qinfo->ztemp,
435: &crestart);
436: if (! ffileisopen (qtrans->e))
437: return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys,
438: "cannot open file");
439:
440: if (qinfo->fspool)
441: zlog = qtrans->s.zto;
442: else
443: zlog = qinfo->zfile;
444: qtrans->zlog = zbufalc (sizeof "Receiving " + strlen (zlog));
445: sprintf (qtrans->zlog, "Receiving %s", zlog);
446:
447: if (qdaemon->qproto->pffile != NULL)
448: {
449: boolean fhandled;
450:
451: if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, FALSE,
452: (long) -1, &fhandled))
453: {
454: (void) ffileclose (qtrans->e);
455: return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys,
456: (const char *) NULL);
457: }
458: if (fhandled)
459: return TRUE;
460: }
461:
462: qtrans->frecfile = TRUE;
463: qtrans->psendfn = frec_file_send_confirm;
464: qtrans->precfn = frec_file_end;
465:
466: return fqueue_receive (qdaemon, qtrans);
467: }
468:
469: /* Make sure there is still enough disk space available to receive a
470: file. */
471:
472: boolean
473: frec_check_free (qtrans, cfree_space)
474: struct stransfer *qtrans;
475: long cfree_space;
476: {
477: struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
478: long cfree1, cfree2;
479:
480: cfree1 = csysdep_bytes_free (qinfo->ztemp);
481: cfree2 = csysdep_bytes_free (qinfo->zfile);
482: if (cfree1 < cfree2)
483: cfree1 = cfree2;
484: if (cfree1 != -1 && cfree1 < cfree_space)
485: {
486: ulog (LOG_ERROR, "%s: too big to receive now", qinfo->zfile);
487: return FALSE;
488: }
489:
490: return TRUE;
491: }
492:
493: /* A remote request to send a file to the local system, meaning that
494: we are going to receive a file.
495:
496: If we are using a protocol which does not support multiple
497: channels, the remote system will not start sending us the file
498: until it has received our confirmation. In that case, the order of
499: functions is as follows:
500:
501: fremote_send_file_init (open file) --> fqueue_remote
502: fremote_send_reply (send SY, call pffile) --> fqueue_receive
503: receive file
504: frec_file_end (close and move file, call pffile) --> fqueue_send
505: frec_file_send_confirm (send CY)
506:
507: If the protocol supports multiple channels, then the remote system
508: will start sending the file immediately after the send request.
509: That means that the data may come in before remote_send_reply is
510: called, so frec_file_end may be called before fremote_send_reply.
511: Note that this means the pffile entry points may be called in
512: reverse order for such a protocol.
513:
514: If the send request is rejected, via fremote_send_fail, and the
515: protocol supports multiple channels, we must accept and discard
516: data until a zero byte buffer is received from the other side,
517: indicating that it has received our rejection.
518:
519: This code also handles execution requests, which are very similar
520: to send requests. */
521:
522: boolean
523: fremote_send_file_init (qdaemon, qcmd, iremote)
524: struct sdaemon *qdaemon;
525: struct scmd *qcmd;
526: int iremote;
527: {
528: const struct uuconf_system *qsys;
529: boolean fspool;
530: char *zfile;
531: openfile_t e;
532: char *ztemp;
533: long cbytes, cbytes2;
534: long crestart;
535: struct srecinfo *qinfo;
536: struct stransfer *qtrans;
537: const char *zlog;
538:
539: qsys = qdaemon->qsys;
540:
541: if (! qsys->uuconf_frec_request)
542: {
543: ulog (LOG_ERROR, "%s: not permitted to receive files from remote",
544: qcmd->zfrom);
545: return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
546: }
547:
548: fspool = fspool_file (qcmd->zto);
549:
550: /* We don't accept remote command files. An execution request may
551: only send a simple data file. */
552: if ((fspool && qcmd->zto[0] == 'C')
553: || (qcmd->bcmd == 'E'
554: && (! fspool || qcmd->zto[0] != 'D')))
555: {
556: ulog (LOG_ERROR, "%s: not permitted to receive", qcmd->zfrom);
557: return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
558: }
559:
560: /* See if we have already received this file in a previous
561: conversation. */
562: if (fsysdep_already_received (qsys, qcmd->zto, qcmd->ztemp))
563: return fremote_send_fail (qdaemon, qcmd, FAILURE_RECEIVED, iremote);
564:
565: if (fspool)
566: {
567: zfile = zsysdep_spool_file_name (qsys, qcmd->zto, (pointer) NULL);
568: if (zfile == NULL)
569: return FALSE;
570: }
571: else
572: {
573: zfile = zsysdep_local_file (qcmd->zto, qsys->uuconf_zpubdir);
574: if (zfile != NULL)
575: {
576: char *zadd;
577:
578: zadd = zsysdep_add_base (zfile, qcmd->zfrom);
579: ubuffree (zfile);
580: zfile = zadd;
581: }
582: if (zfile == NULL)
583: return FALSE;
584:
585: /* Check permissions. */
586: if (! fin_directory_list (zfile, qsys->uuconf_pzremote_receive,
587: qsys->uuconf_zpubdir, TRUE,
588: FALSE, (const char *) NULL))
589: {
590: ulog (LOG_ERROR, "%s: not permitted to receive", zfile);
591: ubuffree (zfile);
592: return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
593: }
594:
595: if (strchr (qcmd->zoptions, 'f') == NULL)
596: {
597: if (! fsysdep_make_dirs (zfile, TRUE))
598: {
599: ubuffree (zfile);
600: return fremote_send_fail (qdaemon, qcmd, FAILURE_OPEN,
601: iremote);
602: }
603: }
604: }
605:
606: ztemp = zsysdep_receive_temp (qsys, zfile, qcmd->ztemp);
607:
608: /* Adjust the number of bytes we are prepared to receive according
609: to the amount of free space we are supposed to leave available
610: and the maximum file size we are permitted to transfer. */
611: cbytes = csysdep_bytes_free (ztemp);
612: cbytes2 = csysdep_bytes_free (zfile);
613: if (cbytes < cbytes2)
614: cbytes = cbytes2;
615:
616: if (cbytes != -1)
617: {
618: cbytes -= qsys->uuconf_cfree_space;
619: if (cbytes < 0)
620: cbytes = 0;
621: }
622:
623: if (qdaemon->cremote_size != -1
624: && (cbytes == -1 || qdaemon->cremote_size < cbytes))
625: cbytes = qdaemon->cremote_size;
626:
627: /* If the number of bytes we are prepared to receive is less than
628: the file size, we must fail. If the remote did not tell us the
629: file size, arbitrarily assumed that it is 10240 bytes. */
630: if (cbytes != -1)
631: {
632: long csize;
633:
634: csize = qcmd->cbytes;
635: if (csize == -1)
636: csize = CASSUMED_FILE_SIZE;
637: if (cbytes < csize)
638: {
639: ulog (LOG_ERROR, "%s: too big to receive", zfile);
640: ubuffree (ztemp);
641: ubuffree (zfile);
642: return fremote_send_fail (qdaemon, qcmd, FAILURE_SIZE, iremote);
643: }
644: }
645:
646: /* Open the file to receive into. This may find an old copy of the
647: file, which will be used for file restart if the other side
648: supports it. */
649: e = esysdep_open_receive (qsys, zfile, qcmd->ztemp, ztemp, &crestart);
650: if (! ffileisopen (e))
651: {
652: ubuffree (ztemp);
653: ubuffree (zfile);
654: return fremote_send_fail (qdaemon, qcmd, FAILURE_OPEN, iremote);
655: }
656:
657: if (crestart > 0)
658: {
659: if ((qdaemon->ifeatures & FEATURE_RESTART) == 0)
660: crestart = -1;
661: else
662: {
663: DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
664: "fremote_send_file_init: Restarting receive from %ld",
665: crestart);
666: if (! ffileseek (e, crestart))
667: {
668: ulog (LOG_ERROR, "seek: %s", strerror (errno));
669: (void) ffileclose (e);
670: ubuffree (ztemp);
671: ubuffree (zfile);
672: return FALSE;
673: }
674: }
675: }
676:
677: qinfo = (struct srecinfo *) xmalloc (sizeof (struct srecinfo));
678: if (strchr (qcmd->zoptions, 'n') == NULL)
679: qinfo->zmail = NULL;
680: else
681: qinfo->zmail = zbufcpy (qcmd->znotify);
682: qinfo->zfile = zfile;
683: qinfo->ztemp = ztemp;
684: qinfo->fspool = fspool;
685: qinfo->flocal = FALSE;
686: qinfo->freceived = FALSE;
687: qinfo->freplied = FALSE;
688:
689: qtrans = qtransalc (qcmd);
690: qtrans->psendfn = fremote_send_reply;
691: qtrans->precfn = frec_file_end;
692: qtrans->iremote = iremote;
693: qtrans->pinfo = (pointer) qinfo;
694: qtrans->frecfile = TRUE;
695: qtrans->e = e;
696: if (crestart > 0)
697: qtrans->ipos = crestart;
698:
699: if (qcmd->bcmd == 'E')
700: zlog = qcmd->zcmd;
701: else
702: {
703: if (qinfo->fspool)
704: zlog = qcmd->zto;
705: else
706: zlog = qinfo->zfile;
707: }
708: qtrans->zlog = zbufalc (sizeof "Receiving " + strlen (zlog));
709: sprintf (qtrans->zlog, "Receiving %s", zlog);
710:
711: return fqueue_remote (qdaemon, qtrans);
712: }
713:
714: /* Reply to a send request, and prepare to receive the file. */
715:
716: static boolean
717: fremote_send_reply (qtrans, qdaemon)
718: struct stransfer *qtrans;
719: struct sdaemon *qdaemon;
720: {
721: struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
722: char ab[50];
723:
724: ab[0] = qtrans->s.bcmd;
725: ab[1] = 'Y';
726: if (qtrans->ipos <= 0)
727: ab[2] = '\0';
728: else
729: sprintf (ab + 2, " 0x%lx", (unsigned long) qtrans->ipos);
730:
731: if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, qtrans->ilocal,
732: qtrans->iremote))
733: {
734: (void) ffileclose (qtrans->e);
735: (void) remove (qinfo->ztemp);
736: urrec_free (qtrans);
737: return FALSE;
738: }
739:
740: qinfo->freplied = TRUE;
741:
742: if (qdaemon->qproto->pffile != NULL)
743: {
744: boolean fhandled;
745:
746: if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, FALSE,
747: (long) -1, &fhandled))
748: {
749: (void) ffileclose (qtrans->e);
750: (void) remove (qinfo->ztemp);
751: urrec_free (qtrans);
752: return FALSE;
753: }
754: if (fhandled)
755: return TRUE;
756: }
757:
758: /* If the file has been completely received, we just want to send
759: the final confirmation. Otherwise, we must wait for the file
760: first. */
761: qtrans->psendfn = frec_file_send_confirm;
762: if (qinfo->freceived)
763: return fqueue_send (qdaemon, qtrans);
764: else
765: return fqueue_receive (qdaemon, qtrans);
766: }
767:
768: /* If we can't receive a file, queue up a response to the remote
769: system. */
770:
771: static boolean
772: fremote_send_fail (qdaemon, qcmd, twhy, iremote)
773: struct sdaemon *qdaemon;
774: struct scmd *qcmd;
775: enum tfailure twhy;
776: int iremote;
777: {
778: struct srecfailinfo *qinfo;
779: struct stransfer *qtrans;
780:
781: qinfo = (struct srecfailinfo *) xmalloc (sizeof (struct srecfailinfo));
782: qinfo->twhy = twhy;
783: qinfo->fsent = FALSE;
784:
785: /* If the protocol does not support multiple channels (cchans <= 1),
786: then we have essentially already received the entire file. */
787: qinfo->freceived = qdaemon->qproto->cchans <= 1;
788:
789: qtrans = qtransalc (qcmd);
790: qtrans->psendfn = fremote_send_fail_send;
791: qtrans->precfn = fremote_discard;
792: qtrans->iremote = iremote;
793: qtrans->pinfo = (pointer) qinfo;
794:
795: return fqueue_remote (qdaemon, qtrans);
796: }
797:
798: /* Send a failure string for a send command to the remote system;
799: this is called when we are ready to reply to the command. */
800:
801: static boolean
802: fremote_send_fail_send (qtrans, qdaemon)
803: struct stransfer *qtrans;
804: struct sdaemon *qdaemon;
805: {
806: struct srecfailinfo *qinfo = (struct srecfailinfo *) qtrans->pinfo;
807: char ab[4];
808: boolean fret;
809:
810: ab[0] = qtrans->s.bcmd;
811: ab[1] = 'N';
812:
813: switch (qinfo->twhy)
814: {
815: case FAILURE_PERM:
816: ab[2] = '2';
817: break;
818: case FAILURE_OPEN:
819: ab[2] = '4';
820: break;
821: case FAILURE_SIZE:
822: ab[2] = '6';
823: break;
824: case FAILURE_RECEIVED:
825: /* Remember this file as though we successfully received it;
826: when the other side acknowledges our rejection, we know that
827: we no longer have to remember that we received this file. */
828: usent_receive_ack (qdaemon, qtrans);
829: ab[2] = '8';
830: break;
831: default:
832: ab[2] = '\0';
833: break;
834: }
835:
836: ab[3] = '\0';
837:
838: fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, qtrans->ilocal,
839: qtrans->iremote);
840:
841: qinfo->fsent = TRUE;
842:
843: /* Wait for the end of file marker if we haven't gotten it yet. */
844: if (! qinfo->freceived)
845: {
846: if (! fqueue_receive (qdaemon, qtrans))
847: fret = FALSE;
848: }
849: else
850: {
851: xfree (qtrans->pinfo);
852: utransfree (qtrans);
853: }
854:
855: return fret;
856: }
857:
858: /* Discard data until we reach the end of the file. This is used for
859: a protocol with multiple channels, since the remote system may
860: start sending the file before the confirmation is sent. If we
861: refuse the file, the remote system will get us back in synch by
862: sending an empty buffer, which is what we look for here. */
863:
864: /*ARGSUSED*/
865: static boolean
866: fremote_discard (qtrans, qdaemon, zdata, cdata)
867: struct stransfer *qtrans;
868: struct sdaemon *qdaemon;
869: const char *zdata;
870: size_t cdata;
871: {
872: struct srecfailinfo *qinfo = (struct srecfailinfo *) qtrans->pinfo;
873:
874: DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
875: "fremote_discard: Discarding %lu bytes",
876: (unsigned long) cdata);
877:
878: if (cdata != 0)
879: return TRUE;
880:
881: qinfo->freceived = TRUE;
882:
883: /* If we have already sent the denial, we are done. */
884: if (qinfo->fsent)
885: {
886: xfree (qtrans->pinfo);
887: utransfree (qtrans);
888: }
889:
890: return TRUE;
891: }
892:
893: /* This is called when a file has been completely received. It sends
894: a response to the remote system. */
895:
896: /*ARGSUSED*/
897: static boolean
898: frec_file_end (qtrans, qdaemon, zdata, cdata)
899: struct stransfer *qtrans;
900: struct sdaemon *qdaemon;
901: const char *zdata;
902: size_t cdata;
903: {
904: struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
905: const char *zerr;
906: boolean fnever;
907:
908: DEBUG_MESSAGE3 (DEBUG_UUCP_PROTO, "frec_file_end: %s to %s (freplied %s)",
909: qtrans->s.zfrom, qtrans->s.zto,
910: qinfo->freplied ? "TRUE" : "FALSE");
911:
912: if (qdaemon->qproto->pffile != NULL)
913: {
914: boolean fhandled;
915:
916: if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, FALSE, FALSE,
917: (long) -1, &fhandled))
918: {
919: (void) ffileclose (qtrans->e);
920: (void) remove (qinfo->ztemp);
921: urrec_free (qtrans);
922: return FALSE;
923: }
924: if (fhandled)
925: return TRUE;
926: }
927:
928: qinfo->freceived = TRUE;
929:
930: fnever = FALSE;
931:
932: if (! ffileclose (qtrans->e))
933: {
934: zerr = strerror (errno);
935: ulog (LOG_ERROR, "%s: close: %s", qtrans->s.zto, zerr);
936: }
937: else if (! fsysdep_move_file (qinfo->ztemp, qinfo->zfile, qinfo->fspool,
938: FALSE, ! qinfo->fspool,
939: (qinfo->flocal
940: ? qtrans->s.zuser
941: : (const char *) NULL)))
942: {
943: zerr = "could not move to final location";
944: ulog (LOG_ERROR, "%s: %s", qinfo->zfile, zerr);
945: fnever = TRUE;
946: }
947: else
948: {
949: if (! qinfo->fspool)
950: {
951: unsigned int imode;
952:
953: /* Unless we can change the ownership of the file, the only
954: choice to make about these bits is whether to set the
955: execute bit or not. */
956: if ((qtrans->s.imode & 0111) != 0)
957: imode = 0777;
958: else
959: imode = 0666;
960: (void) fsysdep_change_mode (qinfo->zfile, imode);
961: }
962:
963: zerr = NULL;
964: }
965:
966: if (zerr != NULL)
967: (void) remove (qinfo->ztemp);
968:
969: ustats (zerr == NULL, qtrans->s.zuser, qdaemon->qsys->uuconf_zname,
970: FALSE, qtrans->cbytes, qtrans->isecs, qtrans->imicros,
971: qdaemon->fmaster);
972:
973: if (zerr == NULL)
974: {
975: if (qinfo->zmail != NULL && *qinfo->zmail != '\0')
976: (void) fmail_transfer (TRUE, qtrans->s.zuser, qinfo->zmail,
977: (const char *) NULL,
978: qtrans->s.zfrom, qdaemon->qsys->uuconf_zname,
979: qtrans->s.zto, (const char *) NULL,
980: (const char *) NULL);
981:
982: if (qtrans->s.pseq != NULL)
983: (void) fsysdep_did_work (qtrans->s.pseq);
984:
985: if (! qinfo->flocal)
986: {
987: /* Remember that we have received this file, so that if the
988: connection drops at this point we won't receive it again.
989: We could check the return value here, but if we return
990: FALSE we couldn't do anything but drop the connection,
991: which would hardly be reasonable. Instead we trust that
992: the administrator will notice and handle any error
993: messages, which are very unlikely to occur if everything
994: is set up correctly. */
995: (void) fsysdep_remember_reception (qdaemon->qsys, qtrans->s.zto,
996: qtrans->s.ztemp);
997: }
998: }
999: else
1000: {
1001: /* If the transfer failed, we send mail if it was requested
1002: locally and if it can never succeed. */
1003: if (qinfo->flocal && fnever)
1004: {
1005: (void) fmail_transfer (FALSE, qtrans->s.zuser, qinfo->zmail,
1006: zerr, qtrans->s.zfrom,
1007: qdaemon->qsys->uuconf_zname,
1008: qtrans->s.zto, (const char *) NULL,
1009: (const char *) NULL);
1010: (void) fsysdep_did_work (qtrans->s.pseq);
1011: }
1012: }
1013:
1014: /* If this is an execution request, we must create the execution
1015: file itself. */
1016: if (qtrans->s.bcmd == 'E' && zerr == NULL)
1017: {
1018: char *zxqt, *zxqtfile, *ztemp;
1019: FILE *e;
1020: boolean fbad;
1021:
1022: /* We get an execution file name by simply replacing the leading
1023: D in the received file name with an X. This pretty much
1024: always has to work since we can always receive a file name
1025: starting with X, so the system dependent code must be
1026: prepared to see one. */
1027: zxqt = zbufcpy (qtrans->s.zto);
1028: zxqt[0] = 'X';
1029: zxqtfile = zsysdep_spool_file_name (qdaemon->qsys, zxqt,
1030: (pointer) NULL);
1031: ubuffree (zxqt);
1032:
1033: if (zxqtfile == NULL)
1034: {
1035: urrec_free (qtrans);
1036: return FALSE;
1037: }
1038:
1039: /* We have to write via a temporary file, because otherwise
1040: uuxqt might pick up the file before we have finished writing
1041: it. */
1042: e = NULL;
1043: ztemp = zsysdep_receive_temp (qdaemon->qsys, zxqtfile, "D.0");
1044: if (ztemp != NULL)
1045: e = esysdep_fopen (ztemp, FALSE, FALSE, TRUE);
1046:
1047: if (e == NULL)
1048: {
1049: ubuffree (zxqtfile);
1050: ubuffree (ztemp);
1051: urrec_free (qtrans);
1052: return FALSE;
1053: }
1054:
1055: fprintf (e, "U %s %s\n", qtrans->s.zuser, qdaemon->qsys->uuconf_zname);
1056: fprintf (e, "F %s\n", qtrans->s.zto);
1057: fprintf (e, "I %s\n", qtrans->s.zto);
1058: if (strchr (qtrans->s.zoptions, 'N') != NULL)
1059: fprintf (e, "N\n");
1060: if (strchr (qtrans->s.zoptions, 'Z') != NULL)
1061: fprintf (e, "Z\n");
1062: if (strchr (qtrans->s.zoptions, 'R') != NULL)
1063: fprintf (e, "R %s\n", qtrans->s.znotify);
1064: if (strchr (qtrans->s.zoptions, 'e') != NULL)
1065: fprintf (e, "e\n");
1066: fprintf (e, "C %s\n", qtrans->s.zcmd);
1067:
1068: fbad = FALSE;
1069: if (fclose (e) == EOF)
1070: {
1071: ulog (LOG_ERROR, "fclose: %s", strerror (errno));
1072: (void) remove (ztemp);
1073: fbad = TRUE;
1074: }
1075:
1076: if (! fbad)
1077: {
1078: if (! fsysdep_move_file (ztemp, zxqtfile, TRUE, FALSE, FALSE,
1079: (const char *) NULL))
1080: fbad = TRUE;
1081: }
1082:
1083: ubuffree (zxqtfile);
1084: ubuffree (ztemp);
1085:
1086: if (fbad)
1087: {
1088: urrec_free (qtrans);
1089: return FALSE;
1090: }
1091: }
1092:
1093: /* Prepare to send the completion string to the remote system. If
1094: we have not yet replied to the remote send request, we leave the
1095: transfer structure on the remote queue. Otherwise we add it to
1096: the send queue. The psendfn field will already be set. */
1097: qinfo->fmoved = zerr == NULL;
1098: if (qinfo->freplied)
1099: return fqueue_send (qdaemon, qtrans);
1100:
1101: return TRUE;
1102: }
1103:
1104: /* Send the final confirmation string to the remote system. */
1105:
1106: static boolean
1107: frec_file_send_confirm (qtrans, qdaemon)
1108: struct stransfer *qtrans;
1109: struct sdaemon *qdaemon;
1110: {
1111: struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
1112: const char *zsend;
1113: boolean fret;
1114:
1115: if (! qinfo->fmoved)
1116: zsend = "CN5";
1117: else if (! qdaemon->frequest_hangup)
1118: zsend = "CY";
1119: else
1120: {
1121: #if DEBUG > 0
1122: if (qdaemon->fmaster)
1123: ulog (LOG_FATAL, "frec_file_send_confirm: Can't happen");
1124: #endif
1125:
1126: DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
1127: "frec_send_file_confirm: Requesting remote to transfer control");
1128: zsend = "CYM";
1129: }
1130:
1131: fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend,
1132: qtrans->ilocal, qtrans->iremote);
1133:
1134: /* Now, if that was a remote command, then when the confirmation
1135: message is acked we no longer have to remember that we received
1136: that file. */
1137: if (! qinfo->flocal && qinfo->fmoved)
1138: usent_receive_ack (qdaemon, qtrans);
1139:
1140: urrec_free (qtrans);
1141: return fret;
1142: }
1143:
1144: /* Discard a temporary file if it is not useful. A temporary file is
1145: useful if it could be used to restart a receive. This is called if
1146: the connection is lost. It is only called if qtrans->frecfile is
1147: TRUE. */
1148:
1149: boolean
1150: frec_discard_temp (qdaemon, qtrans)
1151: struct sdaemon *qdaemon;
1152: struct stransfer *qtrans;
1153: {
1154: struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
1155:
1156: if ((qdaemon->ifeatures & FEATURE_RESTART) == 0
1157: || qtrans->s.ztemp == NULL
1158: || qtrans->s.ztemp[0] != 'D'
1159: || strcmp (qtrans->s.ztemp, "D.0") == 0)
1160: (void) remove (qinfo->ztemp);
1161: return TRUE;
1162: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.