|
|
1.1 root 1: /* send.c
2: Routines to send 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 send_rcsid[] = "$Id: send.c,v 1.1 93/07/30 07:54:01 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: /* We keep this information in the pinfo field of the stransfer
41: structure. */
42: struct ssendinfo
43: {
44: /* Local user to send mail to (may be NULL). */
45: char *zmail;
46: /* Full file name. */
47: char *zfile;
48: /* Number of bytes in file. */
49: long cbytes;
50: /* TRUE if this was a local request. */
51: boolean flocal;
52: /* TRUE if this is a spool directory file. */
53: boolean fspool;
54: /* TRUE if the file has been completely sent. */
55: boolean fsent;
56: /* Execution file for sending an unsupported E request. */
57: char *zexec;
58: };
59:
60: /* Local functions. */
61:
62: static void usfree_send P((struct stransfer *qtrans));
63: static boolean flocal_send_fail P((struct stransfer *qtrans,
64: struct scmd *qcmd,
65: const struct uuconf_system *qsys,
66: const char *zwhy));
67: static boolean flocal_send_request P((struct stransfer *qtrans,
68: struct sdaemon *qdaemon));
69: static boolean flocal_send_await_reply P((struct stransfer *qtrans,
70: struct sdaemon *qdaemon,
71: const char *zdata, size_t cdata));
72: static boolean flocal_send_cancelled P((struct stransfer *qtrans,
73: struct sdaemon *qdaemon));
74: static boolean flocal_send_open_file P((struct stransfer *qtrans,
75: struct sdaemon *qdaemon));
76: static boolean fremote_rec_fail P((struct sdaemon *qdaemon,
77: enum tfailure twhy, int iremote));
78: static boolean fremote_rec_fail_send P((struct stransfer *qtrans,
79: struct sdaemon *qdaemon));
80: static boolean fremote_rec_reply P((struct stransfer *qtrans,
81: struct sdaemon *qdaemon));
82: static boolean fsend_file_end P((struct stransfer *qtrans,
83: struct sdaemon *qdaemon));
84: static boolean fsend_await_confirm P((struct stransfer *qtrans,
85: struct sdaemon *qdaemon,
86: const char *zdata, size_t cdata));
87: static boolean fsend_exec_file_init P((struct stransfer *qtrans,
88: struct sdaemon *qdaemon));
89: static void usadd_exec_line P((char **pz, size_t *pcalc, size_t *pclen,
90: int bcmd, const char *z1, const char *z2));
91: static boolean fsend_exec_file P((struct stransfer *qtrans,
92: struct sdaemon *qdaemon));
93:
94: /* Free up a send stransfer structure. */
95:
96: static void
97: usfree_send (qtrans)
98: struct stransfer *qtrans;
99: {
100: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
101:
102: if (qinfo != NULL)
103: {
104: ubuffree (qinfo->zmail);
105: ubuffree (qinfo->zfile);
106: ubuffree (qinfo->zexec);
107: xfree (qtrans->pinfo);
108: }
109:
110: utransfree (qtrans);
111: }
112:
113: /* Set up a local request to send a file. This may be called before
114: we have even tried to call the remote system.
115:
116: If we are using a traditional protocol, which doesn't support
117: channel numbers and doesn't permit the file to be sent until an
118: acknowledgement has been received, the sequence of function calls
119: looks like this:
120:
121: flocal_send_file_init --> fqueue_local
122: flocal_send_request (sends S request) --> fqueue_receive
123: flocal_send_await_reply (waits for SY) --> fqueue_send
124: flocal_send_open_file (opens file, calls pffile) --> fqueue_send
125: send file
126: fsend_file_end (calls pffile) --> fqueue_receive
127: fsend_await_confirm (waits for CY)
128:
129: If flocal_send_await_reply gets an SN, it deletes the request. If
130: the SY reply contains a file position at which to start sending,
131: flocal_send_await_reply sets qinfo->ipos.
132:
133: This gets more complex if the protocol supports channels. In that
134: case, we want to start sending the file data immediately, to avoid
135: the round trip delay between flocal_send_request and
136: flocal_send_await_reply. To do this, flocal_send_request calls
137: fqueue_send rather than fqueue_receive. The main execution
138: sequence looks like this:
139:
140: flocal_send_file_init --> fqueue_local
141: flocal_send_request (sends S request) --> fqueue_send
142: flocal_send_open_file (opens file, calls pffile) --> fqueue_send
143: send file
144: fsend_file_end (calls pffile) --> fqueue_receive
145: sometime: flocal_send_await_reply (waits for SY)
146: fsend_await_confirm (waits for CY)
147:
148: In this case flocal_send_await_reply must be run before
149: fsend_await_confirm; it may be run anytime after
150: flocal_send_request.
151:
152: If flocal_send_await_reply is called before the entire file has
153: been sent: if it gets an SN, it calls flocal_send_cancelled to send
154: an empty data block to inform the remote system that the file
155: transfer has stopped. If it gets a file position request, it must
156: adjust the file position accordingly.
157:
158: If flocal_send_await_reply is called after the entire file has been
159: sent: if it gets an SN, it can simply delete the request. It can
160: ignore any file position request.
161:
162: If the request is not deleted, flocal_send_await_reply must arrange
163: for the next string to be passed to fsend_await_confirm.
164: Presumably fsend_await_confirm will only be called after the entire
165: file has been sent.
166:
167: Just to make things even more complex, these same routines support
168: sending execution requests, since that is much like sending a file.
169: For an execution request, the bcmd character will be E rather than
170: S. If an execution request is being sent to a system which does
171: not support them, it must be sent as two S requests instead. The
172: second one will be the execution file, but no actual file is
173: created; instead the zexec and znext fields in the ssendinfo
174: structure are used. So if the bcmd character is E, then if the
175: zexec field is NULL, the data file is being sent, otherwise the
176: fake execution file is being sent. */
177:
178: boolean
179: flocal_send_file_init (qdaemon, qcmd)
180: struct sdaemon *qdaemon;
181: struct scmd *qcmd;
182: {
183: const struct uuconf_system *qsys;
184: boolean fspool;
185: char *zfile;
186: long cbytes;
187: struct ssendinfo *qinfo;
188: struct stransfer *qtrans;
189:
190: qsys = qdaemon->qsys;
191:
192: if (qdaemon->fcaller
193: ? ! qsys->uuconf_fcall_transfer
194: : ! qsys->uuconf_fcalled_transfer)
195: {
196: /* uux or uucp should have already made sure that the transfer
197: is possible, but it might have changed since then. */
198: if (! qsys->uuconf_fcall_transfer
199: && ! qsys->uuconf_fcalled_transfer)
200: return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
201: "not permitted to transfer files");
202:
203: /* We can't do the request now, but it may get done later. */
204: return TRUE;
205: }
206:
207: /* The 'C' option means that the file has been copied to the spool
208: directory. */
209: if (strchr (qcmd->zoptions, 'C') == NULL
210: && ! fspool_file (qcmd->zfrom))
211: {
212: fspool = FALSE;
213: if (! fin_directory_list (qcmd->zfrom,
214: qsys->uuconf_pzlocal_send,
215: qsys->uuconf_zpubdir, TRUE,
216: TRUE, qcmd->zuser))
217: return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
218: "not permitted to send");
219: zfile = zbufcpy (qcmd->zfrom);
220: }
221: else
222: {
223: fspool = TRUE;
224: zfile = zsysdep_spool_file_name (qsys, qcmd->ztemp, qcmd->pseq);
225: if (zfile == NULL)
226: return FALSE;
227: }
228:
229: /* Make sure we meet any local size restrictions. The connection
230: may not have been opened at this point, so we can't check remote
231: size restrictions. */
232: cbytes = csysdep_size (zfile);
233: if (cbytes < 0)
234: {
235: ubuffree (zfile);
236: if (cbytes != -1)
237: return FALSE;
238: /* A cbytes value of -1 means that the file does not exist.
239: This can happen legitimately if it has already been sent from
240: the spool directory. */
241: if (! fspool)
242: return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
243: "does not exist");
244: (void) fsysdep_did_work (qcmd->pseq);
245: return TRUE;
246: }
247:
248: if (qdaemon->clocal_size != -1
249: && qdaemon->clocal_size < cbytes)
250: {
251: ubuffree (zfile);
252:
253: if (qdaemon->cmax_ever == -2)
254: {
255: long c1, c2;
256:
257: c1 = cmax_size_ever (qsys->uuconf_qcall_local_size);
258: c2 = cmax_size_ever (qsys->uuconf_qcalled_local_size);
259: if (c1 > c2)
260: qdaemon->cmax_ever = c1;
261: else
262: qdaemon->cmax_ever = c2;
263: }
264:
265: if (qdaemon->cmax_ever != -1
266: && qdaemon->cmax_ever < qcmd->cbytes)
267: return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
268: "too large to send");
269:
270: return TRUE;
271: }
272:
273: /* We are now prepared to send the command to the remote system. We
274: queue up a transfer request to send the command when we are
275: ready. */
276: qinfo = (struct ssendinfo *) xmalloc (sizeof (struct ssendinfo));
277: if (strchr (qcmd->zoptions, 'm') == NULL)
278: qinfo->zmail = NULL;
279: else
280: qinfo->zmail = zbufcpy (qcmd->zuser);
281: qinfo->zfile = zfile;
282: qinfo->cbytes = cbytes;
283: qinfo->flocal = TRUE;
284: qinfo->fspool = fspool;
285: qinfo->fsent = FALSE;
286: qinfo->zexec = NULL;
287:
288: qtrans = qtransalc (qcmd);
289: qtrans->psendfn = flocal_send_request;
290: qtrans->pinfo = (pointer) qinfo;
291:
292: return fqueue_local (qdaemon, qtrans);
293: }
294:
295: /* Clean up after a failing local send request. If zwhy is not NULL,
296: this reports an error to the log file and to the user. */
297:
298: static boolean
299: flocal_send_fail (qtrans, qcmd, qsys, zwhy)
300: struct stransfer *qtrans;
301: struct scmd *qcmd;
302: const struct uuconf_system *qsys;
303: const char *zwhy;
304: {
305: if (zwhy != NULL)
306: {
307: char *zfree;
308:
309: if (qcmd->bcmd != 'E')
310: zfree = NULL;
311: else
312: {
313: zfree = zbufalc (sizeof "Execution of \"\": "
314: + strlen (qcmd->zcmd)
315: + strlen (zwhy));
316: sprintf (zfree, "Execution of \"%s\": %s", qcmd->zcmd, zwhy);
317: zwhy = zfree;
318: }
319:
320: ulog (LOG_ERROR, "%s: %s", qcmd->zfrom, zwhy);
321: (void) fmail_transfer (FALSE, qcmd->zuser, (const char *) NULL,
322: zwhy, qcmd->zfrom, (const char *) NULL,
323: qcmd->zto, qsys->uuconf_zname,
324: zsysdep_save_temp_file (qcmd->pseq));
325:
326: ubuffree (zfree);
327: }
328:
329: (void) fsysdep_did_work (qcmd->pseq);
330:
331: if (qtrans != NULL)
332: usfree_send (qtrans);
333:
334: return TRUE;
335: }
336:
337: /* This is called when we are ready to send the request to the remote
338: system. We form the request and send it over. If the protocol
339: does not support multiple channels, we start waiting for the
340: response; otherwise we can start sending the file immediately. */
341:
342: static boolean
343: flocal_send_request (qtrans, qdaemon)
344: struct stransfer *qtrans;
345: struct sdaemon *qdaemon;
346: {
347: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
348: char *zsend;
349: const char *znotify;
350: char absize[20];
351: boolean fret;
352:
353: /* Make sure the file meets any remote size restrictions. */
354: if (qdaemon->cmax_receive != -1
355: && qdaemon->cmax_receive < qinfo->cbytes)
356: return flocal_send_fail (qtrans, &qtrans->s, qdaemon->qsys,
357: "too large for receiver");
358:
359: /* Construct the notify string to send. If we are going to send a
360: size or an execution command, it must be non-empty. */
361: znotify = qtrans->s.znotify;
362: if (znotify == NULL)
363: znotify = "";
364: if ((qdaemon->ifeatures & FEATURE_SIZES) != 0
365: || (qtrans->s.bcmd == 'E'
366: && (qdaemon->ifeatures & FEATURE_EXEC) != 0))
367: {
368: if (*znotify == '\0')
369: znotify = "\"\"";
370: }
371: else
372: {
373: /* We don't need a notify string. Some crufty UUCP code can't
374: handle a pair of double quotes. */
375: if (strcmp (znotify, "\"\"") == 0)
376: znotify = "";
377: }
378:
379: /* Construct the size string to send. */
380: if ((qdaemon->ifeatures & FEATURE_SIZES) == 0
381: && (qtrans->s.bcmd != 'E'
382: || (qdaemon->ifeatures & FEATURE_EXEC) == 0))
383: absize[0] = '\0';
384: else if ((qdaemon->ifeatures & FEATURE_V103) == 0)
385: sprintf (absize, "0x%lx", (unsigned long) qinfo->cbytes);
386: else
387: sprintf (absize, "%ld", qinfo->cbytes);
388:
389: zsend = zbufalc (strlen (qtrans->s.zfrom) + strlen (qtrans->s.zto)
390: + strlen (qtrans->s.zuser) + strlen (qtrans->s.zoptions)
391: + strlen (qtrans->s.ztemp) + strlen (znotify)
392: + strlen (absize)
393: + (qtrans->s.zcmd != NULL ? strlen (qtrans->s.zcmd) : 0)
394: + 50);
395:
396: /* If this an execution request and the other side supports
397: execution requests, we send an E command. Otherwise we send an S
398: command. The case of an execution request when we are sending
399: the fake execution file is handled just like an S request at this
400: point. */
401: if (qtrans->s.bcmd == 'E'
402: && (qdaemon->ifeatures & FEATURE_EXEC) != 0)
403: {
404: /* Send the string
405: E zfrom zto zuser zoptions ztemp imode znotify size zcmd
406: to the remote system. We put a '-' in front of the (possibly
407: empty) options and a '0' in front of the mode. */
408: sprintf (zsend, "E %s %s %s -%s %s 0%o %s %s %s", qtrans->s.zfrom,
409: qtrans->s.zto, qtrans->s.zuser, qtrans->s.zoptions,
410: qtrans->s.ztemp, qtrans->s.imode, znotify, absize,
411: qtrans->s.zcmd);
412: }
413: else
414: {
415: const char *zoptions, *zdummy;
416:
417: /* Send the string
418: S zfrom zto zuser zoptions ztemp imode znotify
419: to the remote system. We put a '-' in front of the (possibly
420: empty) options and a '0' in front of the mode. If size
421: negotiation is supported, we also send the size; in this case
422: if znotify is empty we must send it as "". If this is really
423: an execution request, we have to simplify the options string
424: to remove the various execution options which may confuse the
425: remote system. SVR4 expects a string "dummy" between the
426: notify string and the size; I don't know why. */
427: if (qtrans->s.bcmd != 'E')
428: zoptions = qtrans->s.zoptions;
429: else if (strchr (qtrans->s.zoptions, 'C') != NULL)
430: {
431: /* This should set zoptions to "C", but at least one UUCP
432: program gets confused by it. That means that it will
433: fail in certain cases, but I suppose we might as well
434: kowtow to compatibility. This shouldn't matter to any
435: other program, I hope. */
436: zoptions = "";
437: }
438: else
439: zoptions = "c";
440:
441: if ((qdaemon->ifeatures & FEATURE_SVR4) != 0)
442: zdummy = " dummy ";
443: else
444: zdummy = " ";
445:
446: sprintf (zsend, "S %s %s %s -%s %s 0%o %s%s%s", qtrans->s.zfrom,
447: qtrans->s.zto, qtrans->s.zuser, zoptions,
448: qtrans->s.ztemp, qtrans->s.imode, znotify, zdummy,
449: absize);
450: }
451:
452: fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
453: qtrans->iremote);
454: ubuffree (zsend);
455: if (! fret)
456: {
457: usfree_send (qtrans);
458: return FALSE;
459: }
460:
461: /* If we are using a protocol which can make multiple channels, then
462: we can open and send the file whenever we are ready. This is
463: because we will be able to distinguish the response by the
464: channel it is directed to. This assumes that every protocol
465: which supports multiple channels also supports sending the file
466: position in mid-stream, since otherwise we would not be able to
467: restart files. */
468: qtrans->fcmd = TRUE;
469: qtrans->psendfn = flocal_send_open_file;
470: qtrans->precfn = flocal_send_await_reply;
471:
472: if (qdaemon->qproto->cchans > 1)
473: return fqueue_send (qdaemon, qtrans);
474: else
475: return fqueue_receive (qdaemon, qtrans);
476: }
477:
478: /* This is called when a reply is received for the send request. As
479: described at length above, if the protocol supports multiple
480: channels we may be in the middle of sending the file, or we may
481: even finished sending the file. */
482:
483: static boolean
484: flocal_send_await_reply (qtrans, qdaemon, zdata, cdata)
485: struct stransfer *qtrans;
486: struct sdaemon *qdaemon;
487: const char *zdata;
488: size_t cdata;
489: {
490: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
491: char bcmd;
492:
493: if (qtrans->s.bcmd == 'E'
494: && (qdaemon->ifeatures & FEATURE_EXEC) != 0)
495: bcmd = 'E';
496: else
497: bcmd = 'S';
498: if (zdata[0] != bcmd
499: || (zdata[1] != 'Y' && zdata[1] != 'N'))
500: {
501: ulog (LOG_ERROR, "%s: Bad response to %c request: \"%s\"",
502: qtrans->s.zfrom, bcmd, zdata);
503: usfree_send (qtrans);
504: return FALSE;
505: }
506:
507: if (zdata[1] == 'N')
508: {
509: const char *zerr;
510: boolean fnever;
511:
512: fnever = TRUE;
513: if (zdata[2] == '2')
514: zerr = "permission denied by remote";
515: else if (zdata[2] == '4')
516: {
517: zerr = "remote cannot create work files";
518: fnever = FALSE;
519: }
520: else if (zdata[2] == '6')
521: {
522: zerr = "too large for remote now";
523: fnever = FALSE;
524: }
525: else if (zdata[2] == '7')
526: {
527: /* The file is too large to ever send. */
528: zerr = "too large for remote";
529: }
530: else if (zdata[2] == '8')
531: {
532: /* The file was already received by the remote system. This
533: is not an error, it just means that the ack from the
534: remote was lost in the previous conversation, and there
535: is no need to resend the file. */
536: zerr = NULL;
537: }
538: else
539: zerr = "unknown reason";
540:
541: if (! fnever)
542: {
543: if (qtrans->s.bcmd == 'E')
544: ulog (LOG_ERROR, "Execution of \"%s\": %s", qtrans->s.zcmd,
545: zerr);
546: else
547: ulog (LOG_ERROR, "%s: %s", qtrans->s.zfrom, zerr);
548: }
549: else
550: {
551: if (! flocal_send_fail ((struct stransfer *) NULL, &qtrans->s,
552: qdaemon->qsys, zerr))
553: return FALSE;
554: }
555:
556: /* If the protocol does not support multiple channels, we can
557: simply remove the transaction. Otherwise we must make sure
558: the remote side knows that we have finished sending the file
559: data. If we have already sent the entire file, there will be
560: no confusion. */
561: if (qdaemon->qproto->cchans == 1 || qinfo->fsent)
562: {
563: usfree_send (qtrans);
564: return TRUE;
565: }
566: else
567: {
568: qtrans->psendfn = flocal_send_cancelled;
569: qtrans->precfn = NULL;
570: qtrans->fsendfile = FALSE;
571: return fqueue_send (qdaemon, qtrans);
572: }
573: }
574:
575: /* A number following the SY or EY is the file position to start
576: sending from. If we are already sending the file, we must set
577: the position accordingly. */
578: if (zdata[2] != '\0')
579: {
580: long cskip;
581:
582: cskip = strtol ((char *) (zdata + 2), (char **) NULL, 0);
583: if (cskip > 0 && qtrans->ipos < cskip)
584: {
585: if (qtrans->fsendfile && ! qinfo->fsent)
586: {
587: if (! ffileseek (qtrans->e, cskip))
588: {
589: ulog (LOG_ERROR, "seek: %s", strerror (errno));
590: usfree_send (qtrans);
591: return FALSE;
592: }
593: }
594: qtrans->ipos = cskip;
595: }
596: }
597:
598: /* Now queue up to send the file or to wait for the confirmation.
599: We already set psendfn at the end of flocal_send_request. If the
600: protocol supports multiple channels, we have already called
601: fqueue_send; calling it again would move the request in the
602: queue, which would make the log file a bit confusing. */
603: qtrans->precfn = fsend_await_confirm;
604: if (qinfo->fsent)
605: return fqueue_receive (qdaemon, qtrans);
606: else if (qdaemon->qproto->cchans <= 1)
607: return fqueue_send (qdaemon, qtrans);
608: else
609: return TRUE;
610: }
611:
612: /* Open the file, if any, and prepare to send it. */
613:
614: static boolean
615: flocal_send_open_file (qtrans, qdaemon)
616: struct stransfer *qtrans;
617: struct sdaemon *qdaemon;
618: {
619: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
620: const char *zuser;
621:
622: /* If this is not a fake execution file, open it. */
623: if (qinfo->zexec == NULL)
624: {
625: /* If there is an ! in the user name, this is a remote request
626: queued up by fremote_xcmd_init. */
627: zuser = qtrans->s.zuser;
628: if (strchr (zuser, '!') != NULL)
629: zuser = NULL;
630:
631: qtrans->e = esysdep_open_send (qdaemon->qsys, qinfo->zfile,
632: ! qinfo->fspool, zuser);
633: if (! ffileisopen (qtrans->e))
634: {
635: (void) fmail_transfer (FALSE, qtrans->s.zuser,
636: (const char *) NULL,
637: "cannot open file",
638: qtrans->s.zfrom, (const char *) NULL,
639: qtrans->s.zto,
640: qdaemon->qsys->uuconf_zname,
641: zsysdep_save_temp_file (qtrans->s.pseq));
642: (void) fsysdep_did_work (qtrans->s.pseq);
643: usfree_send (qtrans);
644:
645: /* Unfortunately, there is no way to cancel a file send
646: after we've already put it in progress. So we have to
647: return FALSE to drop the connection. */
648: return FALSE;
649: }
650: }
651:
652: /* If flocal_send_await_reply has received a reply with a file
653: position, it will have set qtrans->ipos to the position at which
654: to start. */
655: if (qtrans->ipos > 0)
656: {
657: if (qinfo->zexec != NULL)
658: {
659: if (qtrans->ipos > qtrans->cbytes)
660: qtrans->ipos = qtrans->cbytes;
661: }
662: else
663: {
664: if (! ffileseek (qtrans->e, qtrans->ipos))
665: {
666: ulog (LOG_ERROR, "seek: %s", strerror (errno));
667: usfree_send (qtrans);
668: return FALSE;
669: }
670: }
671: }
672:
673: /* We don't bother to log sending the execution file. */
674: if (qinfo->zexec == NULL)
675: {
676: const char *zsend;
677: char *zalc;
678:
679: if (qtrans->s.bcmd != 'E')
680: {
681: zsend = qtrans->s.zfrom;
682: zalc = NULL;
683: }
684: else
685: {
686: zalc = zbufalc (strlen (qtrans->s.zcmd) + sizeof " ()"
687: + strlen (qtrans->s.zfrom));
688: sprintf (zalc, "%s (%s)", qtrans->s.zcmd, qtrans->s.zfrom);
689: zsend = zalc;
690: }
691: qtrans->zlog = zbufalc (sizeof "Sending " + strlen (zsend));
692: sprintf (qtrans->zlog, "Sending %s", zsend);
693: ubuffree (zalc);
694: }
695:
696: if (qdaemon->qproto->pffile != NULL)
697: {
698: boolean fhandled;
699:
700: if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, TRUE,
701: qinfo->cbytes, &fhandled))
702: {
703: usfree_send (qtrans);
704: return FALSE;
705: }
706:
707: if (fhandled)
708: return TRUE;
709: }
710:
711: if (qinfo->zexec != NULL)
712: qtrans->psendfn = fsend_exec_file;
713: else
714: {
715: qtrans->fsendfile = TRUE;
716: qtrans->psendfn = fsend_file_end;
717: }
718:
719: return fqueue_send (qdaemon, qtrans);
720: }
721:
722: /* Cancel a file send by sending an empty buffer. This is only called
723: for a protocol which supports multiple channels. It is needed
724: so that both systems agree as to when a channel is no longer
725: needed. */
726:
727: static boolean
728: flocal_send_cancelled (qtrans, qdaemon)
729: struct stransfer *qtrans;
730: struct sdaemon *qdaemon;
731: {
732: char *zdata;
733: size_t cdata;
734: boolean fret;
735:
736: zdata = (*qdaemon->qproto->pzgetspace) (qdaemon, &cdata);
737: if (zdata == NULL)
738: {
739: usfree_send (qtrans);
740: return FALSE;
741: }
742:
743: fret = (*qdaemon->qproto->pfsenddata) (qdaemon, zdata, (size_t) 0,
744: qtrans->ilocal, qtrans->iremote,
745: qtrans->ipos);
746: usfree_send (qtrans);
747: return fret;
748: }
749:
750: /* A remote request to receive a file (meaning that we have to send a
751: file). The sequence of functions calls is as follows:
752:
753: fremote_rec_file_init (open file) --> fqueue_remote
754: fremote_rec_reply (send RY, call pffile) --> fqueue_send
755: send file
756: fsend_file_end (calls pffile) --> fqueue_receive
757: fsend_await_confirm (waits for CY)
758: */
759:
760: boolean
761: fremote_rec_file_init (qdaemon, qcmd, iremote)
762: struct sdaemon *qdaemon;
763: struct scmd *qcmd;
764: int iremote;
765: {
766: const struct uuconf_system *qsys;
767: char *zfile;
768: long cbytes;
769: unsigned int imode;
770: openfile_t e;
771: struct ssendinfo *qinfo;
772: struct stransfer *qtrans;
773:
774: qsys = qdaemon->qsys;
775:
776: if (! qsys->uuconf_fsend_request)
777: {
778: ulog (LOG_ERROR, "%s: not permitted to send files to remote",
779: qcmd->zfrom);
780: return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
781: }
782:
783: if (fspool_file (qcmd->zfrom))
784: {
785: ulog (LOG_ERROR, "%s: not permitted to send", qcmd->zfrom);
786: return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
787: }
788:
789: zfile = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir);
790: if (zfile != NULL)
791: {
792: char *zbased;
793:
794: zbased = zsysdep_add_base (zfile, qcmd->zto);
795: ubuffree (zfile);
796: zfile = zbased;
797: }
798: if (zfile == NULL)
799: return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
800:
801: if (! fin_directory_list (zfile, qsys->uuconf_pzremote_send,
802: qsys->uuconf_zpubdir, TRUE, TRUE,
803: (const char *) NULL))
804: {
805: ulog (LOG_ERROR, "%s: not permitted to send", zfile);
806: ubuffree (zfile);
807: return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
808: }
809:
810: /* If the file is larger than the amount of space the other side
811: reported, we can't send it. Should we adjust this check based on
812: the restart position? */
813: cbytes = csysdep_size (zfile);
814: if (cbytes != -1
815: && ((qcmd->cbytes != -1 && qcmd->cbytes < cbytes)
816: || (qdaemon->cremote_size != -1
817: && qdaemon->cremote_size < cbytes)
818: || (qdaemon->cmax_receive != -1
819: && qdaemon->cmax_receive < cbytes)))
820: {
821: ulog (LOG_ERROR, "%s: too large to send", zfile);
822: ubuffree (zfile);
823: return fremote_rec_fail (qdaemon, FAILURE_SIZE, iremote);
824: }
825:
826: imode = ixsysdep_file_mode (zfile);
827:
828: e = esysdep_open_send (qsys, zfile, TRUE, (const char *) NULL);
829: if (! ffileisopen (e))
830: {
831: ubuffree (zfile);
832: return fremote_rec_fail (qdaemon, FAILURE_OPEN, iremote);
833: }
834:
835: /* If the remote requested that the file send start from a
836: particular position, arrange to do so. */
837: if (qcmd->ipos > 0)
838: {
839: if (! ffileseek (e, qcmd->ipos))
840: {
841: ulog (LOG_ERROR, "seek: %s", strerror (errno));
842: ubuffree (zfile);
843: return FALSE;
844: }
845: }
846:
847: qinfo = (struct ssendinfo *) xmalloc (sizeof (struct ssendinfo));
848: qinfo->zmail = NULL;
849: qinfo->zfile = zfile;
850: qinfo->cbytes = cbytes;
851: qinfo->flocal = FALSE;
852: qinfo->fspool = FALSE;
853: qinfo->fsent = FALSE;
854: qinfo->zexec = NULL;
855:
856: qtrans = qtransalc (qcmd);
857: qtrans->psendfn = fremote_rec_reply;
858: qtrans->iremote = iremote;
859: qtrans->pinfo = (pointer) qinfo;
860: qtrans->e = e;
861: qtrans->ipos = qcmd->ipos;
862: qtrans->s.imode = imode;
863:
864: return fqueue_remote (qdaemon, qtrans);
865: }
866:
867: /* Reply to a receive request from the remote system, and prepare to
868: start sending the file. */
869:
870: static boolean
871: fremote_rec_reply (qtrans, qdaemon)
872: struct stransfer *qtrans;
873: struct sdaemon *qdaemon;
874: {
875: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
876: char absend[50];
877:
878: sprintf (absend, "RY 0%o 0x%lx", qtrans->s.imode,
879: (unsigned long) qinfo->cbytes);
880: if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, absend, qtrans->ilocal,
881: qtrans->iremote))
882: {
883: (void) ffileclose (qtrans->e);
884: usfree_send (qtrans);
885: return FALSE;
886: }
887:
888: qtrans->zlog = zbufalc (sizeof "Sending " + strlen (qtrans->s.zfrom));
889: sprintf (qtrans->zlog, "Sending %s", qtrans->s.zfrom);
890:
891: if (qdaemon->qproto->pffile != NULL)
892: {
893: boolean fhandled;
894:
895: if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, TRUE,
896: qinfo->cbytes, &fhandled))
897: {
898: usfree_send (qtrans);
899: return FALSE;
900: }
901:
902: if (fhandled)
903: return TRUE;
904: }
905:
906: qtrans->fsendfile = TRUE;
907: qtrans->psendfn = fsend_file_end;
908: qtrans->precfn = fsend_await_confirm;
909:
910: return fqueue_send (qdaemon, qtrans);
911: }
912:
913: /* If we can't send a file as requested by the remote system, queue up
914: a failure reply which will be sent when possible. */
915:
916: static boolean
917: fremote_rec_fail (qdaemon, twhy, iremote)
918: struct sdaemon *qdaemon;
919: enum tfailure twhy;
920: int iremote;
921: {
922: enum tfailure *ptinfo;
923: struct stransfer *qtrans;
924:
925: ptinfo = (enum tfailure *) xmalloc (sizeof (enum tfailure));
926: *ptinfo = twhy;
927:
928: qtrans = qtransalc ((struct scmd *) NULL);
929: qtrans->psendfn = fremote_rec_fail_send;
930: qtrans->iremote = iremote;
931: qtrans->pinfo = (pointer) ptinfo;
932:
933: return fqueue_remote (qdaemon, qtrans);
934: }
935:
936: /* Send a failure string for a receive command to the remote system;
937: this is called when we are ready to reply to the command. */
938:
939: static boolean
940: fremote_rec_fail_send (qtrans, qdaemon)
941: struct stransfer *qtrans;
942: struct sdaemon *qdaemon;
943: {
944: enum tfailure *ptinfo = (enum tfailure *) qtrans->pinfo;
945: const char *z;
946: boolean fret;
947:
948: switch (*ptinfo)
949: {
950: case FAILURE_PERM:
951: case FAILURE_OPEN:
952: z = "RN2";
953: break;
954: case FAILURE_SIZE:
955: z = "RN6";
956: break;
957: default:
958: z = "RN";
959: break;
960: }
961:
962: fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, z, qtrans->ilocal,
963: qtrans->iremote);
964: xfree (qtrans->pinfo);
965: utransfree (qtrans);
966: return fret;
967: }
968:
969: /* This is called when the main loop has finished sending a file. It
970: prepares to wait for a response from the remote system. Note that
971: if this is a local request and the protocol supports multiple
972: channels, we may not even have received a confirmation of the send
973: request. */
974:
975: static boolean
976: fsend_file_end (qtrans, qdaemon)
977: struct stransfer *qtrans;
978: struct sdaemon *qdaemon;
979: {
980: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
981:
982: if (qdaemon->qproto->pffile != NULL)
983: {
984: boolean fhandled;
985:
986: if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, FALSE, TRUE,
987: (long) -1, &fhandled))
988: {
989: usfree_send (qtrans);
990: return FALSE;
991: }
992:
993: if (fhandled)
994: return TRUE;
995: }
996:
997: qinfo->fsent = TRUE;
998:
999: /* qtrans->precfn should have been set by a previous function. */
1000: qtrans->fcmd = TRUE;
1001: return fqueue_receive (qdaemon, qtrans);
1002: }
1003:
1004: /* Handle the confirmation string received after sending a file. */
1005:
1006: /*ARGSUSED*/
1007: static boolean
1008: fsend_await_confirm (qtrans, qdaemon, zdata, cdata)
1009: struct stransfer *qtrans;
1010: struct sdaemon *qdaemon;
1011: const char *zdata;
1012: size_t cdata;
1013: {
1014: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
1015: boolean fnever;
1016: const char *zerr;
1017:
1018: if (qinfo->zexec == NULL)
1019: (void) ffileclose (qtrans->e);
1020:
1021: fnever = FALSE;
1022: if (zdata[0] != 'C'
1023: || (zdata[1] != 'Y' && zdata[1] != 'N'))
1024: {
1025: zerr = "bad confirmation from remote";
1026: ulog (LOG_ERROR, "%s: %s \"%s\"", qtrans->s.zfrom, zerr, zdata);
1027: }
1028: else if (zdata[1] == 'N')
1029: {
1030: fnever = TRUE;
1031: if (zdata[2] == '5')
1032: {
1033: zerr = "file could not be stored in final location";
1034: ulog (LOG_ERROR, "%s: %s", qtrans->s.zfrom, zerr);
1035: }
1036: else
1037: {
1038: zerr = "file send failed for unknown reason";
1039: ulog (LOG_ERROR, "%s: %s \"%s\"", qtrans->s.zfrom, zerr, zdata);
1040: }
1041: }
1042: else
1043: {
1044: zerr = NULL;
1045:
1046: /* If we receive CYM, it means that the other side wants us to
1047: hang up so that they can send us something. The
1048: fhangup_requested field is checked in the main loop. */
1049: if (zdata[2] == 'M' && qdaemon->fmaster)
1050: {
1051: DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
1052: "fsend_await_confirm: Remote has requested transfer of control");
1053: qdaemon->fhangup_requested = TRUE;
1054: }
1055: }
1056:
1057: ustats (zerr == NULL, qtrans->s.zuser, qdaemon->qsys->uuconf_zname,
1058: TRUE, qtrans->cbytes, qtrans->isecs, qtrans->imicros,
1059: qdaemon->fmaster);
1060:
1061: if (zerr == NULL)
1062: {
1063: /* If this is an execution request, and the remote system
1064: doesn't support execution requests, we have to set up the
1065: fake execution file and loop around again. */
1066: if (qtrans->s.bcmd == 'E'
1067: && (qdaemon->ifeatures & FEATURE_EXEC) == 0
1068: && qinfo->zexec == NULL)
1069: return fsend_exec_file_init (qtrans, qdaemon);
1070:
1071: /* Send mail about the transfer if requested. */
1072: if (qinfo->zmail != NULL && *qinfo->zmail != '\0')
1073: (void) fmail_transfer (TRUE, qtrans->s.zuser, qinfo->zmail,
1074: (const char *) NULL,
1075: qtrans->s.zfrom, (const char *) NULL,
1076: qtrans->s.zto, qdaemon->qsys->uuconf_zname,
1077: (const char *) NULL);
1078:
1079: if (qtrans->s.pseq != NULL)
1080: (void) fsysdep_did_work (qtrans->s.pseq);
1081: }
1082: else
1083: {
1084: /* If the file send failed, we only try to save the file and
1085: send mail if it was requested locally and it will never
1086: succeed. We send mail to qinfo->zmail if set, otherwise to
1087: qtrans->s.zuser. I hope this is reasonable. */
1088: if (fnever && qinfo->flocal)
1089: {
1090: (void) fmail_transfer (FALSE, qtrans->s.zuser, qinfo->zmail,
1091: zerr, qtrans->s.zfrom, (const char *) NULL,
1092: qtrans->s.zto, qdaemon->qsys->uuconf_zname,
1093: zsysdep_save_temp_file (qtrans->s.pseq));
1094: (void) fsysdep_did_work (qtrans->s.pseq);
1095: }
1096: }
1097:
1098: usfree_send (qtrans);
1099:
1100: return TRUE;
1101: }
1102:
1103: /* Prepare to send an execution file to a system which does not
1104: support execution requests. We build the execution file in memory,
1105: and then call flocal_send_request as though we were sending a real
1106: file. Instead of sending a file, the code in flocal_send_open_file
1107: will arrange to call fsend_exec_file which will send data out of
1108: the buffer we have created. */
1109:
1110: static boolean
1111: fsend_exec_file_init (qtrans, qdaemon)
1112: struct stransfer *qtrans;
1113: struct sdaemon *qdaemon;
1114: {
1115: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
1116: char *zxqtfile;
1117: char abtname[CFILE_NAME_LEN];
1118: char abxname[CFILE_NAME_LEN];
1119: char *z;
1120: size_t calc, clen;
1121:
1122: z = NULL;
1123: calc = 0;
1124: clen = 0;
1125:
1126: usadd_exec_line (&z, &calc, &clen, 'U', qtrans->s.zuser,
1127: qdaemon->zlocalname);
1128: usadd_exec_line (&z, &calc, &clen, 'F', qtrans->s.zto, "");
1129: usadd_exec_line (&z, &calc, &clen, 'I', qtrans->s.zto, "");
1130: if (strchr (qtrans->s.zoptions, 'N') != NULL)
1131: usadd_exec_line (&z, &calc, &clen, 'N', "", "");
1132: if (strchr (qtrans->s.zoptions, 'Z') != NULL)
1133: usadd_exec_line (&z, &calc, &clen, 'Z', "", "");
1134: if (strchr (qtrans->s.zoptions, 'R') != NULL)
1135: usadd_exec_line (&z, &calc, &clen, 'R', qtrans->s.znotify, "");
1136: if (strchr (qtrans->s.zoptions, 'e') != NULL)
1137: usadd_exec_line (&z, &calc, &clen, 'e', "", "");
1138: usadd_exec_line (&z, &calc, &clen, 'C', qtrans->s.zcmd, "");
1139:
1140: qinfo->zexec = z;
1141: qinfo->cbytes = clen;
1142:
1143: zxqtfile = zsysdep_data_file_name (qdaemon->qsys, qdaemon->zlocalname,
1144: BDEFAULT_UUX_GRADE, TRUE, abtname,
1145: (char *) NULL, abxname);
1146: if (zxqtfile == NULL)
1147: {
1148: usfree_send (qtrans);
1149: return FALSE;
1150: }
1151: ubuffree (zxqtfile);
1152:
1153: ubuffree ((char *) qtrans->s.zfrom);
1154: qtrans->s.zfrom = zbufcpy (abtname);
1155: ubuffree ((char *) qtrans->s.zto);
1156: qtrans->s.zto = zbufcpy (abxname);
1157: ubuffree ((char *) qtrans->s.zoptions);
1158: qtrans->s.zoptions = zbufcpy ("C");
1159: ubuffree ((char *) qtrans->s.ztemp);
1160: qtrans->s.ztemp = zbufcpy (abtname);
1161:
1162: qtrans->psendfn = flocal_send_request;
1163: qtrans->precfn = NULL;
1164: qtrans->ipos = 0;
1165: qtrans->cbytes = 0;
1166: qtrans->isecs = 0;
1167: qtrans->imicros = 0;
1168: qinfo->fsent = FALSE;
1169:
1170: return fqueue_send (qdaemon, qtrans);
1171: }
1172:
1173: /* Add a line to the fake execution file. */
1174:
1175: static void
1176: usadd_exec_line (pz, pcalc, pclen, bcmd, z1, z2)
1177: char **pz;
1178: size_t *pcalc;
1179: size_t *pclen;
1180: int bcmd;
1181: const char *z1;
1182: const char *z2;
1183: {
1184: size_t c1, c2;
1185: char *znew;
1186:
1187: c1 = strlen (z1);
1188: c2 = strlen (z2);
1189:
1190: if (*pclen + c1 + c2 + 4 >= *pcalc)
1191: {
1192: *pcalc += c1 + c2 + 100;
1193: znew = zbufalc (*pcalc);
1194: if (*pclen > 0)
1195: {
1196: memcpy (znew, *pz, *pclen);
1197: ubuffree (*pz);
1198: }
1199: *pz = znew;
1200: }
1201:
1202: znew = *pz + *pclen;
1203: *znew++ = bcmd;
1204: if (*z1 != '\0')
1205: {
1206: *znew++ = ' ';
1207: memcpy (znew, z1, c1);
1208: znew += c1;
1209: if (*z2 != '\0')
1210: {
1211: *znew++ = ' ';
1212: memcpy (znew, z2, c2);
1213: znew += c2;
1214: }
1215: }
1216:
1217: /* In some bizarre non-Unix case we might have to worry about the
1218: newline here. We don't know how a newline is normally written
1219: out to a file, but whatever is written to a file is what we will
1220: normally transfer. If that is not simply \n then this fake
1221: execution file will not look like other execution files. */
1222: *znew++ = '\n';
1223:
1224: *pclen = znew - *pz;
1225: }
1226:
1227: /* This routine is called to send the contents of the fake execution
1228: file. Normally file data is sent by the floop routine in trans.c,
1229: but since we don't have an actual file we must do it here. This
1230: routine sends the complete buffer, followed by a zero length
1231: packet, and then calls fsend_file_end. */
1232:
1233: static boolean
1234: fsend_exec_file (qtrans, qdaemon)
1235: struct stransfer *qtrans;
1236: struct sdaemon *qdaemon;
1237: {
1238: struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
1239: char *zdata;
1240: size_t cdata;
1241: size_t csend;
1242:
1243: zdata = (*qdaemon->qproto->pzgetspace) (qdaemon, &cdata);
1244: if (zdata == NULL)
1245: {
1246: usfree_send (qtrans);
1247: return FALSE;
1248: }
1249:
1250: csend = qinfo->cbytes - qtrans->ipos;
1251: if (csend > cdata)
1252: csend = cdata;
1253:
1254: memcpy (zdata, qinfo->zexec + qtrans->ipos, csend);
1255:
1256: if (! (*qdaemon->qproto->pfsenddata) (qdaemon, zdata, csend,
1257: qtrans->ilocal, qtrans->iremote,
1258: qtrans->ipos))
1259: {
1260: usfree_send (qtrans);
1261: return FALSE;
1262: }
1263:
1264: qtrans->cbytes += csend;
1265: qtrans->ipos += csend;
1266:
1267: if (csend == 0)
1268: return fsend_file_end (qtrans, qdaemon);
1269:
1270: /* Leave the job on the send queue. */
1271:
1272: return TRUE;
1273: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.