comparison scp.c @ 297:79bf1023cf11 agent-client

propagate from branch 'au.asn.ucc.matt.dropbear' (head 0501e6f661b5415eb76f3b312d183c3adfbfb712) to branch 'au.asn.ucc.matt.dropbear.cli-agent' (head 01038174ec27245b51bd43a66c01ad930880f67b)
author Matt Johnston <matt@ucc.asn.au>
date Tue, 21 Mar 2006 16:20:59 +0000
parents 497fddd4a94e
children 973fccb59ea4 c0ce48053259
comparison
equal deleted inserted replaced
225:ca7e76d981d9 297:79bf1023cf11
69 * SUCH DAMAGE. 69 * SUCH DAMAGE.
70 * 70 *
71 */ 71 */
72 72
73 #include "includes.h" 73 #include "includes.h"
74 /*RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");*/
75
74 #include "atomicio.h" 76 #include "atomicio.h"
75 #include "compat.h" 77 #include "compat.h"
76 #include "scpmisc.h" 78 #include "scpmisc.h"
77 #include "progressmeter.h" 79 #include "progressmeter.h"
78 80
79 #define _PATH_CP "/bin/cp"
80
81 #ifndef TIMEVAL_TO_TIMESPEC
82 #define TIMEVAL_TO_TIMESPEC(tv, ts) { \
83 (ts)->tv_sec = (tv)->tv_sec; \
84 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
85 }
86 #endif
87
88 #ifndef timersub
89 #define timersub(tvp, uvp, vvp) \
90 do { \
91 (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
92 (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
93 if ((vvp)->tv_usec < 0) { \
94 (vvp)->tv_sec--; \
95 (vvp)->tv_usec += 1000000; \
96 } \
97 } while (/* CONSTCOND */ 0)
98 #endif /* timersub */
99
100
101 void bwlimit(int); 81 void bwlimit(int);
102 82
103 /* Struct for addargs */ 83 /* Struct for addargs */
104 arglist args; 84 arglist args;
105 85
106 /* Bandwidth limit */ 86 /* Bandwidth limit */
107 off_t limitbw = 0; 87 off_t limit_rate = 0;
108 88
109 /* Name of current file being transferred. */ 89 /* Name of current file being transferred. */
110 char *curfile; 90 char *curfile;
111 91
112 /* This is set to non-zero to enable verbose mode. */ 92 /* This is set to non-zero to enable verbose mode. */
113 int verbose_mode = 0; 93 int verbose_mode = 0;
114 94
115 #ifdef PROGRESS_METER
116 /* This is set to zero if the progressmeter is not desired. */ 95 /* This is set to zero if the progressmeter is not desired. */
117 int showprogress = 1; 96 int showprogress = 1;
118 #endif
119 97
120 /* This is the program to execute for the secured connection. ("ssh" or -S) */ 98 /* This is the program to execute for the secured connection. ("ssh" or -S) */
121 char *ssh_program = _PATH_SSH_PROGRAM; 99 char *ssh_program = _PATH_SSH_PROGRAM;
122 100
123 /* This is used to store the pid of ssh_program */ 101 /* This is used to store the pid of ssh_program */
124 pid_t do_cmd_pid = -1; 102 pid_t do_cmd_pid = -1;
125 103
126 static void 104 static void
127 killchild(int signo) 105 killchild(int signo)
128 { 106 {
129 if (do_cmd_pid > 1) 107 if (do_cmd_pid > 1) {
130 kill(do_cmd_pid, signo); 108 kill(do_cmd_pid, signo ? signo : SIGTERM);
131 109 waitpid(do_cmd_pid, NULL, 0);
132 _exit(1); 110 }
111
112 if (signo)
113 _exit(1);
114 exit(1);
115 }
116
117 static int
118 do_local_cmd(arglist *a)
119 {
120 u_int i;
121 int status;
122 pid_t pid;
123
124 if (a->num == 0)
125 fatal("do_local_cmd: no arguments");
126
127 if (verbose_mode) {
128 fprintf(stderr, "Executing:");
129 for (i = 0; i < a->num; i++)
130 fprintf(stderr, " %s", a->list[i]);
131 fprintf(stderr, "\n");
132 }
133 if ((pid = fork()) == -1)
134 fatal("do_local_cmd: fork: %s", strerror(errno));
135
136 if (pid == 0) {
137 execvp(a->list[0], a->list);
138 perror(a->list[0]);
139 exit(1);
140 }
141
142 do_cmd_pid = pid;
143 signal(SIGTERM, killchild);
144 signal(SIGINT, killchild);
145 signal(SIGHUP, killchild);
146
147 while (waitpid(pid, &status, 0) == -1)
148 if (errno != EINTR)
149 fatal("do_local_cmd: waitpid: %s", strerror(errno));
150
151 do_cmd_pid = -1;
152
153 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
154 return (-1);
155
156 return (0);
133 } 157 }
134 158
135 /* 159 /*
136 * This function executes the given command as the specified user on the 160 * This function executes the given command as the specified user on the
137 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 161 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
154 * descriptors 0 and 1 because that will screw up dup2 below. 178 * descriptors 0 and 1 because that will screw up dup2 below.
155 */ 179 */
156 pipe(reserved); 180 pipe(reserved);
157 181
158 /* Create a socket pair for communicating with ssh. */ 182 /* Create a socket pair for communicating with ssh. */
159 if (pipe(pin) < 0 || pipe(pout) < 0) 183 if (pipe(pin) < 0)
160 { 184 fatal("pipe: %s", strerror(errno));
161 fprintf(stderr, "Fatal error: pipe: %s\n", strerror(errno)); 185 if (pipe(pout) < 0)
162 exit(1); 186 fatal("pipe: %s", strerror(errno));
163 }
164 187
165 /* Free the reserved descriptors. */ 188 /* Free the reserved descriptors. */
166 close(reserved[0]); 189 close(reserved[0]);
167 close(reserved[1]); 190 close(reserved[1]);
168 191
192 /* uClinux needs to build the args here before vforking,
193 otherwise we do it later on. */
194 #ifdef __uClinux__
195 replacearg(&args, 0, "%s", ssh_program);
196 if (remuser != NULL)
197 addargs(&args, "-l%s", remuser);
198 addargs(&args, "%s", host);
199 addargs(&args, "%s", cmd);
200 #endif /* __uClinux__ */
201
169 /* Fork a child to execute the command on the remote host using ssh. */ 202 /* Fork a child to execute the command on the remote host using ssh. */
203 #ifndef __uClinux__
204 do_cmd_pid = vfork();
205 #else
170 do_cmd_pid = fork(); 206 do_cmd_pid = fork();
207 #endif /* __uClinux__ */
208
171 if (do_cmd_pid == 0) { 209 if (do_cmd_pid == 0) {
172 /* Child. */ 210 /* Child. */
173 close(pin[1]); 211 close(pin[1]);
174 close(pout[0]); 212 close(pout[0]);
175 dup2(pin[0], 0); 213 dup2(pin[0], 0);
176 dup2(pout[1], 1); 214 dup2(pout[1], 1);
177 close(pin[0]); 215 close(pin[0]);
178 close(pout[1]); 216 close(pout[1]);
179 217
180 args.list[0] = ssh_program; 218 #ifndef __uClinux__
181 if (remuser != NULL) { 219 replacearg(&args, 0, "%s", ssh_program);
182 addargs(&args, "-l"); 220 if (remuser != NULL)
183 addargs(&args, "%s", remuser); 221 addargs(&args, "-l%s", remuser);
184 }
185 addargs(&args, "%s", host); 222 addargs(&args, "%s", host);
186 addargs(&args, "%s", cmd); 223 addargs(&args, "%s", cmd);
224 #endif /* __uClinux__ */
187 225
188 execvp(ssh_program, args.list); 226 execvp(ssh_program, args.list);
189 perror(ssh_program); 227 perror(ssh_program);
190 exit(1); 228 exit(1);
191 } else if (do_cmd_pid == -1) { 229 } else if (do_cmd_pid == -1) {
192 fprintf(stderr, "Fatal error: fork: %s\n", strerror(errno)); 230 fatal("fork: %s", strerror(errno));
193 exit(1); 231 }
194 } 232
233
234 #ifdef __uClinux__
235 /* clean up command */
236 /* pop cmd */
237 xfree(args.list[args.num-1]);
238 args.list[args.num-1]=NULL;
239 args.num--;
240 /* pop host */
241 xfree(args.list[args.num-1]);
242 args.list[args.num-1]=NULL;
243 args.num--;
244 /* pop user */
245 if (remuser != NULL) {
246 xfree(args.list[args.num-1]);
247 args.list[args.num-1]=NULL;
248 args.num--;
249 }
250 #endif /* __uClinux__ */
251
195 /* Parent. Close the other side, and return the local side. */ 252 /* Parent. Close the other side, and return the local side. */
196 close(pin[0]); 253 close(pin[0]);
197 *fdout = pin[1]; 254 *fdout = pin[1];
198 close(pout[1]); 255 close(pout[1]);
199 *fdin = pout[0]; 256 *fdin = pout[0];
202 signal(SIGHUP, killchild); 259 signal(SIGHUP, killchild);
203 return 0; 260 return 0;
204 } 261 }
205 262
206 typedef struct { 263 typedef struct {
207 int cnt; 264 size_t cnt;
208 char *buf; 265 char *buf;
209 } BUF; 266 } BUF;
210 267
211 BUF *allocbuf(BUF *, int, int); 268 BUF *allocbuf(BUF *, int, int);
212 void lostconn(int); 269 void lostconn(int);
233 290
234 #if defined(DBMULTI_scp) || !defined(DROPBEAR_MULTI) 291 #if defined(DBMULTI_scp) || !defined(DROPBEAR_MULTI)
235 #if defined(DBMULTI_scp) && defined(DROPBEAR_MULTI) 292 #if defined(DBMULTI_scp) && defined(DROPBEAR_MULTI)
236 int scp_main(int argc, char **argv) 293 int scp_main(int argc, char **argv)
237 #else 294 #else
295 int
238 main(int argc, char **argv) 296 main(int argc, char **argv)
239 #endif 297 #endif
240 { 298 {
241 int ch, fflag, tflag, status; 299 int ch, fflag, tflag, status;
242 double speed; 300 double speed;
243 char *targ, *endp; 301 char *targ, *endp;
244 extern char *optarg; 302 extern char *optarg;
245 extern int optind; 303 extern int optind;
246 304
305 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
306 sanitise_stdfd();
307
308 memset(&args, '\0', sizeof(args));
247 args.list = NULL; 309 args.list = NULL;
248 addargs(&args, "ssh"); /* overwritten with ssh_program */ 310 addargs(&args, "%s", ssh_program);
249 addargs(&args, "-x"); 311 addargs(&args, "-x");
250 addargs(&args, "-oForwardAgent no"); 312 addargs(&args, "-oForwardAgent no");
313 addargs(&args, "-oPermitLocalCommand no");
251 addargs(&args, "-oClearAllForwardings yes"); 314 addargs(&args, "-oClearAllForwardings yes");
252 315
253 fflag = tflag = 0; 316 fflag = tflag = 0;
254 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1) 317 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
255 switch (ch) { 318 switch (ch) {
275 break; 338 break;
276 case 'l': 339 case 'l':
277 speed = strtod(optarg, &endp); 340 speed = strtod(optarg, &endp);
278 if (speed <= 0 || *endp != '\0') 341 if (speed <= 0 || *endp != '\0')
279 usage(); 342 usage();
280 limitbw = speed * 1024; 343 limit_rate = speed * 1024;
281 break; 344 break;
282 case 'p': 345 case 'p':
283 pflag = 1; 346 pflag = 1;
284 break; 347 break;
285 case 'r': 348 case 'r':
292 addargs(&args, "-v"); 355 addargs(&args, "-v");
293 verbose_mode = 1; 356 verbose_mode = 1;
294 break; 357 break;
295 #ifdef PROGRESS_METER 358 #ifdef PROGRESS_METER
296 case 'q': 359 case 'q':
360 addargs(&args, "-q");
297 showprogress = 0; 361 showprogress = 0;
298 break; 362 break;
299 #endif 363 #endif
300 364
301 /* Server options. */ 365 /* Server options. */
317 usage(); 381 usage();
318 } 382 }
319 argc -= optind; 383 argc -= optind;
320 argv += optind; 384 argv += optind;
321 385
322 if ((pwd = getpwuid(userid = getuid())) == NULL) { 386 if ((pwd = getpwuid(userid = getuid())) == NULL)
323 fprintf(stderr, "unknown user %u", (u_int) userid); 387 fatal("unknown user %u", (u_int) userid);
324 } 388
325
326 #ifdef PROGRESS_METER
327 if (!isatty(STDERR_FILENO)) 389 if (!isatty(STDERR_FILENO))
328 showprogress = 0; 390 showprogress = 0;
329 #endif
330 391
331 remin = STDIN_FILENO; 392 remin = STDIN_FILENO;
332 remout = STDOUT_FILENO; 393 remout = STDOUT_FILENO;
333 394
334 if (fflag) { 395 if (fflag) {
358 (void) signal(SIGPIPE, lostconn); 419 (void) signal(SIGPIPE, lostconn);
359 420
360 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ 421 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
361 toremote(targ, argc, argv); 422 toremote(targ, argc, argv);
362 else { 423 else {
363 tolocal(argc, argv); /* Dest is local host. */
364 if (targetshouldbedirectory) 424 if (targetshouldbedirectory)
365 verifydir(argv[argc - 1]); 425 verifydir(argv[argc - 1]);
426 tolocal(argc, argv); /* Dest is local host. */
366 } 427 }
367 /* 428 /*
368 * Finally check the exit status of the ssh process, if one was forked 429 * Finally check the exit status of the ssh process, if one was forked
369 * and no error has occured yet 430 * and no error has occured yet
370 */ 431 */
380 errs = 1; 441 errs = 1;
381 } 442 }
382 } 443 }
383 exit(errs != 0); 444 exit(errs != 0);
384 } 445 }
385 #endif /* DBMULTI stuff */ 446 #endif /* DBMULTI_scp stuff */
386 447
387 void 448 void
388 toremote(char *targ, int argc, char **argv) 449 toremote(char *targ, int argc, char **argv)
389 { 450 {
390 int i, len; 451 int i, len;
391 char *bp, *host, *src, *suser, *thost, *tuser; 452 char *bp, *host, *src, *suser, *thost, *tuser, *arg;
453 arglist alist;
454
455 memset(&alist, '\0', sizeof(alist));
456 alist.list = NULL;
392 457
393 *targ++ = 0; 458 *targ++ = 0;
394 if (*targ == 0) 459 if (*targ == 0)
395 targ = "."; 460 targ = ".";
396 461
397 if ((thost = strrchr(argv[argc - 1], '@'))) { 462 arg = xstrdup(argv[argc - 1]);
463 if ((thost = strrchr(arg, '@'))) {
398 /* user@host */ 464 /* user@host */
399 *thost++ = 0; 465 *thost++ = 0;
400 tuser = argv[argc - 1]; 466 tuser = arg;
401 if (*tuser == '\0') 467 if (*tuser == '\0')
402 tuser = NULL; 468 tuser = NULL;
403 } else { 469 } else {
404 thost = argv[argc - 1]; 470 thost = arg;
405 tuser = NULL; 471 tuser = NULL;
472 }
473
474 if (tuser != NULL && !okname(tuser)) {
475 xfree(arg);
476 return;
406 } 477 }
407 478
408 for (i = 0; i < argc - 1; i++) { 479 for (i = 0; i < argc - 1; i++) {
409 src = colon(argv[i]); 480 src = colon(argv[i]);
410 if (src) { /* remote to remote */ 481 if (src) { /* remote to remote */
411 static char *ssh_options = 482 freeargs(&alist);
412 "-x -o'ClearAllForwardings yes'"; 483 addargs(&alist, "%s", ssh_program);
484 if (verbose_mode)
485 addargs(&alist, "-v");
486 addargs(&alist, "-x");
487 addargs(&alist, "-oClearAllForwardings yes");
488 addargs(&alist, "-n");
489
413 *src++ = 0; 490 *src++ = 0;
414 if (*src == 0) 491 if (*src == 0)
415 src = "."; 492 src = ".";
416 host = strrchr(argv[i], '@'); 493 host = strrchr(argv[i], '@');
417 len = strlen(ssh_program) + strlen(argv[i]) + 494
418 strlen(src) + (tuser ? strlen(tuser) : 0) +
419 strlen(thost) + strlen(targ) +
420 strlen(ssh_options) + CMDNEEDS + 20;
421 bp = xmalloc(len);
422 if (host) { 495 if (host) {
423 *host++ = 0; 496 *host++ = 0;
424 host = cleanhostname(host); 497 host = cleanhostname(host);
425 suser = argv[i]; 498 suser = argv[i];
426 if (*suser == '\0') 499 if (*suser == '\0')
427 suser = pwd->pw_name; 500 suser = pwd->pw_name;
428 else if (!okname(suser)) { 501 else if (!okname(suser))
429 xfree(bp);
430 continue; 502 continue;
431 } 503 addargs(&alist, "-l");
432 if (tuser && !okname(tuser)) { 504 addargs(&alist, "%s", suser);
433 xfree(bp);
434 continue;
435 }
436 snprintf(bp, len,
437 "%s%s %s -n "
438 "-l %s %s %s %s '%s%s%s:%s'",
439 ssh_program, verbose_mode ? " -v" : "",
440 ssh_options, suser, host, cmd, src,
441 tuser ? tuser : "", tuser ? "@" : "",
442 thost, targ);
443 } else { 505 } else {
444 host = cleanhostname(argv[i]); 506 host = cleanhostname(argv[i]);
445 snprintf(bp, len,
446 "exec %s%s %s -n %s "
447 "%s %s '%s%s%s:%s'",
448 ssh_program, verbose_mode ? " -v" : "",
449 ssh_options, host, cmd, src,
450 tuser ? tuser : "", tuser ? "@" : "",
451 thost, targ);
452 } 507 }
453 if (verbose_mode) 508 addargs(&alist, "%s", host);
454 fprintf(stderr, "Executing: %s\n", bp); 509 addargs(&alist, "%s", cmd);
455 (void) system(bp); 510 addargs(&alist, "%s", src);
456 (void) xfree(bp); 511 addargs(&alist, "%s%s%s:%s",
512 tuser ? tuser : "", tuser ? "@" : "",
513 thost, targ);
514 if (do_local_cmd(&alist) != 0)
515 errs = 1;
457 } else { /* local to remote */ 516 } else { /* local to remote */
458 if (remin == -1) { 517 if (remin == -1) {
459 len = strlen(targ) + CMDNEEDS + 20; 518 len = strlen(targ) + CMDNEEDS + 20;
460 bp = xmalloc(len); 519 bp = xmalloc(len);
461 (void) snprintf(bp, len, "%s -t %s", cmd, targ); 520 (void) snprintf(bp, len, "%s -t %s", cmd, targ);
475 void 534 void
476 tolocal(int argc, char **argv) 535 tolocal(int argc, char **argv)
477 { 536 {
478 int i, len; 537 int i, len;
479 char *bp, *host, *src, *suser; 538 char *bp, *host, *src, *suser;
539 arglist alist;
540
541 memset(&alist, '\0', sizeof(alist));
542 alist.list = NULL;
480 543
481 for (i = 0; i < argc - 1; i++) { 544 for (i = 0; i < argc - 1; i++) {
482 if (!(src = colon(argv[i]))) { /* Local to local. */ 545 if (!(src = colon(argv[i]))) { /* Local to local. */
483 len = strlen(_PATH_CP) + strlen(argv[i]) + 546 freeargs(&alist);
484 strlen(argv[argc - 1]) + 20; 547 addargs(&alist, "%s", _PATH_CP);
485 bp = xmalloc(len); 548 if (iamrecursive)
486 (void) snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, 549 addargs(&alist, "-r");
487 iamrecursive ? " -r" : "", pflag ? " -p" : "", 550 if (pflag)
488 argv[i], argv[argc - 1]); 551 addargs(&alist, "-p");
489 if (verbose_mode) 552 addargs(&alist, "%s", argv[i]);
490 fprintf(stderr, "Executing: %s\n", bp); 553 addargs(&alist, "%s", argv[argc-1]);
491 if (system(bp)) 554 if (do_local_cmd(&alist))
492 ++errs; 555 ++errs;
493 (void) xfree(bp);
494 continue; 556 continue;
495 } 557 }
496 *src++ = 0; 558 *src++ = 0;
497 if (*src == 0) 559 if (*src == 0)
498 src = "."; 560 src = ".";
525 source(int argc, char **argv) 587 source(int argc, char **argv)
526 { 588 {
527 struct stat stb; 589 struct stat stb;
528 static BUF buffer; 590 static BUF buffer;
529 BUF *bp; 591 BUF *bp;
530 off_t i, amt, result, statbytes; 592 off_t i, amt, statbytes;
531 int fd, haderr, indx; 593 size_t result;
594 int fd = -1, haderr, indx;
532 char *last, *name, buf[2048]; 595 char *last, *name, buf[2048];
533 int len; 596 int len;
534 597
535 for (indx = 0; indx < argc; ++indx) { 598 for (indx = 0; indx < argc; ++indx) {
536 name = argv[indx]; 599 name = argv[indx];
580 goto next; 643 goto next;
581 } 644 }
582 #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 645 #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
583 snprintf(buf, sizeof buf, "C%04o %lld %s\n", 646 snprintf(buf, sizeof buf, "C%04o %lld %s\n",
584 (u_int) (stb.st_mode & FILEMODEMASK), 647 (u_int) (stb.st_mode & FILEMODEMASK),
585 (int64_t)stb.st_size, last); 648 (long long)stb.st_size, last);
586 if (verbose_mode) { 649 if (verbose_mode) {
587 fprintf(stderr, "Sending file modes: %s", buf); 650 fprintf(stderr, "Sending file modes: %s", buf);
588 } 651 }
589 (void) atomicio(vwrite, remout, buf, strlen(buf)); 652 (void) atomicio(vwrite, remout, buf, strlen(buf));
590 if (response() < 0) 653 if (response() < 0)
591 goto next; 654 goto next;
592 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { 655 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
593 next: (void) close(fd); 656 next: if (fd != -1) {
657 (void) close(fd);
658 fd = -1;
659 }
594 continue; 660 continue;
595 } 661 }
596 #ifdef PROGRESS_METER 662 #if PROGRESS_METER
597 if (showprogress) 663 if (showprogress)
598 start_progress_meter(curfile, stb.st_size, &statbytes); 664 start_progress_meter(curfile, stb.st_size, &statbytes);
599 #endif 665 #endif
600 /* Keep writing after an error so that we stay sync'd up. */ 666 /* Keep writing after an error so that we stay sync'd up. */
601 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 667 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
603 if (i + amt > stb.st_size) 669 if (i + amt > stb.st_size)
604 amt = stb.st_size - i; 670 amt = stb.st_size - i;
605 if (!haderr) { 671 if (!haderr) {
606 result = atomicio(read, fd, bp->buf, amt); 672 result = atomicio(read, fd, bp->buf, amt);
607 if (result != amt) 673 if (result != amt)
608 haderr = result >= 0 ? EIO : errno; 674 haderr = errno;
609 } 675 }
610 if (haderr) 676 if (haderr)
611 (void) atomicio(vwrite, remout, bp->buf, amt); 677 (void) atomicio(vwrite, remout, bp->buf, amt);
612 else { 678 else {
613 result = atomicio(vwrite, remout, bp->buf, amt); 679 result = atomicio(vwrite, remout, bp->buf, amt);
614 if (result != amt) 680 if (result != amt)
615 haderr = result >= 0 ? EIO : errno; 681 haderr = errno;
616 statbytes += result; 682 statbytes += result;
617 } 683 }
618 if (limitbw) 684 if (limit_rate)
619 bwlimit(amt); 685 bwlimit(amt);
620 } 686 }
621 #ifdef PROGRESS_METER 687 #ifdef PROGRESS_METER
622 if (showprogress) 688 if (showprogress)
623 stop_progress_meter(); 689 stop_progress_meter();
624 #endif 690 #endif
625 691
626 if (close(fd) < 0 && !haderr) 692 if (fd != -1) {
627 haderr = errno; 693 if (close(fd) < 0 && !haderr)
694 haderr = errno;
695 fd = -1;
696 }
628 if (!haderr) 697 if (!haderr)
629 (void) atomicio(vwrite, remout, "", 1); 698 (void) atomicio(vwrite, remout, "", 1);
630 else 699 else
631 run_err("%s: %s", name, strerror(haderr)); 700 run_err("%s: %s", name, strerror(haderr));
632 (void) response(); 701 (void) response();
689 void 758 void
690 bwlimit(int amount) 759 bwlimit(int amount)
691 { 760 {
692 static struct timeval bwstart, bwend; 761 static struct timeval bwstart, bwend;
693 static int lamt, thresh = 16384; 762 static int lamt, thresh = 16384;
694 uint64_t wait; 763 u_int64_t waitlen;
695 struct timespec ts, rm; 764 struct timespec ts, rm;
696 765
697 if (!timerisset(&bwstart)) { 766 if (!timerisset(&bwstart)) {
698 gettimeofday(&bwstart, NULL); 767 gettimeofday(&bwstart, NULL);
699 return; 768 return;
707 timersub(&bwend, &bwstart, &bwend); 776 timersub(&bwend, &bwstart, &bwend);
708 if (!timerisset(&bwend)) 777 if (!timerisset(&bwend))
709 return; 778 return;
710 779
711 lamt *= 8; 780 lamt *= 8;
712 wait = (double)1000000L * lamt / limitbw; 781 waitlen = (double)1000000L * lamt / limit_rate;
713 782
714 bwstart.tv_sec = wait / 1000000L; 783 bwstart.tv_sec = waitlen / 1000000L;
715 bwstart.tv_usec = wait % 1000000L; 784 bwstart.tv_usec = waitlen % 1000000L;
716 785
717 if (timercmp(&bwstart, &bwend, >)) { 786 if (timercmp(&bwstart, &bwend, >)) {
718 timersub(&bwstart, &bwend, &bwend); 787 timersub(&bwstart, &bwend, &bwend);
719 788
720 /* Adjust the wait time */ 789 /* Adjust the wait time */
747 struct stat stb; 816 struct stat stb;
748 enum { 817 enum {
749 YES, NO, DISPLAYED 818 YES, NO, DISPLAYED
750 } wrerr; 819 } wrerr;
751 BUF *bp; 820 BUF *bp;
752 off_t i, j; 821 off_t i;
753 int amt, count, exists, first, mask, mode, ofd, omode; 822 size_t j, count;
823 int amt, exists, first, mask, mode, ofd, omode;
754 off_t size, statbytes; 824 off_t size, statbytes;
755 int setimes, targisdir, wrerrno = 0; 825 int setimes, targisdir, wrerrno = 0;
756 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; 826 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
757 struct timeval tv[2]; 827 struct timeval tv[2];
758 828
759 #define atime tv[0] 829 #define atime tv[0]
760 #define mtime tv[1] 830 #define mtime tv[1]
761 #define SCREWUP(str) do { why = str; goto screwup; } while (0) 831 #define SCREWUP(str) { why = str; goto screwup; }
762 832
763 setimes = targisdir = 0; 833 setimes = targisdir = 0;
764 mask = umask(0); 834 mask = umask(0);
765 if (!pflag) 835 if (!pflag)
766 (void) umask(mask); 836 (void) umask(mask);
775 (void) atomicio(vwrite, remout, "", 1); 845 (void) atomicio(vwrite, remout, "", 1);
776 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 846 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
777 targisdir = 1; 847 targisdir = 1;
778 for (first = 1;; first = 0) { 848 for (first = 1;; first = 0) {
779 cp = buf; 849 cp = buf;
780 if (atomicio(read, remin, cp, 1) <= 0) 850 if (atomicio(read, remin, cp, 1) != 1)
781 return; 851 return;
782 if (*cp++ == '\n') 852 if (*cp++ == '\n')
783 SCREWUP("unexpected <newline>"); 853 SCREWUP("unexpected <newline>");
784 do { 854 do {
785 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 855 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
786 SCREWUP("lost connection"); 856 SCREWUP("lost connection");
787 *cp++ = ch; 857 *cp++ = ch;
788 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); 858 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
789 *cp = 0; 859 *cp = 0;
860 if (verbose_mode)
861 fprintf(stderr, "Sink: %s", buf);
790 862
791 if (buf[0] == '\01' || buf[0] == '\02') { 863 if (buf[0] == '\01' || buf[0] == '\02') {
792 if (iamremote == 0) 864 if (iamremote == 0)
793 (void) atomicio(vwrite, STDERR_FILENO, 865 (void) atomicio(vwrite, STDERR_FILENO,
794 buf + 1, strlen(buf + 1)); 866 buf + 1, strlen(buf + 1));
848 920
849 for (size = 0; isdigit(*cp);) 921 for (size = 0; isdigit(*cp);)
850 size = size * 10 + (*cp++ - '0'); 922 size = size * 10 + (*cp++ - '0');
851 if (*cp++ != ' ') 923 if (*cp++ != ' ')
852 SCREWUP("size not delimited"); 924 SCREWUP("size not delimited");
925 if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
926 run_err("error: unexpected filename: %s", cp);
927 exit(1);
928 }
853 if (targisdir) { 929 if (targisdir) {
854 static char *namebuf; 930 static char *namebuf;
855 static int cursize; 931 static size_t cursize;
856 size_t need; 932 size_t need;
857 933
858 need = strlen(targ) + strlen(cp) + 250; 934 need = strlen(targ) + strlen(cp) + 250;
859 if (need > cursize) { 935 if (need > cursize) {
860 if (namebuf) 936 if (namebuf)
869 np = targ; 945 np = targ;
870 curfile = cp; 946 curfile = cp;
871 exists = stat(np, &stb) == 0; 947 exists = stat(np, &stb) == 0;
872 if (buf[0] == 'D') { 948 if (buf[0] == 'D') {
873 int mod_flag = pflag; 949 int mod_flag = pflag;
950 if (!iamrecursive)
951 SCREWUP("received directory without -r");
874 if (exists) { 952 if (exists) {
875 if (!S_ISDIR(stb.st_mode)) { 953 if (!S_ISDIR(stb.st_mode)) {
876 errno = ENOTDIR; 954 errno = ENOTDIR;
877 goto bad; 955 goto bad;
878 } 956 }
922 amt = 4096; 1000 amt = 4096;
923 if (i + amt > size) 1001 if (i + amt > size)
924 amt = size - i; 1002 amt = size - i;
925 count += amt; 1003 count += amt;
926 do { 1004 do {
927 j = read(remin, cp, amt); 1005 j = atomicio(read, remin, cp, amt);
928 if (j == -1 && (errno == EINTR || 1006 if (j == 0) {
929 errno == EAGAIN)) {
930 continue;
931 } else if (j <= 0) {
932 run_err("%s", j ? strerror(errno) : 1007 run_err("%s", j ? strerror(errno) :
933 "dropped connection"); 1008 "dropped connection");
934 exit(1); 1009 exit(1);
935 } 1010 }
936 amt -= j; 1011 amt -= j;
937 cp += j; 1012 cp += j;
938 statbytes += j; 1013 statbytes += j;
939 } while (amt > 0); 1014 } while (amt > 0);
940 1015
941 if (limitbw) 1016 if (limit_rate)
942 bwlimit(4096); 1017 bwlimit(4096);
943 1018
944 if (count == bp->cnt) { 1019 if (count == bp->cnt) {
945 /* Keep reading so we stay sync'd up. */ 1020 /* Keep reading so we stay sync'd up. */
946 if (wrerr == NO) { 1021 if (wrerr == NO) {
947 j = atomicio(vwrite, ofd, bp->buf, count); 1022 if (atomicio(vwrite, ofd, bp->buf,
948 if (j != count) { 1023 count) != count) {
949 wrerr = YES; 1024 wrerr = YES;
950 wrerrno = j >= 0 ? EIO : errno; 1025 wrerrno = errno;
951 } 1026 }
952 } 1027 }
953 count = 0; 1028 count = 0;
954 cp = bp->buf; 1029 cp = bp->buf;
955 } 1030 }
957 #ifdef PROGRESS_METER 1032 #ifdef PROGRESS_METER
958 if (showprogress) 1033 if (showprogress)
959 stop_progress_meter(); 1034 stop_progress_meter();
960 #endif 1035 #endif
961 if (count != 0 && wrerr == NO && 1036 if (count != 0 && wrerr == NO &&
962 (j = atomicio(vwrite, ofd, bp->buf, count)) != count) { 1037 atomicio(vwrite, ofd, bp->buf, count) != count) {
963 wrerr = YES; 1038 wrerr = YES;
964 wrerrno = j >= 0 ? EIO : errno; 1039 wrerrno = errno;
965 } 1040 }
966 if (wrerr == NO && ftruncate(ofd, size) != 0) { 1041 if (wrerr == NO && ftruncate(ofd, size) != 0) {
967 run_err("%s: truncate: %s", np, strerror(errno)); 1042 run_err("%s: truncate: %s", np, strerror(errno));
968 wrerr = DISPLAYED; 1043 wrerr = DISPLAYED;
969 } 1044 }
970 if (pflag) { 1045 if (pflag) {
971 if (exists || omode != mode) 1046 if (exists || omode != mode)
972 #ifdef HAVE_FCHMOD 1047 #ifdef HAVE_FCHMOD
973 if (fchmod(ofd, omode)) 1048 if (fchmod(ofd, omode)) {
974 #else /* HAVE_FCHMOD */ 1049 #else /* HAVE_FCHMOD */
975 if (chmod(np, omode)) 1050 if (chmod(np, omode)) {
976 #endif /* HAVE_FCHMOD */ 1051 #endif /* HAVE_FCHMOD */
977 run_err("%s: set mode: %s", 1052 run_err("%s: set mode: %s",
978 np, strerror(errno)); 1053 np, strerror(errno));
1054 wrerr = DISPLAYED;
1055 }
979 } else { 1056 } else {
980 if (!exists && omode != mode) 1057 if (!exists && omode != mode)
981 #ifdef HAVE_FCHMOD 1058 #ifdef HAVE_FCHMOD
982 if (fchmod(ofd, omode & ~mask)) 1059 if (fchmod(ofd, omode & ~mask)) {
983 #else /* HAVE_FCHMOD */ 1060 #else /* HAVE_FCHMOD */
984 if (chmod(np, omode & ~mask)) 1061 if (chmod(np, omode & ~mask)) {
985 #endif /* HAVE_FCHMOD */ 1062 #endif /* HAVE_FCHMOD */
986 run_err("%s: set mode: %s", 1063 run_err("%s: set mode: %s",
987 np, strerror(errno)); 1064 np, strerror(errno));
1065 wrerr = DISPLAYED;
1066 }
988 } 1067 }
989 if (close(ofd) == -1) { 1068 if (close(ofd) == -1) {
990 wrerr = YES; 1069 wrerr = YES;
991 wrerrno = errno; 1070 wrerrno = errno;
992 } 1071 }
1050 1129
1051 void 1130 void
1052 usage(void) 1131 usage(void)
1053 { 1132 {
1054 (void) fprintf(stderr, 1133 (void) fprintf(stderr,
1055 "usage: scp [-pqrvBC1246] [-F config] [-S program] [-P port]\n" 1134 "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
1056 " [-c cipher] [-i identity] [-l limit] [-o option]\n" 1135 " [-l limit] [-o ssh_option] [-P port] [-S program]\n"
1057 " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); 1136 " [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
1058 exit(1); 1137 exit(1);
1059 } 1138 }
1060 1139
1061 void 1140 void
1092 if (S_ISDIR(stb.st_mode)) 1171 if (S_ISDIR(stb.st_mode))
1093 return; 1172 return;
1094 errno = ENOTDIR; 1173 errno = ENOTDIR;
1095 } 1174 }
1096 run_err("%s: %s", cp, strerror(errno)); 1175 run_err("%s: %s", cp, strerror(errno));
1097 exit(1); 1176 killchild(0);
1098 } 1177 }
1099 1178
1100 int 1179 int
1101 okname(char *cp0) 1180 okname(char *cp0)
1102 { 1181 {