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