Advertisement
rapier1

Untitled

Apr 5th, 2021
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.66 KB | None | 0 0
  1. diff --git a/scp.1 b/scp.1
  2. index 5471ea31..48644e0e 100644
  3. --- a/scp.1
  4. +++ b/scp.1
  5. @@ -8,9 +8,9 @@
  6. .\"
  7. .\" Created: Sun May 7 00:14:37 1995 ylo
  8. .\"
  9. -.\" $OpenBSD: scp.1,v 1.95 2021/01/26 15:40:17 naddy Exp $
  10. +.\" $OpenBSD: scp.1,v 1.95 2021/03/31 15:40:17 rapier Exp $
  11. .\"
  12. -.Dd $Mdocdate: January 26 2021 $
  13. +.Dd $Mdocdate: March 31 2021 $
  14. .Dt SCP 1
  15. .Os
  16. .Sh NAME
  17. @@ -228,6 +228,8 @@ Recursively copy entire directories.
  18. Note that
  19. .Nm
  20. follows symbolic links encountered in the tree traversal.
  21. +.It Fl R
  22. +Resume failed or interrupted transfer. Identical files will be skipped. Remote must have resume option.
  23. .It Fl S Ar program
  24. Name of
  25. .Ar program
  26. @@ -235,6 +237,10 @@ to use for the encrypted connection.
  27. The program must understand
  28. .Xr ssh 1
  29. options.
  30. +.It Fl s Ar program
  31. +Path to scp on remote system. Useful if remote has multiple scp installs.
  32. +For example, using the resume option but the default remote scp does not have the resume option.
  33. +Use -s to point the version that does - e.g. -s /opt/hpnssh/bin/scp
  34. .It Fl T
  35. Disable strict filename checking.
  36. By default when copying files from a remote host to a local directory
  37. @@ -273,3 +279,4 @@ source code from the Regents of the University of California.
  38. .Sh AUTHORS
  39. .An Timo Rinne Aq Mt [email protected]
  40. .An Tatu Ylonen Aq Mt [email protected]
  41. +.An Chris Rapier Aq Mt [email protected]
  42. diff --git a/scp.c b/scp.c
  43. index 165962d2..f5bee05e 100644
  44. --- a/scp.c
  45. +++ b/scp.c
  46. @@ -17,6 +17,7 @@
  47. /*
  48. * Copyright (c) 1999 Theo de Raadt. All rights reserved.
  49. * Copyright (c) 1999 Aaron Campbell. All rights reserved.
  50. + * Copyright (c) 2021 Chris Rapier. All rights reserved.
  51. *
  52. * Redistribution and use in source and binary forms, with or without
  53. * modification, are permitted provided that the following conditions
  54. @@ -122,6 +123,7 @@
  55. #include "misc.h"
  56. #include "progressmeter.h"
  57. #include "utf8.h"
  58. +#include <openssl/evp.h>
  59.  
  60. extern char *__progname;
  61.  
  62. @@ -159,9 +161,20 @@ int sshport = -1;
  63. /* This is the program to execute for the secured connection. ("ssh" or -S) */
  64. char *ssh_program = _PATH_SSH_PROGRAM;
  65.  
  66. +/* this is path to the remote scp program allowing the user to specify
  67. + * a non-default scp */
  68. +char *remote_path;
  69. +
  70. /* This is used to store the pid of ssh_program */
  71. pid_t do_cmd_pid = -1;
  72.  
  73. +/* Flag to indicate that this is a file resume */
  74. +int resume_flag = 0; /* 0 is off, 1 is on */
  75. +
  76. +//int fcount = 0; /*tmp track number of files xferred */
  77. +
  78. +char hostname[HOST_NAME_MAX + 1];
  79. +
  80. static void
  81. killchild(int signo)
  82. {
  83. @@ -196,6 +209,9 @@ do_local_cmd(arglist *a)
  84. int status;
  85. pid_t pid;
  86.  
  87. + //if (verbose_mode)
  88. + // fprintf(stderr, "In do_local_cmd\n");
  89. +
  90. if (a->num == 0)
  91. fatal("do_local_cmd: no arguments");
  92.  
  93. @@ -295,7 +311,6 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
  94. addargs(&args, "--");
  95. addargs(&args, "%s", host);
  96. addargs(&args, "%s", cmd);
  97. -
  98. execvp(ssh_program, args.list);
  99. perror(ssh_program);
  100. exit(1);
  101. @@ -388,13 +403,17 @@ int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
  102. #define CMDNEEDS 64
  103. char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
  104.  
  105. +/* forward declarations */
  106. int response(void);
  107. +int debug_response(char *); /* debugging responses -cjr. rm for prod*/
  108. void rsource(char *, struct stat *);
  109. void sink(int, char *[], const char *);
  110. void source(int, char *[]);
  111. void tolocal(int, char *[]);
  112. void toremote(int, char *[]);
  113. void usage(void);
  114. +void calculate_hash(char *, char *, off_t); /*get the hash of file to length*/
  115. +void rand_str(char *, size_t); /*gen randome char string */
  116.  
  117. int
  118. main(int argc, char **argv)
  119. @@ -405,6 +424,10 @@ main(int argc, char **argv)
  120. extern char *optarg;
  121. extern int optind;
  122.  
  123. + /* we use this to prepend the debugging statements
  124. + * so we know which side is saying what */
  125. + gethostname(hostname, HOST_NAME_MAX + 1);
  126. +
  127. /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
  128. sanitise_stdfd();
  129.  
  130. @@ -412,6 +435,9 @@ main(int argc, char **argv)
  131.  
  132. msetlocale();
  133.  
  134. + /* for use with rand function when resume option is used*/
  135. + srand(time(NULL));
  136. +
  137. /* Copy argv, because we modify it */
  138. newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
  139. for (n = 0; n < argc; n++)
  140. @@ -432,7 +458,7 @@ main(int argc, char **argv)
  141.  
  142. fflag = Tflag = tflag = 0;
  143. while ((ch = getopt(argc, argv,
  144. - "12346ABCTdfpqrtvF:J:P:S:c:i:l:o:")) != -1) {
  145. + "12346ABCTdfpqrtvRF:J:P:S:c:i:l:o:s:")) != -1) {
  146. switch (ch) {
  147. /* User-visible flags. */
  148. case '1':
  149. @@ -487,6 +513,9 @@ main(int argc, char **argv)
  150. case 'S':
  151. ssh_program = xstrdup(optarg);
  152. break;
  153. + case 's':
  154. + remote_path = xstrdup(optarg);
  155. + break;
  156. case 'v':
  157. addargs(&args, "-v");
  158. addargs(&remote_remote_args, "-v");
  159. @@ -497,6 +526,9 @@ main(int argc, char **argv)
  160. addargs(&remote_remote_args, "-q");
  161. showprogress = 0;
  162. break;
  163. + case 'R':
  164. + resume_flag = 1;
  165. + break;
  166.  
  167. /* Server options. */
  168. case 'd':
  169. @@ -564,10 +596,20 @@ main(int argc, char **argv)
  170. remin = remout = -1;
  171. do_cmd_pid = -1;
  172. /* Command to be executed on remote system using "ssh". */
  173. - (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
  174. - verbose_mode ? " -v" : "",
  175. - iamrecursive ? " -r" : "", pflag ? " -p" : "",
  176. - targetshouldbedirectory ? " -d" : "");
  177. + /* the command uses the first scp in the users
  178. + * path. This isn't necessarily going to be the 'right' scp to use.
  179. + * So the current solution is to give the user the option of
  180. + * entering the path to correct scp. If they don't then it defaults
  181. + * to whatever scp is first in their path -cjr */
  182. + (void) snprintf(cmd, sizeof cmd, "%s%s%s%s%s%s",
  183. + remote_path ? remote_path : "scp",
  184. + verbose_mode ? " -v" : "",
  185. + iamrecursive ? " -r" : "", pflag ? " -p" : "",
  186. + targetshouldbedirectory ? " -d" : "",
  187. + resume_flag ? " -R" : "");
  188. +
  189. + //if (verbose_mode)
  190. + // fprintf(stderr, "%s: Sending cmd %s\n", hostname, cmd);
  191.  
  192. (void) ssh_signal(SIGPIPE, lostconn);
  193.  
  194. @@ -578,6 +620,7 @@ main(int argc, char **argv)
  195. verifydir(argv[argc - 1]);
  196. tolocal(argc, argv); /* Dest is local host. */
  197. }
  198. +
  199. /*
  200. * Finally check the exit status of the ssh process, if one was forked
  201. * and no error has occurred yet
  202. @@ -616,6 +659,9 @@ do_times(int fd, int verb, const struct stat *sb)
  203. /* strlen(2^64) == 20; strlen(10^6) == 7 */
  204. char buf[(20 + 7 + 2) * 2 + 2];
  205.  
  206. + //if (verbose_mode)
  207. + // fprintf(stderr, "In do_times\n");
  208. +
  209. (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n",
  210. (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime),
  211. (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime));
  212. @@ -634,6 +680,9 @@ parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
  213. {
  214. int r;
  215.  
  216. + //if (verbose_mode)
  217. + // fprintf (stderr, "In parse_scp_uri\n");
  218. +
  219. r = parse_uri("scp", uri, userp, hostp, portp, pathp);
  220. if (r == 0 && *pathp == NULL)
  221. *pathp = xstrdup(".");
  222. @@ -897,6 +946,9 @@ toremote(int argc, char **argv)
  223. int i, r;
  224. u_int j;
  225.  
  226. + //if (verbose_mode)
  227. + // fprintf (stderr, "In toremote\n");
  228. +
  229. memset(&alist, '\0', sizeof(alist));
  230. alist.list = NULL;
  231.  
  232. @@ -987,6 +1039,7 @@ toremote(int argc, char **argv)
  233. if (do_local_cmd(&alist) != 0)
  234. errs = 1;
  235. } else { /* local to remote */
  236. + fprintf (stderr,"Local to remote (toremote)\n");
  237. if (remin == -1) {
  238. xasprintf(&bp, "%s -t %s%s", cmd,
  239. *targ == '-' ? "-- " : "", targ);
  240. @@ -1016,6 +1069,9 @@ tolocal(int argc, char **argv)
  241. arglist alist;
  242. int i, r, sport = -1;
  243.  
  244. + //if (verbose_mode)
  245. + // fprintf (stderr,"In tolocal\n");
  246. +
  247. memset(&alist, '\0', sizeof(alist));
  248. alist.list = NULL;
  249.  
  250. @@ -1067,20 +1123,89 @@ tolocal(int argc, char **argv)
  251. free(src);
  252. }
  253.  
  254. +/* calculate the hash of a file up to length bytes
  255. + * this is used to determine if remote and local file
  256. + * fragments match. There may be a more efficient process for the hashing */
  257. +void calculate_hash(char *filename, char *output, off_t length)
  258. +{
  259. +#define HASH_LEN 40 /*40 sha1, 64 blake2s256*/
  260. +#define hash_buflen 1024 /* 1024 is an arbitrary size */
  261. + int n, md_len;
  262. + EVP_MD_CTX *c;
  263. + const EVP_MD *md;
  264. + char buf[hash_buflen];
  265. + ssize_t bytes;
  266. + unsigned char out[EVP_MAX_MD_SIZE];
  267. + char tmp[3];
  268. + FILE *file_ptr;
  269. + *output = '\0';
  270. +
  271. + //open file for calculating hash
  272. + file_ptr = fopen(filename, "r");
  273. + if (file_ptr==NULL)
  274. + {
  275. + if (verbose_mode) {
  276. + fprintf(stderr, "%s: error opening file %s\n", hostname, filename);
  277. + /* file the expected output with spaces */
  278. + snprintf(output, HASH_LEN, "%s", " ");
  279. + }
  280. + return;
  281. + }
  282. +
  283. + md = EVP_get_digestbyname("sha1");
  284. + c = EVP_MD_CTX_new();
  285. + EVP_DigestInit_ex(c, md, NULL);
  286. +
  287. + while (length > 0) {
  288. + if (length > hash_buflen)
  289. + bytes=fread(buf, 1, hash_buflen, file_ptr);
  290. + else
  291. + bytes=fread(buf, 1, length, file_ptr);
  292. + EVP_DigestUpdate(c, buf, bytes);
  293. + length -= hash_buflen;
  294. + }
  295. + EVP_DigestFinal_ex(c, out, &md_len);
  296. +
  297. + /* convert the hash into a string */
  298. + for(n=0; n < md_len; n++) {
  299. + snprintf(tmp, 3, "%02x", out[n]);
  300. + strcat(output, tmp);
  301. + }
  302. + //if (verbose_mode)
  303. + // fprintf(stderr, "%s: HASH IS '%s' of length %ld\n", hostname, output, strlen(output));
  304. + fclose(file_ptr);
  305. +}
  306. +
  307. +#define TYPE_OVERFLOW(type, val) \
  308. + ((sizeof(type) == 4 && (val) > INT32_MAX) || \
  309. + (sizeof(type) == 8 && (val) > INT64_MAX) || \
  310. + (sizeof(type) != 4 && sizeof(type) != 8))
  311. +
  312. void
  313. source(int argc, char **argv)
  314. {
  315. struct stat stb;
  316. static BUF buffer;
  317. BUF *bp;
  318. - off_t i, statbytes;
  319. + off_t i, statbytes, xfer_size;
  320. size_t amt, nr;
  321. int fd = -1, haderr, indx;
  322. - char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX];
  323. + char *cp, *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX];
  324. int len;
  325. + char hashsum[HASH_LEN], test_hashsum[HASH_LEN];
  326. + char inbuf[PATH_MAX + 128];
  327. + size_t insize;
  328. + unsigned long long ull;
  329. + char *match; /* used to communicate fragment match */
  330. + match = "\0"; /*default is to fail the match. NULL and F both indicate fail*/
  331. +
  332. + //if (verbose_mode)
  333. + // fprintf (stderr, "%s In source\n", hostname);
  334.  
  335. for (indx = 0; indx < argc; ++indx) {
  336. name = argv[indx];
  337. + //if (verbose_mode)
  338. + // fprintf(stderr, "%s index is %d, name is %s\n", hostname, indx, name);
  339. statbytes = 0;
  340. len = strlen(name);
  341. while (len > 1 && name[len-1] == '/')
  342. @@ -1102,6 +1227,16 @@ syserr: run_err("%s: %s", name, strerror(errno));
  343. unset_nonblock(fd);
  344. switch (stb.st_mode & S_IFMT) {
  345. case S_IFREG:
  346. + // only calculate hash if we are in resume mode and a file
  347. + if (resume_flag) {
  348. + calculate_hash(name, hashsum, stb.st_size);
  349. + // debug -cjr
  350. + //if (verbose_mode)
  351. + // fprintf(stderr, "%s: Name is '%s' and hash '%s'\n", hostname, name, hashsum);
  352. + // debug -cjr
  353. + //if (verbose_mode)
  354. + // fprintf (stderr,"%s: size of %s is %ld\n", hostname, name, stb.st_size);
  355. + }
  356. break;
  357. case S_IFDIR:
  358. if (iamrecursive) {
  359. @@ -1123,14 +1258,119 @@ syserr: run_err("%s: %s", name, strerror(errno));
  360. goto next;
  361. }
  362. #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
  363. - snprintf(buf, sizeof buf, "C%04o %lld %s\n",
  364. - (u_int) (stb.st_mode & FILEMODEMASK),
  365. - (long long)stb.st_size, last);
  366. - if (verbose_mode)
  367. - fmprintf(stderr, "Sending file modes: %s", buf);
  368. + /* Add a hash of the file along with the filemode if in resume */
  369. + if (resume_flag)
  370. + snprintf(buf, sizeof buf, "C%04o %lld %s %s\n",
  371. + (u_int) (stb.st_mode & FILEMODEMASK),
  372. + (long long)stb.st_size, hashsum, last);
  373. + else
  374. + snprintf(buf, sizeof buf, "C%04o %lld %s\n",
  375. + (u_int) (stb.st_mode & FILEMODEMASK),
  376. + (long long)stb.st_size, last);
  377. +
  378. + //if (verbose_mode)
  379. + // fmprintf(stderr, "%s: Sending file modes: %s", hostname, buf);
  380. +
  381. (void) atomicio(vwrite, remout, buf, strlen(buf));
  382. - if (response() < 0)
  383. +
  384. + //if (verbose_mode)
  385. + // fprintf(stderr, "%s: inbuf length %ld buf length %ld\n", hostname, strlen(inbuf), strlen(buf));
  386. +
  387. + if (resume_flag) { /* get the hash response from the remote */
  388. + (void) atomicio(read, remin, inbuf, 127);
  389. + //if (verbose_mode)
  390. + // fprintf(stderr, "%s: we got '%s' in inbuf length %ld buf was %ld\n", hostname, inbuf, strlen(inbuf), strlen(buf));
  391. + }
  392. + /*if (debug_response("position 1") < 0) {*/
  393. + if (response() < 0) {
  394. + //if (verbose_mode)
  395. + // fprintf(stderr, "%s: response is less than 0\n", hostname);
  396. goto next;
  397. + }
  398. + xfer_size = stb.st_size;
  399. +
  400. + /* we only do the following in resume mode because we have a
  401. + * new buf from the remote to parse */
  402. + if (resume_flag) {
  403. + cp = inbuf;
  404. + if (*cp == 'R') { // resume file transfer
  405. + char *in_hashsum; /* where to hold the incoming hash */
  406. + in_hashsum = calloc(HASH_LEN+1, sizeof(char));
  407. + for (++cp; cp < inbuf + 5; cp++) {
  408. + /* skip over the mode */
  409. + }
  410. + if (*cp++ != ' ') {
  411. + fprintf(stderr, "%s: mode not delineated!\n", hostname);
  412. + }
  413. +
  414. + if (!isdigit((unsigned char)*cp))
  415. + fprintf(stderr, "%s: size not present\n", hostname);
  416. + ull = strtoull(cp, &cp, 10);
  417. + if (!cp || *cp++ != ' ')
  418. + fprintf(stderr, "%s: size not delimited\n", hostname);
  419. + if (TYPE_OVERFLOW(off_t, ull))
  420. + fprintf(stderr, "%s: size out of range\n", hostname);
  421. + insize = (off_t)ull;
  422. +
  423. + //if (verbose_mode)
  424. + // fprintf (stderr, "%s: received size of %ld\n", hostname, insize);
  425. +
  426. + /* copy the cp pointer byte by byte */
  427. + for (int i = 0; i < HASH_LEN; i++) {
  428. + strncat(in_hashsum, cp++, 1);
  429. + }
  430. + //if (verbose_mode)
  431. + // fprintf (stderr, "%s: in_hashsum '%s'\n", hostname, in_hashsum);
  432. +
  433. + /*get the hash of the source file to the byte length we just got*/
  434. + calculate_hash(name, test_hashsum, insize);
  435. + //if (verbose_mode)
  436. + // fprintf(stderr, "%s: calculated hashsum of local %s to %ld is %s\n", hostname, last, insize, test_hashsum);
  437. + /* compare the incoming hash to the hash of the local file*/
  438. + if (strcmp(in_hashsum, test_hashsum) == 0) {
  439. + /* the fragments match so we should seek to the appropriate place in the
  440. + * local file and set the remote file to append */
  441. + //if (verbose_mode)
  442. + // fprintf(stderr, "%s: File fragments match\n", hostname);
  443. + //fprintf(stderr, "%s: seeking to %ld\n", hostname, insize);
  444. + xfer_size = stb.st_size - insize;
  445. + //if (verbose_mode)
  446. + // fprintf(stderr, "%s: xfer_size: %ld, stb.st_size: %ld insize: %ld\n",
  447. + // hostname, xfer_size, stb.st_size, insize);
  448. + if (lseek(fd, insize, SEEK_CUR) != (off_t)insize) {
  449. + //if (verbose_mode)
  450. + // fprintf(stderr, "%s: lseek did not return %ld\n", hostname, insize) ;
  451. + goto next;
  452. + }
  453. + match = "M";
  454. + } else {
  455. + /* the fragments don't match so we should start over from the begining */
  456. + //if (verbose_mode)
  457. + // fprintf(stderr, "%s: File fragments do not match '%s'(in) '%s'(local)\n",
  458. + // hostname, in_hashsum, test_hashsum);
  459. + match = "F";
  460. + xfer_size = stb.st_size;
  461. + }
  462. + free(in_hashsum);
  463. + }
  464. + if (*cp == 'S') { /* skip file */
  465. + //if (verbose_mode)
  466. + // fprintf(stderr, "%s: Should be skipping this file\n", hostname);
  467. + goto next;
  468. + }
  469. + if (*cp == 'C') { /*transfer entire file*/
  470. + //if (verbose_mode)
  471. + // fprintf(stderr, "%s: Resending entire file\n", hostname);
  472. + xfer_size = stb.st_size;
  473. + }
  474. + /* need to send the match status
  475. + * We always send the match status or we get out of sync
  476. + */
  477. + //if (verbose_mode)
  478. + // fprintf(stderr, "%s: sending match %s\n", hostname, match);
  479. + (void) atomicio(vwrite, remout, match, 1);
  480. + }
  481. +
  482. if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
  483. next: if (fd != -1) {
  484. (void) close(fd);
  485. @@ -1138,22 +1378,27 @@ next: if (fd != -1) {
  486. }
  487. continue;
  488. }
  489. - if (showprogress)
  490. - start_progress_meter(curfile, stb.st_size, &statbytes);
  491. +
  492. + //if (verbose_mode)
  493. + // fprintf(stderr, "%s: going to xfer %ld\n", hostname, xfer_size);
  494. + if (showprogress) {
  495. + start_progress_meter(curfile, xfer_size, &statbytes);
  496. + }
  497. set_nonblock(remout);
  498. - for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
  499. + for (haderr = i = 0; i < xfer_size; i += bp->cnt) {
  500. amt = bp->cnt;
  501. - if (i + (off_t)amt > stb.st_size)
  502. - amt = stb.st_size - i;
  503. + if (i + (off_t)amt > xfer_size)
  504. + amt = xfer_size - i;
  505. if (!haderr) {
  506. - if ((nr = atomicio(read, fd,
  507. - bp->buf, amt)) != amt) {
  508. + if ((nr = atomicio(read, fd, bp->buf, amt)) != amt) {
  509. haderr = errno;
  510. memset(bp->buf + nr, 0, amt - nr);
  511. }
  512. }
  513. /* Keep writing after error to retain sync */
  514. if (haderr) {
  515. + //if (verbose_mode)
  516. + // fprintf(stderr, "%s: had error %d\n", hostname, haderr);
  517. (void)atomicio(vwrite, remout, bp->buf, amt);
  518. memset(bp->buf, 0, amt);
  519. continue;
  520. @@ -1173,6 +1418,7 @@ next: if (fd != -1) {
  521. (void) atomicio(vwrite, remout, "", 1);
  522. else
  523. run_err("%s: %s", name, strerror(haderr));
  524. + /*(void) debug_response("position 2");*/
  525. (void) response();
  526. if (showprogress)
  527. stop_progress_meter();
  528. @@ -1186,6 +1432,9 @@ rsource(char *name, struct stat *statp)
  529. struct dirent *dp;
  530. char *last, *vect[1], path[PATH_MAX];
  531.  
  532. + //if (verbose_mode)
  533. + // fprintf (stderr, "%s: In rsource\n", hostname);
  534. +
  535. if (!(dirp = opendir(name))) {
  536. run_err("%s: %s", name, strerror(errno));
  537. return;
  538. @@ -1228,33 +1477,39 @@ rsource(char *name, struct stat *statp)
  539. (void) response();
  540. }
  541.  
  542. -#define TYPE_OVERFLOW(type, val) \
  543. - ((sizeof(type) == 4 && (val) > INT32_MAX) || \
  544. - (sizeof(type) == 8 && (val) > INT64_MAX) || \
  545. - (sizeof(type) != 4 && sizeof(type) != 8))
  546. -
  547. void
  548. sink(int argc, char **argv, const char *src)
  549. {
  550. static BUF buffer;
  551. - struct stat stb;
  552. + struct stat stb, cpstat, npstat;
  553. BUF *bp;
  554. off_t i;
  555. size_t j, count;
  556. int amt, exists, first, ofd;
  557. mode_t mode, omode, mask;
  558. - off_t size, statbytes;
  559. + off_t size, statbytes, xfer_size;
  560. unsigned long long ull;
  561. int setimes, targisdir, wrerr;
  562. - char ch, *cp, *np, *targ, *why, *vect[1], buf[16384], visbuf[16384];
  563. + char ch, *cp, *np, *np_tmp, *targ, *why, *vect[1], buf[16384], visbuf[16384];
  564. char **patterns = NULL;
  565. size_t n, npatterns = 0;
  566. struct timeval tv[2];
  567. + char remote_hashsum[HASH_LEN+1];
  568. + char local_hashsum[HASH_LEN+1];
  569. + char tmpbuf[128];
  570. + char outbuf[128];
  571. + char match;
  572. + int bad_match_flag = 0;
  573. + np = '\0';
  574. + np_tmp = '\0';
  575.  
  576. #define atime tv[0]
  577. #define mtime tv[1]
  578. #define SCREWUP(str) { why = str; goto screwup; }
  579.  
  580. + //if (verbose_mode)
  581. + // fprintf (stderr, "%s: LOCAL In sink with %s\n", hostname, src);
  582. +
  583. if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0))
  584. SCREWUP("Unexpected off_t/time_t size");
  585.  
  586. @@ -1270,9 +1525,16 @@ sink(int argc, char **argv, const char *src)
  587. if (targetshouldbedirectory)
  588. verifydir(targ);
  589.  
  590. + //if (verbose_mode)
  591. + // fprintf (stderr, "%s: Sending null to remout.\n",hostname);
  592. +
  593. (void) atomicio(vwrite, remout, "", 1);
  594. if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
  595. targisdir = 1;
  596. +
  597. + //if (verbose_mode)
  598. + // fprintf(stderr, "%s: Target is %s with a size of %ld\n", hostname, targ, stb.st_size);
  599. +
  600. if (src != NULL && !iamrecursive && !Tflag) {
  601. /*
  602. * Prepare to try to restrict incoming filenames to match
  603. @@ -1281,7 +1543,11 @@ sink(int argc, char **argv, const char *src)
  604. if (brace_expand(src, &patterns, &npatterns) != 0)
  605. fatal_f("could not expand pattern");
  606. }
  607. +
  608. for (first = 1;; first = 0) {
  609. + bad_match_flag = 0; /* used in resume mode. */
  610. + //if (verbose_mode)
  611. + // fprintf(stderr, "%s: position 1 buf is %s\n", hostname, buf);
  612. cp = buf;
  613. if (atomicio(read, remin, cp, 1) != 1)
  614. goto done;
  615. @@ -1309,6 +1575,8 @@ sink(int argc, char **argv, const char *src)
  616. continue;
  617. }
  618. if (buf[0] == 'E') {
  619. + //if (verbose_mode)
  620. + // fprintf (stderr, "%s: Sending null to remout.\n", hostname);
  621. (void) atomicio(vwrite, remout, "", 1);
  622. goto done;
  623. }
  624. @@ -1316,6 +1584,9 @@ sink(int argc, char **argv, const char *src)
  625. *--cp = 0;
  626.  
  627. cp = buf;
  628. + //if (verbose_mode)
  629. + // fprintf(stderr, "%s: buf is %s\n", hostname, buf);
  630. +
  631. if (*cp == 'T') {
  632. setimes++;
  633. cp++;
  634. @@ -1343,9 +1614,17 @@ sink(int argc, char **argv, const char *src)
  635. if (!cp || *cp++ != '\0' || atime.tv_usec < 0 ||
  636. atime.tv_usec > 999999)
  637. SCREWUP("atime.usec not delimited");
  638. +
  639. + //if (verbose_mode)
  640. + // fprintf (stderr, "%s: Sending null to remout.\n", hostname);
  641. (void) atomicio(vwrite, remout, "", 1);
  642. continue;
  643. }
  644. + if (*cp == 'R') { /*resume file transfer (dont' think I need this here)*/
  645. + //if (verbose_mode)
  646. + // fprintf(stderr, "%s: Received a RESUME request with %s\n", hostname, cp);
  647. + resume_flag = 1;
  648. + }
  649. if (*cp != 'C' && *cp != 'D') {
  650. /*
  651. * Check for the case "rcp remote:foo\* local:bar".
  652. @@ -1361,6 +1640,18 @@ sink(int argc, char **argv, const char *src)
  653. SCREWUP("expected control record");
  654. }
  655. mode = 0;
  656. + //if (verbose_mode)
  657. + // fprintf(stderr, "%s: buf is %s\n", hostname, buf);
  658. + //if (verbose_mode)
  659. + // fprintf(stderr, "%s: cp is %s\n", hostname, cp);
  660. + /* we need to track if this object is a directory
  661. + * before we move the pointer. If we are in resume mode
  662. + * we might endup trying to get an mdsum on a directory
  663. + * and that doesn't work */
  664. + int dir_flag = 0;
  665. + if (*cp == 'D')
  666. + dir_flag = 1;
  667. +
  668. for (++cp; cp < buf + 5; cp++) {
  669. if (*cp < '0' || *cp > '7')
  670. SCREWUP("bad mode");
  671. @@ -1371,6 +1662,10 @@ sink(int argc, char **argv, const char *src)
  672. if (*cp++ != ' ')
  673. SCREWUP("mode not delimited");
  674.  
  675. + //if (verbose_mode)
  676. + // fprintf(stderr, "%s: cp is %s\n", hostname, cp);
  677. +
  678. +
  679. if (!isdigit((unsigned char)*cp))
  680. SCREWUP("size not present");
  681. ull = strtoull(cp, &cp, 10);
  682. @@ -1380,11 +1675,29 @@ sink(int argc, char **argv, const char *src)
  683. SCREWUP("size out of range");
  684. size = (off_t)ull;
  685.  
  686. + //if (verbose_mode)
  687. + // fprintf(stderr, "%s: cp is %s\n", hostname, cp);
  688. +
  689. + if (resume_flag && !dir_flag) {
  690. + *remote_hashsum = '\0';
  691. + for (int i = 0; i < HASH_LEN; i++) {
  692. + strncat (remote_hashsum, cp++, 1);
  693. + }
  694. + //if (verbose_mode)
  695. + // fprintf (stderr, "%s: %s\n", hostname, remote_hashsum);
  696. + if (!cp || *cp++ != ' ')
  697. + SCREWUP("hash not delimited");
  698. + }
  699. + //if (verbose_mode)
  700. + // fprintf(stderr, "%s: cp is %s\n", hostname, cp);
  701. +
  702. if (*cp == '\0' || strchr(cp, '/') != NULL ||
  703. strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
  704. run_err("error: unexpected filename: %s", cp);
  705. exit(1);
  706. }
  707. + //if (verbose_mode)
  708. + // fprintf(stderr, "%s cp is %s\n", hostname, cp);
  709. if (npatterns > 0) {
  710. for (n = 0; n < npatterns; n++) {
  711. if (fnmatch(patterns[n], cp, 0) == 0)
  712. @@ -1442,11 +1755,173 @@ sink(int argc, char **argv, const char *src)
  713. }
  714. omode = mode;
  715. mode |= S_IWUSR;
  716. + stat(cp, &cpstat);
  717. + xfer_size = size;
  718. + if (resume_flag) {
  719. + //if (verbose_mode)
  720. + // fprintf(stderr, "%s: np is %s\n", hostname, np);
  721. + /* does the file exist and if it does it writable? */
  722. + if (stat(np, &npstat) == -1) {
  723. + //if (verbose_mode)
  724. + // fprintf(stderr, "%s Local file does not exist size is %ld!\n",
  725. + // hostname, npstat.st_size);
  726. + npstat.st_size = 0;
  727. + } else {
  728. + /* check to see if the file is writeable
  729. + * if it isn't then we need to skip it but
  730. + * before we skip it we need to send the remote
  731. + * what they are expecting so 128 bytes and then
  732. + * a null */
  733. + if (access (np, W_OK) != 0) {
  734. + fprintf(stderr, "scp: %s: Permission denied on %s\n", np, hostname);
  735. + snprintf(outbuf, 128, "S%-126s", " ");
  736. + (void)atomicio(vwrite, remout, outbuf, strlen(outbuf));
  737. + (void)atomicio(vwrite, remout, "", 1);
  738. + continue;
  739. + }
  740. + }
  741. + /* this file is already here do we need to move it?
  742. + * Check to make sure npstat.st_size > 0. If it is 0 then we
  743. + * may trying to be moving a zero byte file in which case this
  744. + * following block fails. See on 0 byte files the hashes will
  745. + * always match and the file won't be created even though it should
  746. + */
  747. + if (xfer_size == npstat.st_size && (npstat.st_size > 0)) {
  748. + calculate_hash(np, local_hashsum, npstat.st_size);
  749. + if (strcmp(local_hashsum,remote_hashsum) == 0) {
  750. + /* we can skip this file if we want to. */
  751. + //if (verbose_mode)
  752. + // fprintf(stderr, "%s: Files are the same\n", hostname);
  753. + /* the remote is expecting something so we need to send them something*/
  754. + snprintf(outbuf, 128, "S%-126s", " ");
  755. + (void)atomicio(vwrite, remout, outbuf, strlen(outbuf));
  756. + //if (verbose_mode)
  757. + // fprintf(stderr,"%s: sent '%s' to remote\n", hostname, outbuf);
  758. + /* the remote is waiting on an ack so send a null */
  759. + (void)atomicio(vwrite, remout, "", 1);
  760. + fprintf (stderr, "Skipping identical file: %s\n", np);
  761. + continue;
  762. + } else {
  763. + /* file sizes are the same but they don't match */
  764. + //if (verbose_mode)
  765. + // fprintf(stderr, "%s: target(%ld) is different than source(%ld)!\n",
  766. + // hostname, npstat.st_size, size);
  767. + snprintf(tmpbuf, sizeof outbuf, "C%04o %lld %s",
  768. + (u_int) (npstat.st_mode & FILEMODEMASK),
  769. + (long long)npstat.st_size, local_hashsum);
  770. + snprintf(outbuf, 128, "%-127s", tmpbuf);
  771. + (void) atomicio(vwrite, remout, outbuf, strlen(outbuf));
  772. + bad_match_flag = 1;
  773. + }
  774. + }
  775. + /* if npstat.st_size is 0 then the local file doesn't exist and
  776. + * we have to move it. Since we are in resume mode treat it as a resume */
  777. + if (npstat.st_size < xfer_size || (npstat.st_size == 0)) {
  778. + char rand_string[9];
  779. + //if (verbose_mode)
  780. + // fprintf (stderr, "%s: %s is smaller than %s\n", hostname, np, cp);
  781. + calculate_hash(np, local_hashsum, npstat.st_size);
  782. +#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
  783. + snprintf(tmpbuf, sizeof outbuf, "R%04o %lld %s",
  784. + (u_int) (npstat.st_mode & FILEMODEMASK),
  785. + (long long)npstat.st_size, local_hashsum);
  786. + snprintf(outbuf, 128, "%-127s", tmpbuf);
  787. + //if (verbose_mode)
  788. + // fprintf (stderr, "%s: new buf is %s of length %ld\n",
  789. + // hostname, outbuf, strlen(outbuf));
  790. + //if (verbose_mode)
  791. + // fprintf(stderr, "%s: Sending new file (%s) modes: %s\n",
  792. + // hostname, np, outbuf);
  793. + /*now we have to send np's length and hash to the other end
  794. + * if the computed hashes match then we seek to np's length in
  795. + * file and append to np starting from there */
  796. + (void) atomicio(vwrite, remout, outbuf, strlen(outbuf));
  797. + //if (verbose_mode)
  798. + // fprintf(stderr, "%s: New size: %ld, size: %ld, st_size: %ld\n",
  799. + // hostname, size - npstat.st_size, size, npstat.st_size);
  800. + xfer_size = size - npstat.st_size;
  801. + resume_flag = 1;
  802. + np_tmp = strndup(np, strlen(np));
  803. + /* We should have a random component to avoid clobbering a
  804. + * local file */
  805. + rand_str(rand_string, 8);
  806. + strcat(np, rand_string);
  807. + //if (verbose_mode)
  808. + // fprintf(stderr, "%s: Will concat %s to %s after xfer\n",
  809. + // hostname, np, np_tmp);
  810. + } else if (npstat.st_size > size) {
  811. + /* the target file is larger than the source.
  812. + * so we need to overwrite it */
  813. + //if (verbose_mode)
  814. + // fprintf(stderr, "%s: target(%ld) is larger than source(%ld)!\n",
  815. + // hostname, npstat.st_size, size);
  816. + snprintf(tmpbuf, sizeof outbuf, "C%04o %lld %s",
  817. + (u_int) (npstat.st_mode & FILEMODEMASK),
  818. + (long long)npstat.st_size, local_hashsum);
  819. + snprintf(outbuf, 128, "%-127s", tmpbuf);
  820. + (void) atomicio(vwrite, remout, outbuf, strlen(outbuf));
  821. + bad_match_flag = 1;
  822. + }
  823. +
  824. + //if (verbose_mode)
  825. + // fprintf (stderr, "%s: CP is %s(%ld) NP is %s(%ld)\n",
  826. + // hostname, cp, size, np, npstat.st_size);
  827. + /* we are in resume mode so we need this *here* and not later
  828. + * because we need to get the file match information from the remote
  829. + * outside of resume mode we don't get that so we get out of sync
  830. + * so we have a test for the resume_flag after this block */
  831. + //if (verbose_mode)
  832. + // fprintf (stderr, "%s: Sending null to remout.\n", hostname);
  833. + (void) atomicio(vwrite, remout, "", 1);
  834. +
  835. + /* the remote is always going to send a match status
  836. + * so we need to read it so we don't get out of sync */
  837. + (void) atomicio(read, remin, &match, 1);
  838. + if (match != 'M') {/*fragments do not match*/
  839. + /* expected response of F, M and NULL *but*
  840. + * anything other than M is a failure */
  841. + xfer_size = size;
  842. + bad_match_flag = 1;
  843. + if (match == 'F') {
  844. + /* got an F for failure and not NULL
  845. + * so we want to swap over the filename from
  846. + * the temp back to the original */
  847. + //if (verbose_mode)
  848. + // fprintf(stderr, "%s: match status is F\n", hostname);
  849. + if (np_tmp != NULL)
  850. + np = strndup(np_tmp, strlen(np_tmp));
  851. + else {
  852. + //run_err("%s: np_tmp is NULL", hostname);
  853. + continue;
  854. + }
  855. +
  856. + }
  857. + } else {
  858. + //if (verbose_mode)
  859. + // fprintf(stderr, "%s match status is M\n", hostname);
  860. + bad_match_flag = 0; /* while this is set at the beginning of the
  861. + * loop I'm setting it here explicitly as well */
  862. + }
  863. + }
  864. +
  865. + //if (verbose_mode)
  866. + // fprintf(stderr, "%s: Creating file. mode is %d for %s\n",
  867. + // hostname, mode, np);
  868. if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) {
  869. bad: run_err("%s: %s", np, strerror(errno));
  870. continue;
  871. }
  872. - (void) atomicio(vwrite, remout, "", 1);
  873. +
  874. + /* in the case of not using the resume function we need this vwrite here
  875. + * in the case of using the resume flag it comes in the above if (resume_flag) block
  876. + * why? because scp is weird and depends on an intricate and silly dance of
  877. + * call and response at just the right time. That's why */
  878. + if (!resume_flag) {
  879. + //if (verbose_mode)
  880. + // fprintf (stderr, "%s: Sending null to remout.\n", hostname);
  881. + (void) atomicio(vwrite, remout, "", 1);
  882. + }
  883. +
  884. if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
  885. (void) close(ofd);
  886. continue;
  887. @@ -1461,14 +1936,19 @@ bad: run_err("%s: %s", np, strerror(errno));
  888. */
  889. statbytes = 0;
  890. if (showprogress)
  891. - start_progress_meter(curfile, size, &statbytes);
  892. + start_progress_meter(curfile, xfer_size, &statbytes);
  893. set_nonblock(remin);
  894. - for (count = i = 0; i < size; i += bp->cnt) {
  895. + //if (verbose_mode)
  896. + // fprintf(stderr, "%s: xfer_size is %ld\n", hostname, xfer_size);
  897. + //int total_bytes = 0;
  898. + for (count = i = 0; i < xfer_size; i += bp->cnt) {
  899. amt = bp->cnt;
  900. - if (i + amt > size)
  901. - amt = size - i;
  902. + if (i + amt > xfer_size)
  903. + amt = xfer_size - i;
  904. count += amt;
  905. + /* read the data from the socket*/
  906. do {
  907. +
  908. j = atomicio6(read, remin, cp, amt,
  909. scpio, &statbytes);
  910. if (j == 0) {
  911. @@ -1477,10 +1957,10 @@ bad: run_err("%s: %s", np, strerror(errno));
  912. "dropped connection");
  913. exit(1);
  914. }
  915. + //total_bytes += amt;
  916. amt -= j;
  917. cp += j;
  918. } while (amt > 0);
  919. -
  920. if (count == bp->cnt) {
  921. /* Keep reading so we stay sync'd up. */
  922. if (!wrerr) {
  923. @@ -1495,6 +1975,8 @@ bad: run_err("%s: %s", np, strerror(errno));
  924. cp = bp->buf;
  925. }
  926. }
  927. + //if (verbose_mode)
  928. + // fprintf(stderr, "%s: total received bytes is %d\n", hostname, total_bytes);
  929. unset_nonblock(remin);
  930. if (count != 0 && !wrerr &&
  931. atomicio(vwrite, ofd, bp->buf, count) != count) {
  932. @@ -1502,8 +1984,80 @@ bad: run_err("%s: %s", np, strerror(errno));
  933. wrerr = 1;
  934. }
  935. if (!wrerr && (!exists || S_ISREG(stb.st_mode)) &&
  936. - ftruncate(ofd, size) != 0)
  937. + ftruncate(ofd, xfer_size) != 0)
  938. note_err("%s: truncate: %s", np, strerror(errno));
  939. +
  940. + /* if np_tmp isn't set then we don't have a resume file to cat */
  941. + /* likewise, bad match flag means no resume flag */
  942. + //if (verbose_mode)
  943. + // fprintf (stderr, "%s: resume_flag: %d, np_tmp: %s, bad_match_flag: %d\n",
  944. + // hostname, resume_flag, np_tmp, bad_match_flag);
  945. + if (resume_flag && np_tmp && !bad_match_flag) {
  946. + FILE *orig, *resume;
  947. + char res_buf[512]; /* set at 512 just because, might want to increase*/
  948. + ssize_t res_bytes = 0;
  949. + off_t sum = 0;
  950. + struct stat res_stat;
  951. + *res_buf = '\0';
  952. + orig = NULL; /*supress warnings*/
  953. + resume = NULL; /*supress warnings*/
  954. +
  955. + //if (verbose_mode)
  956. + // fprintf(stderr, "%s: Resume flag is set. Going to concat %s to %s now\n",
  957. + // hostname, np, np_tmp);
  958. + /* np/ofd is the resume file so open np_tmp for appending
  959. + * close ofd because we are going to be shifting it
  960. + * and I don't wnat the same file open in multiple descriptors */
  961. + if (close(ofd) == -1)
  962. + note_err("%s: close: %s", np, strerror(errno));
  963. + /* orig is the target file, resume is the temp file */
  964. + orig = fopen(np_tmp, "a"); /*open for appending*/
  965. + if (orig == NULL) {
  966. + fprintf(stderr, "%s: Could not open %s for appending.", hostname, np_tmp);
  967. + goto stopcat;
  968. + }
  969. + resume = fopen(np, "r"); /*open for reading only*/
  970. + if (resume == NULL) {
  971. + fprintf(stderr, "%s: Could not open %s for reading.", hostname, np);
  972. + goto stopcat;
  973. + }
  974. + /* get the number of bytes in the temp file*/
  975. + if (fstat(fileno(resume), &res_stat) == -1) {
  976. + fprintf(stderr, "%s: Could not stat %s", hostname, np);
  977. + goto stopcat;
  978. + }
  979. + /* while the number of bytes read from the temp file
  980. + * is less than the size of the file read in a chunk and
  981. + * write it to the target file */
  982. + do {
  983. + res_bytes = fread(res_buf, 1, 512, resume);
  984. + fwrite(res_buf, 1, res_bytes, orig);
  985. + sum += res_bytes;
  986. + } while (sum < res_stat.st_size);
  987. +
  988. +stopcat: if (orig)
  989. + fclose(orig);
  990. + if (resume)
  991. + fclose(resume);
  992. + /* delete the resume file */
  993. + remove(np);
  994. + //if (verbose_mode)
  995. + // fprintf (stderr, "%s: np(%s) and np_tmp(%s)\n", hostname, np, np_tmp);
  996. + np = np_tmp;
  997. + //if (verbose_mode)
  998. + // fprintf (stderr, "%s np(%s) and np_tmp(%s)\n", hostname, np, np_tmp);
  999. + /* reset ofd to the original np */
  1000. + if ((ofd = open(np_tmp, O_WRONLY)) == -1) {
  1001. + free(np_tmp);
  1002. + fprintf(stderr, "%s: couldn't open %s in append function\n", hostname, np_tmp);
  1003. + atomicio(vwrite, remout, "", 1);
  1004. + goto bad;
  1005. + }
  1006. + free(np_tmp);
  1007. + //fcount++;
  1008. + }
  1009. + //if (verbose_mode)
  1010. + // fprintf (stderr, "%s: Current file count is %d\n", hostname, fcount);
  1011. if (pflag) {
  1012. if (exists || omode != mode)
  1013. #ifdef HAVE_FCHMOD
  1014. @@ -1538,8 +2092,10 @@ bad: run_err("%s: %s", np, strerror(errno));
  1015. }
  1016. }
  1017. /* If no error was noted then signal success for this file */
  1018. - if (note_err(NULL) == 0)
  1019. - (void) atomicio(vwrite, remout, "", 1);
  1020. + if (note_err(NULL) == 0) {
  1021. + //if (verbose_mode)
  1022. + // fprintf (stderr, "%s: Sending null to remout.\n", hostname);
  1023. + (void) atomicio(vwrite, remout, "", 1); }
  1024. }
  1025. done:
  1026. for (n = 0; n < npatterns; n++)
  1027. @@ -1563,6 +2119,9 @@ response(void)
  1028. lostconn(0);
  1029.  
  1030. cp = rbuf;
  1031. + //if (verbose_mode)
  1032. + // fprintf (stderr, "%s: In response is %d and cp is '%s'\n", hostname, resp, cp);
  1033. +
  1034. switch (resp) {
  1035. case 0: /* ok */
  1036. return (0);
  1037. @@ -1592,13 +2151,64 @@ response(void)
  1038. /* NOTREACHED */
  1039. }
  1040.  
  1041. +/* remove for production */
  1042. +int
  1043. +debug_response(char *message)
  1044. +{
  1045. + char ch, *cp, resp, rbuf[2048], visbuf[2048];
  1046. +
  1047. + fprintf(stderr, "LOCAL in reponse at %s\n", message);
  1048. + if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
  1049. + lostconn(0);
  1050. +
  1051. + cp = rbuf;
  1052. + fprintf (stderr, "LOCAL In response is %d and cp is '%s'\n", resp, cp);
  1053. + fprintf (stderr, "LOCAL In response and printed cp sizeof resp is %ld\n", sizeof(resp));
  1054. +
  1055. + switch (resp) {
  1056. + case 0: /* ok */
  1057. + fprintf(stderr, "LOCAL returning 0\n");
  1058. + return (0);
  1059. + default:
  1060. + *cp++ = resp;
  1061. + /* FALLTHROUGH */
  1062. + case 1: /* error, followed by error msg */
  1063. + case 2: /* fatal error, "" */
  1064. + fprintf(stderr, "LOCAL in response case 2\n");
  1065. + do {
  1066. + if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
  1067. + lostconn(0);
  1068. + *cp++ = ch;
  1069. + } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
  1070. + fprintf(stderr, "LOCAL in response case 2 after do loop\n");
  1071. +
  1072. + if (!iamremote) {
  1073. + cp[-1] = '\0';
  1074. + (void) snmprintf(visbuf, sizeof(visbuf),
  1075. + NULL, "%s\n", rbuf);
  1076. + (void) atomicio(vwrite, STDERR_FILENO,
  1077. + visbuf, strlen(visbuf));
  1078. + fprintf(stderr, "LOCAL in response case after atomicio (sent '%s')\n", visbuf);
  1079. + }
  1080. + ++errs;
  1081. + fprintf(stderr, "LOCAL in response case resp is %d\n", resp);
  1082. + if (resp == 1) {
  1083. + fprintf(stderr, "LOCAL in response case returning -1\n");
  1084. + return (-1);
  1085. + }
  1086. + fprintf(stderr, "LOCAL in response case about to exit\n");
  1087. + exit(1);
  1088. + }
  1089. + /* NOTREACHED */
  1090. +}
  1091. +
  1092. void
  1093. usage(void)
  1094. {
  1095. (void) fprintf(stderr,
  1096. - "usage: scp [-346ABCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
  1097. + "usage: scp [-346ABCpqrTvR] [-c cipher] [-F ssh_config] [-i identity_file]\n"
  1098. " [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
  1099. - " [-S program] source ... target\n");
  1100. + " [-S program] [-s filepath of remote scp] source ... target\n");
  1101. exit(1);
  1102. }
  1103.  
  1104. @@ -1737,3 +2347,15 @@ lostconn(int signo)
  1105. else
  1106. exit(1);
  1107. }
  1108. +
  1109. +void rand_str(char *dest, size_t length) {
  1110. + char charset[] = "0123456789"
  1111. + "abcdefghijklmnopqrstuvwxyz"
  1112. + "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1113. +
  1114. + while (length-- > 0) {
  1115. + size_t index = (double) rand() / RAND_MAX * (sizeof charset - 1);
  1116. + *dest++ = charset[index];
  1117. + }
  1118. + *dest = '\0';
  1119. +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement