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