|
|
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.