1 /* $NetBSD: scp.c,v 1.39 2023/08/01 08:47:25 mrg Exp $ */ 2 /* $OpenBSD: scp.c,v 1.253 2023/03/03 03:12:24 dtucker Exp $ */ 3 /* 4 * scp - secure remote copy. This is basically patched BSD rcp which 5 * uses ssh to do the data transfer (instead of using rcmd). 6 * 7 * NOTE: This version should NOT be suid root. (This uses ssh to 8 * do the transfer and ssh has the necessary privileges.) 9 * 10 * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi> 11 * 12 * As far as I am concerned, the code I have written for this software 13 * can be used freely for any purpose. Any derived versions of this 14 * software must be clearly marked as such, and if the derived work is 15 * incompatible with the protocol description in the RFC file, it must be 16 * called by a name other than "ssh" or "Secure Shell". 17 */ 18 /* 19 * Copyright (c) 1999 Theo de Raadt. All rights reserved. 20 * Copyright (c) 1999 Aaron Campbell. All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43 /* 44 * Parts from: 45 * 46 * Copyright (c) 1983, 1990, 1992, 1993, 1995 47 * The Regents of the University of California. All rights reserved. 48 * 49 * Redistribution and use in source and binary forms, with or without 50 * modification, are permitted provided that the following conditions 51 * are met: 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 3. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 * 73 */ 74 75 #include "includes.h" 76 __RCSID("$NetBSD: scp.c,v 1.39 2023/08/01 08:47:25 mrg Exp $"); 77 78 #include <sys/param.h> /* roundup MAX */ 79 #include <sys/types.h> 80 #include <sys/poll.h> 81 #include <sys/wait.h> 82 #include <sys/stat.h> 83 #include <sys/time.h> 84 #include <sys/uio.h> 85 86 #include <ctype.h> 87 #include <dirent.h> 88 #include <errno.h> 89 #include <fcntl.h> 90 #include <fnmatch.h> 91 #include <glob.h> 92 #include <libgen.h> 93 #include <locale.h> 94 #include <pwd.h> 95 #include <signal.h> 96 #include <stdarg.h> 97 #include <stdint.h> 98 #include <stdio.h> 99 #include <stdlib.h> 100 #include <string.h> 101 #include <time.h> 102 #include <unistd.h> 103 #include <limits.h> 104 #include <util.h> 105 #include <vis.h> 106 107 #include "xmalloc.h" 108 #include "ssh.h" 109 #include "atomicio.h" 110 #include "pathnames.h" 111 #include "log.h" 112 #include "misc.h" 113 #include "progressmeter.h" 114 #include "utf8.h" 115 #include "sftp.h" 116 #include "fmt_scaled.h" 117 118 #include "sftp-common.h" 119 #include "sftp-client.h" 120 121 #define COPY_BUFLEN 16384 122 123 int do_cmd(const char *, const char *, const char *, int, int, const char *, int *, int *, pid_t *); 124 int do_cmd2(char *, char *, int, char *, int, int); 125 126 static char empty[] = ""; 127 128 /* Struct for addargs */ 129 arglist args; 130 arglist remote_remote_args; 131 132 /* Bandwidth limit */ 133 long long limit_kbps = 0; 134 struct bwlimit bwlimit; 135 136 /* Name of current file being transferred. */ 137 char *curfile; 138 139 /* This is set to non-zero to enable verbose mode. */ 140 int verbose_mode = 0; 141 LogLevel log_level = SYSLOG_LEVEL_INFO; 142 143 /* This is set to zero if the progressmeter is not desired. */ 144 int showprogress = 1; 145 146 /* 147 * This is set to non-zero if remote-remote copy should be piped 148 * through this process. 149 */ 150 int throughlocal = 1; 151 152 /* Non-standard port to use for the ssh connection or -1. */ 153 int sshport = -1; 154 155 /* This is the program to execute for the secured connection. ("ssh" or -S) */ 156 #ifdef RESCUEDIR 157 const char *ssh_program = RESCUEDIR "/ssh"; 158 #else 159 const char *ssh_program = _PATH_SSH_PROGRAM; 160 #endif 161 162 /* This is used to store the pid of ssh_program */ 163 pid_t do_cmd_pid = -1; 164 pid_t do_cmd_pid2 = -1; 165 166 /* SFTP copy parameters */ 167 size_t sftp_copy_buflen; 168 size_t sftp_nrequests; 169 170 /* Needed for sftp */ 171 volatile sig_atomic_t interrupted = 0; 172 173 int remote_glob(struct sftp_conn *, const char *, int, 174 int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ 175 176 __dead static void 177 killchild(int signo) 178 { 179 if (do_cmd_pid > 1) { 180 kill(do_cmd_pid, signo ? signo : SIGTERM); 181 waitpid(do_cmd_pid, NULL, 0); 182 } 183 if (do_cmd_pid2 > 1) { 184 kill(do_cmd_pid2, signo ? signo : SIGTERM); 185 waitpid(do_cmd_pid2, NULL, 0); 186 } 187 188 if (signo) 189 _exit(1); 190 exit(1); 191 } 192 193 static void 194 suspone(int pid, int signo) 195 { 196 int status; 197 198 if (pid > 1) { 199 kill(pid, signo); 200 while (waitpid(pid, &status, WUNTRACED) == -1 && 201 errno == EINTR) 202 ; 203 } 204 } 205 206 static void 207 suspchild(int signo) 208 { 209 suspone(do_cmd_pid, signo); 210 suspone(do_cmd_pid2, signo); 211 kill(getpid(), SIGSTOP); 212 } 213 214 static int 215 do_local_cmd(arglist *a) 216 { 217 u_int i; 218 int status; 219 pid_t pid; 220 221 if (a->num == 0) 222 fatal("do_local_cmd: no arguments"); 223 224 if (verbose_mode) { 225 fprintf(stderr, "Executing:"); 226 for (i = 0; i < a->num; i++) 227 fmprintf(stderr, " %s", a->list[i]); 228 fprintf(stderr, "\n"); 229 } 230 if ((pid = fork()) == -1) 231 fatal("do_local_cmd: fork: %s", strerror(errno)); 232 233 if (pid == 0) { 234 execvp(a->list[0], a->list); 235 perror(a->list[0]); 236 exit(1); 237 } 238 239 do_cmd_pid = pid; 240 ssh_signal(SIGTERM, killchild); 241 ssh_signal(SIGINT, killchild); 242 ssh_signal(SIGHUP, killchild); 243 244 while (waitpid(pid, &status, 0) == -1) 245 if (errno != EINTR) 246 fatal("do_local_cmd: waitpid: %s", strerror(errno)); 247 248 do_cmd_pid = -1; 249 250 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 251 return (-1); 252 253 return (0); 254 } 255 256 /* 257 * This function executes the given command as the specified user on the 258 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 259 * assigns the input and output file descriptors on success. 260 */ 261 262 int 263 do_cmd(const char *program, const char *host, const char *remuser, int port, int subsystem, 264 const char *cmd, int *fdin, int *fdout, pid_t *pid) 265 { 266 int sv[2]; 267 268 if (verbose_mode) 269 fmprintf(stderr, 270 "Executing: program %s host %s, user %s, command %s\n", 271 program, host, 272 remuser ? remuser : "(unspecified)", cmd); 273 274 if (port == -1) 275 port = sshport; 276 277 /* Create a socket pair for communicating with ssh. */ 278 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) 279 fatal("socketpair: %s", strerror(errno)); 280 281 ssh_signal(SIGTSTP, suspchild); 282 ssh_signal(SIGTTIN, suspchild); 283 ssh_signal(SIGTTOU, suspchild); 284 285 /* Fork a child to execute the command on the remote host using ssh. */ 286 *pid = fork(); 287 switch (*pid) { 288 case -1: 289 fatal("fork: %s", strerror(errno)); 290 case 0: 291 /* Child. */ 292 if (dup2(sv[0], STDIN_FILENO) == -1 || 293 dup2(sv[0], STDOUT_FILENO) == -1) { 294 perror("dup2"); 295 _exit(1); 296 } 297 close(sv[0]); 298 close(sv[1]); 299 replacearg(&args, 0, "%s", program); 300 if (port != -1) { 301 addargs(&args, "-p"); 302 addargs(&args, "%d", port); 303 } 304 if (remuser != NULL) { 305 addargs(&args, "-l"); 306 addargs(&args, "%s", remuser); 307 } 308 if (subsystem) 309 addargs(&args, "-s"); 310 addargs(&args, "--"); 311 addargs(&args, "%s", host); 312 addargs(&args, "%s", cmd); 313 314 execvp(program, args.list); 315 perror(program); 316 _exit(1); 317 default: 318 /* Parent. Close the other side, and return the local side. */ 319 close(sv[0]); 320 *fdin = sv[1]; 321 *fdout = sv[1]; 322 ssh_signal(SIGTERM, killchild); 323 ssh_signal(SIGINT, killchild); 324 ssh_signal(SIGHUP, killchild); 325 return 0; 326 } 327 } 328 329 /* 330 * This function executes a command similar to do_cmd(), but expects the 331 * input and output descriptors to be setup by a previous call to do_cmd(). 332 * This way the input and output of two commands can be connected. 333 */ 334 int 335 do_cmd2(char *host, char *remuser, int port, char *cmd, 336 int fdin, int fdout) 337 { 338 int status; 339 pid_t pid; 340 341 if (verbose_mode) 342 fmprintf(stderr, 343 "Executing: 2nd program %s host %s, user %s, command %s\n", 344 ssh_program, host, 345 remuser ? remuser : "(unspecified)", cmd); 346 347 if (port == -1) 348 port = sshport; 349 350 /* Fork a child to execute the command on the remote host using ssh. */ 351 pid = fork(); 352 if (pid == 0) { 353 if (dup2(fdin, 0) == -1) 354 perror("dup2"); 355 if (dup2(fdout, 1) == -1) 356 perror("dup2"); 357 358 replacearg(&args, 0, "%s", ssh_program); 359 if (port != -1) { 360 addargs(&args, "-p"); 361 addargs(&args, "%d", port); 362 } 363 if (remuser != NULL) { 364 addargs(&args, "-l"); 365 addargs(&args, "%s", remuser); 366 } 367 addargs(&args, "-oBatchMode=yes"); 368 addargs(&args, "--"); 369 addargs(&args, "%s", host); 370 addargs(&args, "%s", cmd); 371 372 execvp(ssh_program, args.list); 373 perror(ssh_program); 374 exit(1); 375 } else if (pid == -1) { 376 fatal("fork: %s", strerror(errno)); 377 } 378 while (waitpid(pid, &status, 0) == -1) 379 if (errno != EINTR) 380 fatal("do_cmd2: waitpid: %s", strerror(errno)); 381 return 0; 382 } 383 384 typedef struct { 385 size_t cnt; 386 char *buf; 387 } BUF; 388 389 BUF *allocbuf(BUF *, int, int); 390 __dead static void lostconn(int); 391 int okname(char *); 392 void run_err(const char *,...) 393 __attribute__((__format__ (printf, 1, 2))) 394 __attribute__((__nonnull__ (1))); 395 int note_err(const char *,...) 396 __attribute__((__format__ (printf, 1, 2))); 397 void verifydir(char *); 398 399 struct passwd *pwd; 400 uid_t userid; 401 int errs, remin, remout, remin2, remout2; 402 int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory; 403 404 #define CMDNEEDS 64 405 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ 406 407 enum scp_mode_e { 408 MODE_SCP, 409 MODE_SFTP 410 }; 411 412 int response(void); 413 void rsource(char *, struct stat *); 414 void sink(int, char *[], const char *); 415 void source(int, char *[]); 416 static void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct); 417 static void toremote(int, char *[], enum scp_mode_e, char *sftp_direct); 418 __dead static void usage(void); 419 420 void source_sftp(int, char *, char *, struct sftp_conn *); 421 void sink_sftp(int, char *, const char *, struct sftp_conn *); 422 void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *, 423 char *, char *); 424 425 int 426 main(int argc, char **argv) 427 { 428 int ch, fflag, tflag, status, r, n; 429 char **newargv, *argv0; 430 const char *errstr; 431 extern char *optarg; 432 extern int optind; 433 enum scp_mode_e mode = MODE_SFTP; 434 char *sftp_direct = NULL; 435 long long llv; 436 437 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 438 sanitise_stdfd(); 439 440 setlocale(LC_CTYPE, ""); 441 442 /* Copy argv, because we modify it */ 443 argv0 = argv[0]; 444 newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); 445 for (n = 0; n < argc; n++) 446 newargv[n] = xstrdup(argv[n]); 447 argv = newargv; 448 449 log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); 450 451 memset(&args, '\0', sizeof(args)); 452 memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); 453 args.list = remote_remote_args.list = NULL; 454 addargs(&args, "%s", ssh_program); 455 addargs(&args, "-x"); 456 addargs(&args, "-oPermitLocalCommand=no"); 457 addargs(&args, "-oClearAllForwardings=yes"); 458 addargs(&args, "-oRemoteCommand=none"); 459 addargs(&args, "-oRequestTTY=no"); 460 461 fflag = Tflag = tflag = 0; 462 while ((ch = getopt(argc, argv, 463 "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:X:")) != -1) { 464 switch (ch) { 465 /* User-visible flags. */ 466 case '1': 467 fatal("SSH protocol v.1 is no longer supported"); 468 break; 469 case '2': 470 /* Ignored */ 471 break; 472 case 'A': 473 case '4': 474 case '6': 475 case 'C': 476 addargs(&args, "-%c", ch); 477 addargs(&remote_remote_args, "-%c", ch); 478 break; 479 case 'D': 480 sftp_direct = optarg; 481 break; 482 case '3': 483 throughlocal = 1; 484 break; 485 case 'R': 486 throughlocal = 0; 487 break; 488 case 'o': 489 case 'c': 490 case 'i': 491 case 'F': 492 case 'J': 493 addargs(&remote_remote_args, "-%c", ch); 494 addargs(&remote_remote_args, "%s", optarg); 495 addargs(&args, "-%c", ch); 496 addargs(&args, "%s", optarg); 497 break; 498 case 'O': 499 mode = MODE_SCP; 500 break; 501 case 's': 502 mode = MODE_SFTP; 503 break; 504 case 'P': 505 sshport = a2port(optarg); 506 if (sshport <= 0) 507 fatal("bad port \"%s\"\n", optarg); 508 break; 509 case 'B': 510 addargs(&remote_remote_args, "-oBatchmode=yes"); 511 addargs(&args, "-oBatchmode=yes"); 512 break; 513 case 'l': 514 limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, 515 &errstr); 516 if (errstr != NULL) 517 usage(); 518 limit_kbps *= 1024; /* kbps */ 519 bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); 520 break; 521 case 'p': 522 pflag = 1; 523 break; 524 case 'r': 525 iamrecursive = 1; 526 break; 527 case 'S': 528 ssh_program = xstrdup(optarg); 529 break; 530 case 'v': 531 addargs(&args, "-v"); 532 addargs(&remote_remote_args, "-v"); 533 if (verbose_mode == 0) 534 log_level = SYSLOG_LEVEL_DEBUG1; 535 else if (log_level < SYSLOG_LEVEL_DEBUG3) 536 log_level++; 537 verbose_mode = 1; 538 break; 539 case 'q': 540 addargs(&args, "-q"); 541 addargs(&remote_remote_args, "-q"); 542 showprogress = 0; 543 break; 544 case 'X': 545 /* Please keep in sync with sftp.c -X */ 546 if (strncmp(optarg, "buffer=", 7) == 0) { 547 r = scan_scaled(optarg + 7, &llv); 548 if (r == 0 && (llv <= 0 || llv > 256 * 1024)) { 549 r = -1; 550 errno = EINVAL; 551 } 552 if (r == -1) { 553 fatal("Invalid buffer size \"%s\": %s", 554 optarg + 7, strerror(errno)); 555 } 556 sftp_copy_buflen = (size_t)llv; 557 } else if (strncmp(optarg, "nrequests=", 10) == 0) { 558 llv = strtonum(optarg + 10, 1, 256 * 1024, 559 &errstr); 560 if (errstr != NULL) { 561 fatal("Invalid number of requests " 562 "\"%s\": %s", optarg + 10, errstr); 563 } 564 sftp_nrequests = (size_t)llv; 565 } else { 566 fatal("Invalid -X option"); 567 } 568 break; 569 570 /* Server options. */ 571 case 'd': 572 targetshouldbedirectory = 1; 573 break; 574 case 'f': /* "from" */ 575 iamremote = 1; 576 fflag = 1; 577 break; 578 case 't': /* "to" */ 579 iamremote = 1; 580 tflag = 1; 581 break; 582 case 'T': 583 Tflag = 1; 584 break; 585 default: 586 usage(); 587 } 588 } 589 argc -= optind; 590 argv += optind; 591 592 log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); 593 594 /* Do this last because we want the user to be able to override it */ 595 addargs(&args, "-oForwardAgent=no"); 596 597 if (iamremote) 598 mode = MODE_SCP; 599 600 if ((pwd = getpwuid(userid = getuid())) == NULL) 601 fatal("unknown user %u", (u_int) userid); 602 603 if (!isatty(STDOUT_FILENO)) 604 showprogress = 0; 605 606 if (pflag) { 607 /* Cannot pledge: -p allows setuid/setgid files... */ 608 } else { 609 #ifdef __OpenBSD__ 610 if (pledge("stdio rpath wpath cpath fattr tty proc exec", 611 NULL) == -1) { 612 perror("pledge"); 613 exit(1); 614 } 615 #endif 616 } 617 618 remin = STDIN_FILENO; 619 remout = STDOUT_FILENO; 620 621 if (fflag) { 622 /* Follow "protocol", send data. */ 623 (void) response(); 624 source(argc, argv); 625 exit(errs != 0); 626 } 627 if (tflag) { 628 /* Receive data. */ 629 sink(argc, argv, NULL); 630 exit(errs != 0); 631 } 632 if (argc < 2) 633 usage(); 634 if (argc > 2) 635 targetshouldbedirectory = 1; 636 637 remin = remout = -1; 638 do_cmd_pid = -1; 639 /* Command to be executed on remote system using "ssh". */ 640 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", 641 verbose_mode ? " -v" : "", 642 iamrecursive ? " -r" : "", pflag ? " -p" : "", 643 targetshouldbedirectory ? " -d" : ""); 644 645 (void) ssh_signal(SIGPIPE, lostconn); 646 647 if (colon(argv[argc - 1])) /* Dest is remote host. */ 648 toremote(argc, argv, mode, sftp_direct); 649 else { 650 if (targetshouldbedirectory) 651 verifydir(argv[argc - 1]); 652 tolocal(argc, argv, mode, sftp_direct); /* Dest is local host. */ 653 } 654 /* 655 * Finally check the exit status of the ssh process, if one was forked 656 * and no error has occurred yet 657 */ 658 if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) { 659 if (remin != -1) 660 (void) close(remin); 661 if (remout != -1) 662 (void) close(remout); 663 if (waitpid(do_cmd_pid, &status, 0) == -1) 664 errs = 1; 665 else { 666 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 667 errs = 1; 668 } 669 } 670 exit(errs != 0); 671 } 672 673 /* Callback from atomicio6 to update progress meter and limit bandwidth */ 674 static int 675 scpio(void *_cnt, size_t s) 676 { 677 off_t *cnt = (off_t *)_cnt; 678 679 *cnt += s; 680 refresh_progress_meter(0); 681 if (limit_kbps > 0) 682 bandwidth_limit(&bwlimit, s); 683 return 0; 684 } 685 686 static int 687 do_times(int fd, int verb, const struct stat *sb) 688 { 689 /* strlen(2^64) == 20; strlen(10^6) == 7 */ 690 char buf[(20 + 7 + 2) * 2 + 2]; 691 692 (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n", 693 (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime), 694 (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime)); 695 if (verb) { 696 fprintf(stderr, "File mtime %lld atime %lld\n", 697 (long long)sb->st_mtime, (long long)sb->st_atime); 698 fprintf(stderr, "Sending file timestamps: %s", buf); 699 } 700 (void) atomicio(vwrite, fd, buf, strlen(buf)); 701 return (response()); 702 } 703 704 static int 705 parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp, 706 char **pathp) 707 { 708 int r; 709 710 r = parse_uri("scp", uri, userp, hostp, portp, pathp); 711 if (r == 0 && *pathp == NULL) 712 *pathp = xstrdup("."); 713 return r; 714 } 715 716 /* Appends a string to an array; returns 0 on success, -1 on alloc failure */ 717 static int 718 append(char *cp, char ***ap, size_t *np) 719 { 720 char **tmp; 721 722 if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL) 723 return -1; 724 tmp[(*np)] = cp; 725 (*np)++; 726 *ap = tmp; 727 return 0; 728 } 729 730 /* 731 * Finds the start and end of the first brace pair in the pattern. 732 * returns 0 on success or -1 for invalid patterns. 733 */ 734 static int 735 find_brace(const char *pattern, int *startp, int *endp) 736 { 737 int i; 738 int in_bracket, brace_level; 739 740 *startp = *endp = -1; 741 in_bracket = brace_level = 0; 742 for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) { 743 switch (pattern[i]) { 744 case '\\': 745 /* skip next character */ 746 if (pattern[i + 1] != '\0') 747 i++; 748 break; 749 case '[': 750 in_bracket = 1; 751 break; 752 case ']': 753 in_bracket = 0; 754 break; 755 case '{': 756 if (in_bracket) 757 break; 758 if (pattern[i + 1] == '}') { 759 /* Protect a single {}, for find(1), like csh */ 760 i++; /* skip */ 761 break; 762 } 763 if (*startp == -1) 764 *startp = i; 765 brace_level++; 766 break; 767 case '}': 768 if (in_bracket) 769 break; 770 if (*startp < 0) { 771 /* Unbalanced brace */ 772 return -1; 773 } 774 if (--brace_level <= 0) 775 *endp = i; 776 break; 777 } 778 } 779 /* unbalanced brackets/braces */ 780 if (*endp < 0 && (*startp >= 0 || in_bracket)) 781 return -1; 782 return 0; 783 } 784 785 /* 786 * Assembles and records a successfully-expanded pattern, returns -1 on 787 * alloc failure. 788 */ 789 static int 790 emit_expansion(const char *pattern, int brace_start, int brace_end, 791 int sel_start, int sel_end, char ***patternsp, size_t *npatternsp) 792 { 793 char *cp; 794 int o = 0, tail_len = strlen(pattern + brace_end + 1); 795 796 if ((cp = malloc(brace_start + (sel_end - sel_start) + 797 tail_len + 1)) == NULL) 798 return -1; 799 800 /* Pattern before initial brace */ 801 if (brace_start > 0) { 802 memcpy(cp, pattern, brace_start); 803 o = brace_start; 804 } 805 /* Current braced selection */ 806 if (sel_end - sel_start > 0) { 807 memcpy(cp + o, pattern + sel_start, 808 sel_end - sel_start); 809 o += sel_end - sel_start; 810 } 811 /* Remainder of pattern after closing brace */ 812 if (tail_len > 0) { 813 memcpy(cp + o, pattern + brace_end + 1, tail_len); 814 o += tail_len; 815 } 816 cp[o] = '\0'; 817 if (append(cp, patternsp, npatternsp) != 0) { 818 free(cp); 819 return -1; 820 } 821 return 0; 822 } 823 824 /* 825 * Expand the first encountered brace in pattern, appending the expanded 826 * patterns it yielded to the *patternsp array. 827 * 828 * Returns 0 on success or -1 on allocation failure. 829 * 830 * Signals whether expansion was performed via *expanded and whether 831 * pattern was invalid via *invalid. 832 */ 833 static int 834 brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp, 835 int *expanded, int *invalid) 836 { 837 int i; 838 int in_bracket, brace_start, brace_end, brace_level; 839 int sel_start, sel_end; 840 841 *invalid = *expanded = 0; 842 843 if (find_brace(pattern, &brace_start, &brace_end) != 0) { 844 *invalid = 1; 845 return 0; 846 } else if (brace_start == -1) 847 return 0; 848 849 in_bracket = brace_level = 0; 850 for (i = sel_start = brace_start + 1; i < brace_end; i++) { 851 switch (pattern[i]) { 852 case '{': 853 if (in_bracket) 854 break; 855 brace_level++; 856 break; 857 case '}': 858 if (in_bracket) 859 break; 860 brace_level--; 861 break; 862 case '[': 863 in_bracket = 1; 864 break; 865 case ']': 866 in_bracket = 0; 867 break; 868 case '\\': 869 if (i < brace_end - 1) 870 i++; /* skip */ 871 break; 872 } 873 if (pattern[i] == ',' || i == brace_end - 1) { 874 if (in_bracket || brace_level > 0) 875 continue; 876 /* End of a selection, emit an expanded pattern */ 877 878 /* Adjust end index for last selection */ 879 sel_end = (i == brace_end - 1) ? brace_end : i; 880 if (emit_expansion(pattern, brace_start, brace_end, 881 sel_start, sel_end, patternsp, npatternsp) != 0) 882 return -1; 883 /* move on to the next selection */ 884 sel_start = i + 1; 885 continue; 886 } 887 } 888 if (in_bracket || brace_level > 0) { 889 *invalid = 1; 890 return 0; 891 } 892 /* success */ 893 *expanded = 1; 894 return 0; 895 } 896 897 /* Expand braces from pattern. Returns 0 on success, -1 on failure */ 898 static int 899 brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp) 900 { 901 char *cp, *cp2, **active = NULL, **done = NULL; 902 size_t i, nactive = 0, ndone = 0; 903 int ret = -1, invalid = 0, expanded = 0; 904 905 *patternsp = NULL; 906 *npatternsp = 0; 907 908 /* Start the worklist with the original pattern */ 909 if ((cp = strdup(pattern)) == NULL) 910 return -1; 911 if (append(cp, &active, &nactive) != 0) { 912 free(cp); 913 return -1; 914 } 915 while (nactive > 0) { 916 cp = active[nactive - 1]; 917 nactive--; 918 if (brace_expand_one(cp, &active, &nactive, 919 &expanded, &invalid) == -1) { 920 free(cp); 921 goto fail; 922 } 923 if (invalid) 924 fatal_f("invalid brace pattern \"%s\"", cp); 925 if (expanded) { 926 /* 927 * Current entry expanded to new entries on the 928 * active list; discard the progenitor pattern. 929 */ 930 free(cp); 931 continue; 932 } 933 /* 934 * Pattern did not expand; append the finename component to 935 * the completed list 936 */ 937 if ((cp2 = strrchr(cp, '/')) != NULL) 938 *cp2++ = '\0'; 939 else 940 cp2 = cp; 941 if (append(xstrdup(cp2), &done, &ndone) != 0) { 942 free(cp); 943 goto fail; 944 } 945 free(cp); 946 } 947 /* success */ 948 *patternsp = done; 949 *npatternsp = ndone; 950 done = NULL; 951 ndone = 0; 952 ret = 0; 953 fail: 954 for (i = 0; i < nactive; i++) 955 free(active[i]); 956 free(active); 957 for (i = 0; i < ndone; i++) 958 free(done[i]); 959 free(done); 960 return ret; 961 } 962 963 static struct sftp_conn * 964 do_sftp_connect(char *host, char *user, int port, char *sftp_direct, 965 int *reminp, int *remoutp, int *pidp) 966 { 967 if (sftp_direct == NULL) { 968 if (do_cmd(ssh_program, host, user, port, 1, "sftp", 969 reminp, remoutp, pidp) < 0) 970 return NULL; 971 972 } else { 973 freeargs(&args); 974 addargs(&args, "sftp-server"); 975 if (do_cmd(sftp_direct, host, NULL, -1, 0, "sftp", 976 reminp, remoutp, pidp) < 0) 977 return NULL; 978 } 979 return do_init(*reminp, *remoutp, 980 sftp_copy_buflen, sftp_nrequests, limit_kbps); 981 } 982 983 static void 984 toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) 985 { 986 char *suser = NULL, *host = NULL, *src = NULL; 987 char *bp, *tuser, *thost, *targ; 988 int sport = -1, tport = -1; 989 struct sftp_conn *conn = NULL, *conn2 = NULL; 990 arglist alist; 991 int i, r, status; 992 u_int j; 993 994 memset(&alist, '\0', sizeof(alist)); 995 alist.list = NULL; 996 997 /* Parse target */ 998 r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ); 999 if (r == -1) { 1000 fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]); 1001 ++errs; 1002 goto out; 1003 } 1004 if (r != 0) { 1005 if (parse_user_host_path(argv[argc - 1], &tuser, &thost, 1006 &targ) == -1) { 1007 fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]); 1008 ++errs; 1009 goto out; 1010 } 1011 } 1012 1013 /* Parse source files */ 1014 for (i = 0; i < argc - 1; i++) { 1015 free(suser); 1016 free(host); 1017 free(src); 1018 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); 1019 if (r == -1) { 1020 fmprintf(stderr, "%s: invalid uri\n", argv[i]); 1021 ++errs; 1022 continue; 1023 } 1024 if (r != 0) { 1025 parse_user_host_path(argv[i], &suser, &host, &src); 1026 } 1027 if (suser != NULL && !okname(suser)) { 1028 ++errs; 1029 continue; 1030 } 1031 if (host && throughlocal) { /* extended remote to remote */ 1032 if (mode == MODE_SFTP) { 1033 if (remin == -1) { 1034 /* Connect to dest now */ 1035 conn = do_sftp_connect(thost, tuser, 1036 tport, sftp_direct, 1037 &remin, &remout, &do_cmd_pid); 1038 if (conn == NULL) { 1039 fatal("Unable to open " 1040 "destination connection"); 1041 } 1042 debug3_f("origin in %d out %d pid %ld", 1043 remin, remout, (long)do_cmd_pid); 1044 } 1045 /* 1046 * XXX remember suser/host/sport and only 1047 * reconnect if they change between arguments. 1048 * would save reconnections for cases like 1049 * scp -3 hosta:/foo hosta:/bar hostb: 1050 */ 1051 /* Connect to origin now */ 1052 conn2 = do_sftp_connect(host, suser, 1053 sport, sftp_direct, 1054 &remin2, &remout2, &do_cmd_pid2); 1055 if (conn2 == NULL) { 1056 fatal("Unable to open " 1057 "source connection"); 1058 } 1059 debug3_f("destination in %d out %d pid %ld", 1060 remin2, remout2, (long)do_cmd_pid2); 1061 throughlocal_sftp(conn2, conn, src, targ); 1062 (void) close(remin2); 1063 (void) close(remout2); 1064 remin2 = remout2 = -1; 1065 if (waitpid(do_cmd_pid2, &status, 0) == -1) 1066 ++errs; 1067 else if (!WIFEXITED(status) || 1068 WEXITSTATUS(status) != 0) 1069 ++errs; 1070 do_cmd_pid2 = -1; 1071 continue; 1072 } else { 1073 xasprintf(&bp, "%s -f %s%s", cmd, 1074 *src == '-' ? "-- " : "", src); 1075 if (do_cmd(ssh_program, host, suser, sport, 0, 1076 bp, &remin, &remout, &do_cmd_pid) < 0) 1077 exit(1); 1078 free(bp); 1079 xasprintf(&bp, "%s -t %s%s", cmd, 1080 *targ == '-' ? "-- " : "", targ); 1081 if (do_cmd2(thost, tuser, tport, bp, 1082 remin, remout) < 0) 1083 exit(1); 1084 free(bp); 1085 (void) close(remin); 1086 (void) close(remout); 1087 remin = remout = -1; 1088 } 1089 } else if (host) { /* standard remote to remote */ 1090 /* 1091 * Second remote user is passed to first remote side 1092 * via scp command-line. Ensure it contains no obvious 1093 * shell characters. 1094 */ 1095 if (tuser != NULL && !okname(tuser)) { 1096 ++errs; 1097 continue; 1098 } 1099 if (tport != -1 && tport != SSH_DEFAULT_PORT) { 1100 /* This would require the remote support URIs */ 1101 fatal("target port not supported with two " 1102 "remote hosts and the -R option"); 1103 } 1104 1105 freeargs(&alist); 1106 addargs(&alist, "%s", ssh_program); 1107 addargs(&alist, "-x"); 1108 addargs(&alist, "-oClearAllForwardings=yes"); 1109 addargs(&alist, "-n"); 1110 for (j = 0; j < remote_remote_args.num; j++) { 1111 addargs(&alist, "%s", 1112 remote_remote_args.list[j]); 1113 } 1114 1115 if (sport != -1) { 1116 addargs(&alist, "-p"); 1117 addargs(&alist, "%d", sport); 1118 } 1119 if (suser) { 1120 addargs(&alist, "-l"); 1121 addargs(&alist, "%s", suser); 1122 } 1123 addargs(&alist, "--"); 1124 addargs(&alist, "%s", host); 1125 addargs(&alist, "%s", cmd); 1126 addargs(&alist, "%s", src); 1127 addargs(&alist, "%s%s%s:%s", 1128 tuser ? tuser : "", tuser ? "@" : "", 1129 thost, targ); 1130 if (do_local_cmd(&alist) != 0) 1131 errs = 1; 1132 } else { /* local to remote */ 1133 if (mode == MODE_SFTP) { 1134 if (remin == -1) { 1135 /* Connect to remote now */ 1136 conn = do_sftp_connect(thost, tuser, 1137 tport, sftp_direct, 1138 &remin, &remout, &do_cmd_pid); 1139 if (conn == NULL) { 1140 fatal("Unable to open sftp " 1141 "connection"); 1142 } 1143 } 1144 1145 /* The protocol */ 1146 source_sftp(1, argv[i], targ, conn); 1147 continue; 1148 } 1149 /* SCP */ 1150 if (remin == -1) { 1151 xasprintf(&bp, "%s -t %s%s", cmd, 1152 *targ == '-' ? "-- " : "", targ); 1153 if (do_cmd(ssh_program, thost, tuser, tport, 0, 1154 bp, &remin, &remout, &do_cmd_pid) < 0) 1155 exit(1); 1156 if (response() < 0) 1157 exit(1); 1158 free(bp); 1159 } 1160 source(1, argv + i); 1161 } 1162 } 1163 out: 1164 if (mode == MODE_SFTP) 1165 free(conn); 1166 free(tuser); 1167 free(thost); 1168 free(targ); 1169 free(suser); 1170 free(host); 1171 free(src); 1172 } 1173 1174 static void 1175 tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) 1176 { 1177 char *bp, *host = NULL, *suser = NULL, *src = NULL; 1178 arglist alist; 1179 struct sftp_conn *conn = NULL; 1180 int i, r, sport = -1; 1181 1182 memset(&alist, '\0', sizeof(alist)); 1183 alist.list = NULL; 1184 1185 for (i = 0; i < argc - 1; i++) { 1186 free(suser); 1187 free(host); 1188 free(src); 1189 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); 1190 if (r == -1) { 1191 fmprintf(stderr, "%s: invalid uri\n", argv[i]); 1192 ++errs; 1193 continue; 1194 } 1195 if (r != 0) 1196 parse_user_host_path(argv[i], &suser, &host, &src); 1197 if (suser != NULL && !okname(suser)) { 1198 ++errs; 1199 continue; 1200 } 1201 if (!host) { /* Local to local. */ 1202 freeargs(&alist); 1203 addargs(&alist, "%s", _PATH_CP); 1204 if (iamrecursive) 1205 addargs(&alist, "-r"); 1206 if (pflag) 1207 addargs(&alist, "-p"); 1208 addargs(&alist, "--"); 1209 addargs(&alist, "%s", argv[i]); 1210 addargs(&alist, "%s", argv[argc-1]); 1211 if (do_local_cmd(&alist)) 1212 ++errs; 1213 continue; 1214 } 1215 /* Remote to local. */ 1216 if (mode == MODE_SFTP) { 1217 conn = do_sftp_connect(host, suser, sport, 1218 sftp_direct, &remin, &remout, &do_cmd_pid); 1219 if (conn == NULL) { 1220 error("sftp connection failed"); 1221 ++errs; 1222 continue; 1223 } 1224 1225 /* The protocol */ 1226 sink_sftp(1, argv[argc - 1], src, conn); 1227 1228 free(conn); 1229 (void) close(remin); 1230 (void) close(remout); 1231 remin = remout = -1; 1232 continue; 1233 } 1234 /* SCP */ 1235 xasprintf(&bp, "%s -f %s%s", 1236 cmd, *src == '-' ? "-- " : "", src); 1237 if (do_cmd(ssh_program, host, suser, sport, 0, bp, 1238 &remin, &remout, &do_cmd_pid) < 0) { 1239 free(bp); 1240 ++errs; 1241 continue; 1242 } 1243 free(bp); 1244 sink(1, argv + argc - 1, src); 1245 (void) close(remin); 1246 remin = remout = -1; 1247 } 1248 free(suser); 1249 free(host); 1250 free(src); 1251 } 1252 1253 /* Prepare remote path, handling ~ by assuming cwd is the homedir */ 1254 static char * 1255 prepare_remote_path(struct sftp_conn *conn, const char *path) 1256 { 1257 size_t nslash; 1258 1259 /* Handle ~ prefixed paths */ 1260 if (*path == '\0' || strcmp(path, "~") == 0) 1261 return xstrdup("."); 1262 if (*path != '~') 1263 return xstrdup(path); 1264 if (strncmp(path, "~/", 2) == 0) { 1265 if ((nslash = strspn(path + 2, "/")) == strlen(path + 2)) 1266 return xstrdup("."); 1267 return xstrdup(path + 2 + nslash); 1268 } 1269 if (can_expand_path(conn)) 1270 return do_expand_path(conn, path); 1271 /* No protocol extension */ 1272 error("server expand-path extension is required " 1273 "for ~user paths in SFTP mode"); 1274 return NULL; 1275 } 1276 1277 void 1278 source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) 1279 { 1280 char *target = NULL, *filename = NULL, *abs_dst = NULL; 1281 int src_is_dir, target_is_dir; 1282 Attrib a; 1283 struct stat st; 1284 1285 memset(&a, '\0', sizeof(a)); 1286 if (stat(src, &st) != 0) 1287 fatal("stat local \"%s\": %s", src, strerror(errno)); 1288 src_is_dir = S_ISDIR(st.st_mode); 1289 if ((filename = basename(src)) == NULL) 1290 fatal("basename \"%s\": %s", src, strerror(errno)); 1291 1292 /* 1293 * No need to glob here - the local shell already took care of 1294 * the expansions 1295 */ 1296 if ((target = prepare_remote_path(conn, targ)) == NULL) 1297 cleanup_exit(255); 1298 target_is_dir = remote_is_dir(conn, target); 1299 if (targetshouldbedirectory && !target_is_dir) { 1300 debug("target directory \"%s\" does not exist", target); 1301 a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; 1302 a.perm = st.st_mode | 0700; /* ensure writable */ 1303 if (do_mkdir(conn, target, &a, 1) != 0) 1304 cleanup_exit(255); /* error already logged */ 1305 target_is_dir = 1; 1306 } 1307 if (target_is_dir) 1308 abs_dst = path_append(target, filename); 1309 else { 1310 abs_dst = target; 1311 target = NULL; 1312 } 1313 debug3_f("copying local %s to remote %s", src, abs_dst); 1314 1315 if (src_is_dir && iamrecursive) { 1316 if (upload_dir(conn, src, abs_dst, pflag, 1317 SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { 1318 error("failed to upload directory %s to %s", src, targ); 1319 errs = 1; 1320 } 1321 } else if (do_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { 1322 error("failed to upload file %s to %s", src, targ); 1323 errs = 1; 1324 } 1325 1326 free(abs_dst); 1327 free(target); 1328 } 1329 1330 void 1331 source(int argc, char **argv) 1332 { 1333 struct stat stb; 1334 static BUF buffer; 1335 BUF *bp; 1336 off_t i, statbytes; 1337 size_t amt, nr; 1338 int fd = -1, haderr, indx; 1339 char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX]; 1340 int len; 1341 1342 for (indx = 0; indx < argc; ++indx) { 1343 fd = -1; 1344 name = argv[indx]; 1345 statbytes = 0; 1346 len = strlen(name); 1347 while (len > 1 && name[len-1] == '/') 1348 name[--len] = '\0'; 1349 if ((fd = open(name, O_RDONLY|O_NONBLOCK)) == -1) 1350 goto syserr; 1351 if (strchr(name, '\n') != NULL) { 1352 strvisx(encname, name, len, VIS_NL); 1353 name = encname; 1354 } 1355 if (fstat(fd, &stb) == -1) { 1356 syserr: run_err("%s: %s", name, strerror(errno)); 1357 goto next; 1358 } 1359 if (stb.st_size < 0) { 1360 run_err("%s: %s", name, "Negative file size"); 1361 goto next; 1362 } 1363 unset_nonblock(fd); 1364 switch (stb.st_mode & S_IFMT) { 1365 case S_IFREG: 1366 break; 1367 case S_IFDIR: 1368 if (iamrecursive) { 1369 rsource(name, &stb); 1370 goto next; 1371 } 1372 /* FALLTHROUGH */ 1373 default: 1374 run_err("%s: not a regular file", name); 1375 goto next; 1376 } 1377 if ((last = strrchr(name, '/')) == NULL) 1378 last = name; 1379 else 1380 ++last; 1381 curfile = last; 1382 if (pflag) { 1383 if (do_times(remout, verbose_mode, &stb) < 0) 1384 goto next; 1385 } 1386 #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 1387 snprintf(buf, sizeof buf, "C%04o %lld %s\n", 1388 (u_int) (stb.st_mode & FILEMODEMASK), 1389 (long long)stb.st_size, last); 1390 if (verbose_mode) 1391 fmprintf(stderr, "Sending file modes: %s", buf); 1392 (void) atomicio(vwrite, remout, buf, strlen(buf)); 1393 if (response() < 0) 1394 goto next; 1395 if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) { 1396 next: if (fd != -1) { 1397 (void) close(fd); 1398 fd = -1; 1399 } 1400 continue; 1401 } 1402 if (showprogress) 1403 start_progress_meter(curfile, stb.st_size, &statbytes); 1404 set_nonblock(remout); 1405 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 1406 amt = bp->cnt; 1407 if (i + (off_t)amt > stb.st_size) 1408 amt = stb.st_size - i; 1409 if (!haderr) { 1410 if ((nr = atomicio(read, fd, 1411 bp->buf, amt)) != amt) { 1412 haderr = errno; 1413 memset(bp->buf + nr, 0, amt - nr); 1414 } 1415 } 1416 /* Keep writing after error to retain sync */ 1417 if (haderr) { 1418 (void)atomicio(vwrite, remout, bp->buf, amt); 1419 memset(bp->buf, 0, amt); 1420 continue; 1421 } 1422 if (atomicio6(vwrite, remout, bp->buf, amt, scpio, 1423 &statbytes) != amt) 1424 haderr = errno; 1425 } 1426 unset_nonblock(remout); 1427 1428 if (fd != -1) { 1429 if (close(fd) == -1 && !haderr) 1430 haderr = errno; 1431 fd = -1; 1432 } 1433 if (!haderr) 1434 (void) atomicio(vwrite, remout, empty, 1); 1435 else 1436 run_err("%s: %s", name, strerror(haderr)); 1437 (void) response(); 1438 if (showprogress) 1439 stop_progress_meter(); 1440 } 1441 } 1442 1443 void 1444 rsource(char *name, struct stat *statp) 1445 { 1446 DIR *dirp; 1447 struct dirent *dp; 1448 char *last, *vect[1], path[PATH_MAX + 20]; 1449 1450 if (!(dirp = opendir(name))) { 1451 run_err("%s: %s", name, strerror(errno)); 1452 return; 1453 } 1454 last = strrchr(name, '/'); 1455 if (last == NULL) 1456 last = name; 1457 else 1458 last++; 1459 if (pflag) { 1460 if (do_times(remout, verbose_mode, statp) < 0) { 1461 closedir(dirp); 1462 return; 1463 } 1464 } 1465 (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", 1466 (u_int) (statp->st_mode & FILEMODEMASK), 0, last); 1467 if (verbose_mode) 1468 fmprintf(stderr, "Entering directory: %s", path); 1469 (void) atomicio(vwrite, remout, path, strlen(path)); 1470 if (response() < 0) { 1471 closedir(dirp); 1472 return; 1473 } 1474 while ((dp = readdir(dirp)) != NULL) { 1475 if (dp->d_ino == 0) 1476 continue; 1477 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 1478 continue; 1479 if ((size_t)snprintf(path, sizeof path, "%s/%s", 1480 name, dp->d_name) >= sizeof path) { 1481 run_err("%s/%s: name too long", name, dp->d_name); 1482 continue; 1483 } 1484 vect[0] = path; 1485 source(1, vect); 1486 } 1487 (void) closedir(dirp); 1488 (void) atomicio(vwrite, remout, __UNCONST("E\n"), 2); 1489 (void) response(); 1490 } 1491 1492 void 1493 sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) 1494 { 1495 char *abs_src = NULL; 1496 char *abs_dst = NULL; 1497 glob_t g; 1498 char *filename, *tmp = NULL; 1499 int i, r, err = 0, dst_is_dir; 1500 struct stat st; 1501 1502 memset(&g, 0, sizeof(g)); 1503 1504 /* 1505 * Here, we need remote glob as SFTP can not depend on remote shell 1506 * expansions 1507 */ 1508 if ((abs_src = prepare_remote_path(conn, src)) == NULL) { 1509 err = -1; 1510 goto out; 1511 } 1512 1513 debug3_f("copying remote %s to local %s", abs_src, dst); 1514 if ((r = remote_glob(conn, abs_src, GLOB_NOCHECK|GLOB_MARK, 1515 NULL, &g)) != 0) { 1516 if (r == GLOB_NOSPACE) 1517 error("%s: too many glob matches", src); 1518 else 1519 error("%s: %s", src, strerror(ENOENT)); 1520 err = -1; 1521 goto out; 1522 } 1523 1524 /* Did we actually get any matches back from the glob? */ 1525 if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) { 1526 /* 1527 * If nothing matched but a path returned, then it's probably 1528 * a GLOB_NOCHECK result. Check whether the unglobbed path 1529 * exists so we can give a nice error message early. 1530 */ 1531 if (do_stat(conn, g.gl_pathv[0], 1) == NULL) { 1532 error("%s: %s", src, strerror(ENOENT)); 1533 err = -1; 1534 goto out; 1535 } 1536 } 1537 1538 if ((r = stat(dst, &st)) != 0) 1539 debug2_f("stat local \"%s\": %s", dst, strerror(errno)); 1540 dst_is_dir = r == 0 && S_ISDIR(st.st_mode); 1541 1542 if (g.gl_matchc > 1 && !dst_is_dir) { 1543 if (r == 0) { 1544 error("Multiple files match pattern, but destination " 1545 "\"%s\" is not a directory", dst); 1546 err = -1; 1547 goto out; 1548 } 1549 debug2_f("creating destination \"%s\"", dst); 1550 if (mkdir(dst, 0777) != 0) { 1551 error("local mkdir \"%s\": %s", dst, strerror(errno)); 1552 err = -1; 1553 goto out; 1554 } 1555 dst_is_dir = 1; 1556 } 1557 1558 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 1559 tmp = xstrdup(g.gl_pathv[i]); 1560 if ((filename = basename(tmp)) == NULL) { 1561 error("basename %s: %s", tmp, strerror(errno)); 1562 err = -1; 1563 goto out; 1564 } 1565 1566 if (dst_is_dir) 1567 abs_dst = path_append(dst, filename); 1568 else 1569 abs_dst = xstrdup(dst); 1570 1571 debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 1572 if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { 1573 if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 1574 pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) 1575 err = -1; 1576 } else { 1577 if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, 1578 pflag, 0, 0, 1) == -1) 1579 err = -1; 1580 } 1581 free(abs_dst); 1582 abs_dst = NULL; 1583 free(tmp); 1584 tmp = NULL; 1585 } 1586 1587 out: 1588 free(abs_src); 1589 free(tmp); 1590 globfree(&g); 1591 if (err == -1) 1592 errs = 1; 1593 } 1594 1595 1596 #define TYPE_OVERFLOW(type, val) \ 1597 ((sizeof(type) == 4 && (val) > INT32_MAX) || \ 1598 (sizeof(type) == 8 && (val) > INT64_MAX) || \ 1599 (sizeof(type) != 4 && sizeof(type) != 8)) 1600 1601 void 1602 sink(int argc, char **argv, const char *src) 1603 { 1604 static BUF buffer; 1605 struct stat stb; 1606 BUF *bp; 1607 off_t i; 1608 size_t j, count; 1609 int amt, exists, first, ofd; 1610 mode_t mode, omode, mask; 1611 off_t size, statbytes; 1612 unsigned long long ull; 1613 int setimes, targisdir, wrerr; 1614 char ch, *cp, *np, *targ, *vect[1], buf[2048], visbuf[2048]; 1615 const char *why; 1616 char **patterns = NULL; 1617 size_t n, npatterns = 0; 1618 struct timeval tv[2]; 1619 1620 #define atime tv[0] 1621 #define mtime tv[1] 1622 #define SCREWUP(str) { why = str; goto screwup; } 1623 1624 if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0)) 1625 SCREWUP("Unexpected off_t/time_t size"); 1626 1627 setimes = targisdir = 0; 1628 mask = umask(0); 1629 if (!pflag) 1630 (void) umask(mask); 1631 if (argc != 1) { 1632 run_err("ambiguous target"); 1633 exit(1); 1634 } 1635 targ = *argv; 1636 if (targetshouldbedirectory) 1637 verifydir(targ); 1638 1639 (void) atomicio(vwrite, remout, empty, 1); 1640 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 1641 targisdir = 1; 1642 if (src != NULL && !iamrecursive && !Tflag) { 1643 /* 1644 * Prepare to try to restrict incoming filenames to match 1645 * the requested destination file glob. 1646 */ 1647 if (brace_expand(src, &patterns, &npatterns) != 0) 1648 fatal_f("could not expand pattern"); 1649 } 1650 for (first = 1;; first = 0) { 1651 cp = buf; 1652 if (atomicio(read, remin, cp, 1) != 1) 1653 goto done; 1654 if (*cp++ == '\n') 1655 SCREWUP("unexpected <newline>"); 1656 do { 1657 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 1658 SCREWUP("lost connection"); 1659 *cp++ = ch; 1660 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); 1661 *cp = 0; 1662 if (verbose_mode) 1663 fmprintf(stderr, "Sink: %s", buf); 1664 1665 if (buf[0] == '\01' || buf[0] == '\02') { 1666 if (iamremote == 0) { 1667 (void) snmprintf(visbuf, sizeof(visbuf), 1668 NULL, "%s", buf + 1); 1669 (void) atomicio(vwrite, STDERR_FILENO, 1670 visbuf, strlen(visbuf)); 1671 } 1672 if (buf[0] == '\02') 1673 exit(1); 1674 ++errs; 1675 continue; 1676 } 1677 if (buf[0] == 'E') { 1678 (void) atomicio(vwrite, remout, __UNCONST(""), 1); 1679 goto done; 1680 } 1681 if (ch == '\n') 1682 *--cp = 0; 1683 1684 cp = buf; 1685 if (*cp == 'T') { 1686 setimes++; 1687 cp++; 1688 if (!isdigit((unsigned char)*cp)) 1689 SCREWUP("mtime.sec not present"); 1690 ull = strtoull(cp, &cp, 10); 1691 if (!cp || *cp++ != ' ') 1692 SCREWUP("mtime.sec not delimited"); 1693 if (TYPE_OVERFLOW(time_t, ull)) 1694 setimes = 0; /* out of range */ 1695 mtime.tv_sec = ull; 1696 mtime.tv_usec = strtol(cp, &cp, 10); 1697 if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 || 1698 mtime.tv_usec > 999999) 1699 SCREWUP("mtime.usec not delimited"); 1700 if (!isdigit((unsigned char)*cp)) 1701 SCREWUP("atime.sec not present"); 1702 ull = strtoull(cp, &cp, 10); 1703 if (!cp || *cp++ != ' ') 1704 SCREWUP("atime.sec not delimited"); 1705 if (TYPE_OVERFLOW(time_t, ull)) 1706 setimes = 0; /* out of range */ 1707 atime.tv_sec = ull; 1708 atime.tv_usec = strtol(cp, &cp, 10); 1709 if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || 1710 atime.tv_usec > 999999) 1711 SCREWUP("atime.usec not delimited"); 1712 (void) atomicio(vwrite, remout, empty, 1); 1713 continue; 1714 } 1715 if (*cp != 'C' && *cp != 'D') { 1716 /* 1717 * Check for the case "rcp remote:foo\* local:bar". 1718 * In this case, the line "No match." can be returned 1719 * by the shell before the rcp command on the remote is 1720 * executed so the ^Aerror_message convention isn't 1721 * followed. 1722 */ 1723 if (first) { 1724 run_err("%s", cp); 1725 exit(1); 1726 } 1727 SCREWUP("expected control record"); 1728 } 1729 mode = 0; 1730 for (++cp; cp < buf + 5; cp++) { 1731 if (*cp < '0' || *cp > '7') 1732 SCREWUP("bad mode"); 1733 mode = (mode << 3) | (*cp - '0'); 1734 } 1735 if (!pflag) 1736 mode &= ~mask; 1737 if (*cp++ != ' ') 1738 SCREWUP("mode not delimited"); 1739 1740 if (!isdigit((unsigned char)*cp)) 1741 SCREWUP("size not present"); 1742 ull = strtoull(cp, &cp, 10); 1743 if (!cp || *cp++ != ' ') 1744 SCREWUP("size not delimited"); 1745 if (TYPE_OVERFLOW(off_t, ull)) 1746 SCREWUP("size out of range"); 1747 size = (off_t)ull; 1748 1749 if (*cp == '\0' || strchr(cp, '/') != NULL || 1750 strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) { 1751 run_err("error: unexpected filename: %s", cp); 1752 exit(1); 1753 } 1754 if (npatterns > 0) { 1755 for (n = 0; n < npatterns; n++) { 1756 if (strcmp(patterns[n], cp) == 0 || 1757 fnmatch(patterns[n], cp, 0) == 0) 1758 break; 1759 } 1760 if (n >= npatterns) 1761 SCREWUP("filename does not match request"); 1762 } 1763 if (targisdir) { 1764 static char *namebuf; 1765 static size_t cursize; 1766 size_t need; 1767 1768 need = strlen(targ) + strlen(cp) + 250; 1769 if (need > cursize) { 1770 free(namebuf); 1771 namebuf = xmalloc(need); 1772 cursize = need; 1773 } 1774 (void) snprintf(namebuf, need, "%s%s%s", targ, 1775 strcmp(targ, "/") ? "/" : "", cp); 1776 np = namebuf; 1777 } else 1778 np = targ; 1779 curfile = cp; 1780 exists = stat(np, &stb) == 0; 1781 if (buf[0] == 'D') { 1782 int mod_flag = pflag; 1783 if (!iamrecursive) 1784 SCREWUP("received directory without -r"); 1785 if (exists) { 1786 if (!S_ISDIR(stb.st_mode)) { 1787 errno = ENOTDIR; 1788 goto bad; 1789 } 1790 if (pflag) 1791 (void) chmod(np, mode); 1792 } else { 1793 /* Handle copying from a read-only directory */ 1794 mod_flag = 1; 1795 if (mkdir(np, mode | S_IRWXU) == -1) 1796 goto bad; 1797 } 1798 vect[0] = xstrdup(np); 1799 sink(1, vect, src); 1800 if (setimes) { 1801 setimes = 0; 1802 (void) utimes(vect[0], tv); 1803 } 1804 if (mod_flag) 1805 (void) chmod(vect[0], mode); 1806 free(vect[0]); 1807 continue; 1808 } 1809 omode = mode; 1810 mode |= S_IWUSR; 1811 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { 1812 bad: run_err("%s: %s", np, strerror(errno)); 1813 continue; 1814 } 1815 (void) atomicio(vwrite, remout, empty, 1); 1816 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { 1817 (void) close(ofd); 1818 continue; 1819 } 1820 cp = bp->buf; 1821 wrerr = 0; 1822 1823 /* 1824 * NB. do not use run_err() unless immediately followed by 1825 * exit() below as it may send a spurious reply that might 1826 * desyncronise us from the peer. Use note_err() instead. 1827 */ 1828 statbytes = 0; 1829 if (showprogress) 1830 start_progress_meter(curfile, size, &statbytes); 1831 set_nonblock(remin); 1832 for (count = i = 0; i < size; i += bp->cnt) { 1833 amt = bp->cnt; 1834 if (i + amt > size) 1835 amt = size - i; 1836 count += amt; 1837 do { 1838 j = atomicio6(read, remin, cp, amt, 1839 scpio, &statbytes); 1840 if (j == 0) { 1841 run_err("%s", j != EPIPE ? 1842 strerror(errno) : 1843 "dropped connection"); 1844 exit(1); 1845 } 1846 amt -= j; 1847 cp += j; 1848 } while (amt > 0); 1849 1850 if (count == bp->cnt) { 1851 /* Keep reading so we stay sync'd up. */ 1852 if (!wrerr) { 1853 if (atomicio(vwrite, ofd, bp->buf, 1854 count) != count) { 1855 note_err("%s: %s", np, 1856 strerror(errno)); 1857 wrerr = 1; 1858 } 1859 } 1860 count = 0; 1861 cp = bp->buf; 1862 } 1863 } 1864 unset_nonblock(remin); 1865 if (count != 0 && !wrerr && 1866 atomicio(vwrite, ofd, bp->buf, count) != count) { 1867 note_err("%s: %s", np, strerror(errno)); 1868 wrerr = 1; 1869 } 1870 if (!wrerr && (!exists || S_ISREG(stb.st_mode)) && 1871 ftruncate(ofd, size) != 0) 1872 note_err("%s: truncate: %s", np, strerror(errno)); 1873 if (pflag) { 1874 if (exists || omode != mode) 1875 if (fchmod(ofd, omode)) { 1876 note_err("%s: set mode: %s", 1877 np, strerror(errno)); 1878 } 1879 } else { 1880 if (!exists && omode != mode) 1881 if (fchmod(ofd, omode & ~mask)) { 1882 note_err("%s: set mode: %s", 1883 np, strerror(errno)); 1884 } 1885 } 1886 if (close(ofd) == -1) 1887 note_err("%s: close: %s", np, strerror(errno)); 1888 (void) response(); 1889 if (showprogress) 1890 stop_progress_meter(); 1891 if (setimes && !wrerr) { 1892 setimes = 0; 1893 if (utimes(np, tv) == -1) { 1894 note_err("%s: set times: %s", 1895 np, strerror(errno)); 1896 } 1897 } 1898 /* If no error was noted then signal success for this file */ 1899 if (note_err(NULL) == 0) 1900 (void) atomicio(vwrite, remout, __UNCONST(""), 1); 1901 } 1902 done: 1903 for (n = 0; n < npatterns; n++) 1904 free(patterns[n]); 1905 free(patterns); 1906 return; 1907 screwup: 1908 for (n = 0; n < npatterns; n++) 1909 free(patterns[n]); 1910 free(patterns); 1911 run_err("protocol error: %s", why); 1912 exit(1); 1913 } 1914 1915 void 1916 throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, 1917 char *src, char *targ) 1918 { 1919 char *target = NULL, *filename = NULL, *abs_dst = NULL; 1920 char *abs_src = NULL, *tmp = NULL; 1921 glob_t g; 1922 int i, r, targetisdir, err = 0; 1923 1924 if ((filename = basename(src)) == NULL) 1925 fatal("basename %s: %s", src, strerror(errno)); 1926 1927 if ((abs_src = prepare_remote_path(from, src)) == NULL || 1928 (target = prepare_remote_path(to, targ)) == NULL) 1929 cleanup_exit(255); 1930 memset(&g, 0, sizeof(g)); 1931 1932 targetisdir = remote_is_dir(to, target); 1933 if (!targetisdir && targetshouldbedirectory) { 1934 error("%s: destination is not a directory", targ); 1935 err = -1; 1936 goto out; 1937 } 1938 1939 debug3_f("copying remote %s to remote %s", abs_src, target); 1940 if ((r = remote_glob(from, abs_src, GLOB_NOCHECK|GLOB_MARK, 1941 NULL, &g)) != 0) { 1942 if (r == GLOB_NOSPACE) 1943 error("%s: too many glob matches", src); 1944 else 1945 error("%s: %s", src, strerror(ENOENT)); 1946 err = -1; 1947 goto out; 1948 } 1949 1950 /* Did we actually get any matches back from the glob? */ 1951 if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) { 1952 /* 1953 * If nothing matched but a path returned, then it's probably 1954 * a GLOB_NOCHECK result. Check whether the unglobbed path 1955 * exists so we can give a nice error message early. 1956 */ 1957 if (do_stat(from, g.gl_pathv[0], 1) == NULL) { 1958 error("%s: %s", src, strerror(ENOENT)); 1959 err = -1; 1960 goto out; 1961 } 1962 } 1963 1964 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 1965 tmp = xstrdup(g.gl_pathv[i]); 1966 if ((filename = basename(tmp)) == NULL) { 1967 error("basename %s: %s", tmp, strerror(errno)); 1968 err = -1; 1969 goto out; 1970 } 1971 1972 if (targetisdir) 1973 abs_dst = path_append(target, filename); 1974 else 1975 abs_dst = xstrdup(target); 1976 1977 debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 1978 if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { 1979 if (crossload_dir(from, to, g.gl_pathv[i], abs_dst, 1980 NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1) 1981 err = -1; 1982 } else { 1983 if (do_crossload(from, to, g.gl_pathv[i], abs_dst, NULL, 1984 pflag) == -1) 1985 err = -1; 1986 } 1987 free(abs_dst); 1988 abs_dst = NULL; 1989 free(tmp); 1990 tmp = NULL; 1991 } 1992 1993 out: 1994 free(abs_src); 1995 free(abs_dst); 1996 free(target); 1997 free(tmp); 1998 globfree(&g); 1999 if (err == -1) 2000 errs = 1; 2001 } 2002 2003 int 2004 response(void) 2005 { 2006 char ch, *cp, resp, rbuf[2048], visbuf[2048]; 2007 2008 if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) 2009 lostconn(0); 2010 2011 cp = rbuf; 2012 switch (resp) { 2013 case 0: /* ok */ 2014 return (0); 2015 default: 2016 *cp++ = resp; 2017 /* FALLTHROUGH */ 2018 case 1: /* error, followed by error msg */ 2019 case 2: /* fatal error, "" */ 2020 do { 2021 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 2022 lostconn(0); 2023 *cp++ = ch; 2024 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); 2025 2026 if (!iamremote) { 2027 cp[-1] = '\0'; 2028 (void) snmprintf(visbuf, sizeof(visbuf), 2029 NULL, "%s\n", rbuf); 2030 (void) atomicio(vwrite, STDERR_FILENO, 2031 visbuf, strlen(visbuf)); 2032 } 2033 ++errs; 2034 if (resp == 1) 2035 return (-1); 2036 exit(1); 2037 } 2038 /* NOTREACHED */ 2039 } 2040 2041 static void 2042 usage(void) 2043 { 2044 (void) fprintf(stderr, 2045 "usage: scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" 2046 " [-i identity_file] [-J destination] [-l limit] [-o ssh_option]\n" 2047 " [-P port] [-S program] [-X sftp_option] source ... target\n"); 2048 exit(1); 2049 } 2050 2051 void 2052 run_err(const char *fmt,...) 2053 { 2054 static FILE *fp; 2055 va_list ap; 2056 2057 ++errs; 2058 if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) { 2059 (void) fprintf(fp, "%c", 0x01); 2060 (void) fprintf(fp, "scp: "); 2061 va_start(ap, fmt); 2062 (void) vfprintf(fp, fmt, ap); 2063 va_end(ap); 2064 (void) fprintf(fp, "\n"); 2065 (void) fflush(fp); 2066 } 2067 2068 if (!iamremote) { 2069 va_start(ap, fmt); 2070 vfmprintf(stderr, fmt, ap); 2071 va_end(ap); 2072 fprintf(stderr, "\n"); 2073 } 2074 } 2075 2076 /* 2077 * Notes a sink error for sending at the end of a file transfer. Returns 0 if 2078 * no error has been noted or -1 otherwise. Use note_err(NULL) to flush 2079 * any active error at the end of the transfer. 2080 */ 2081 int 2082 note_err(const char *fmt, ...) 2083 { 2084 static char *emsg; 2085 va_list ap; 2086 2087 /* Replay any previously-noted error */ 2088 if (fmt == NULL) { 2089 if (emsg == NULL) 2090 return 0; 2091 run_err("%s", emsg); 2092 free(emsg); 2093 emsg = NULL; 2094 return -1; 2095 } 2096 2097 errs++; 2098 /* Prefer first-noted error */ 2099 if (emsg != NULL) 2100 return -1; 2101 2102 va_start(ap, fmt); 2103 vasnmprintf(&emsg, INT_MAX, NULL, fmt, ap); 2104 va_end(ap); 2105 return -1; 2106 } 2107 2108 void 2109 verifydir(char *cp) 2110 { 2111 struct stat stb; 2112 2113 if (!stat(cp, &stb)) { 2114 if (S_ISDIR(stb.st_mode)) 2115 return; 2116 errno = ENOTDIR; 2117 } 2118 run_err("%s: %s", cp, strerror(errno)); 2119 killchild(0); 2120 } 2121 2122 int 2123 okname(char *cp0) 2124 { 2125 int c; 2126 char *cp; 2127 2128 cp = cp0; 2129 do { 2130 c = (int)*cp; 2131 if (c & 0200) 2132 goto bad; 2133 if (!isalpha(c) && !isdigit((unsigned char)c)) { 2134 switch (c) { 2135 case '\'': 2136 case '"': 2137 case '`': 2138 case ' ': 2139 case '#': 2140 goto bad; 2141 default: 2142 break; 2143 } 2144 } 2145 } while (*++cp); 2146 return (1); 2147 2148 bad: fmprintf(stderr, "%s: invalid user name\n", cp0); 2149 return (0); 2150 } 2151 2152 BUF * 2153 allocbuf(BUF *bp, int fd, int blksize) 2154 { 2155 size_t size; 2156 struct stat stb; 2157 2158 if (fstat(fd, &stb) == -1) { 2159 run_err("fstat: %s", strerror(errno)); 2160 return (0); 2161 } 2162 size = ROUNDUP(stb.st_blksize, blksize); 2163 if (size == 0) 2164 size = blksize; 2165 if (bp->cnt >= size) 2166 return (bp); 2167 bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1); 2168 bp->cnt = size; 2169 return (bp); 2170 } 2171 2172 static void 2173 lostconn(int signo) 2174 { 2175 if (!iamremote) 2176 (void)write(STDERR_FILENO, "lost connection\n", 16); 2177 if (signo) 2178 _exit(1); 2179 else 2180 exit(1); 2181 } 2182 2183 void 2184 cleanup_exit(int i) 2185 { 2186 if (remin > 0) 2187 close(remin); 2188 if (remout > 0) 2189 close(remout); 2190 if (remin2 > 0) 2191 close(remin2); 2192 if (remout2 > 0) 2193 close(remout2); 2194 if (do_cmd_pid > 0) 2195 waitpid(do_cmd_pid, NULL, 0); 2196 if (do_cmd_pid2 > 0) 2197 waitpid(do_cmd_pid2, NULL, 0); 2198 exit(i); 2199 } 2200