1a2eb7b567692e7a3f435b1ee8ed26c63d395d5eaGreg Hartman/* $OpenBSD: scp.c,v 1.182 2015/04/24 01:36:00 deraadt Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * scp - secure remote copy. This is basically patched BSD rcp which 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * uses ssh to do the data transfer (instead of using rcmd). 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOTE: This version should NOT be suid root. (This uses ssh to 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * do the transfer and ssh has the necessary privileges.) 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi> 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * As far as I am concerned, the code I have written for this software 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * can be used freely for any purpose. Any derived versions of this 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * software must be clearly marked as such, and if the derived work is 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * incompatible with the protocol description in the RFC file, it must be 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * called by a name other than "ssh" or "Secure Shell". 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1999 Theo de Raadt. All rights reserved. 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1999 Aaron Campbell. All rights reserved. 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met: 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer. 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer in the 28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * documentation and/or other materials provided with the distribution. 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Parts from: 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1983, 1990, 1992, 1993, 1995 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * The Regents of the University of California. All rights reserved. 47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without 49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions 50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met: 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer. 53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright 54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer in the 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * documentation and/or other materials provided with the distribution. 56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 3. Neither the name of the University nor the names of its contributors 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * may be used to endorse or promote products derived from this software 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * without specific prior written permission. 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * SUCH DAMAGE. 71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h> 77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/param.h> 78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_SYS_STAT_H 79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <sys/stat.h> 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_POLL_H 82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <poll.h> 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else 84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# ifdef HAVE_SYS_POLL_H 85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <sys/poll.h> 86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# endif 87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_SYS_TIME_H 89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <sys/time.h> 90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/wait.h> 92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/uio.h> 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <ctype.h> 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <dirent.h> 96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <errno.h> 97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <fcntl.h> 98d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <limits.h> 99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <pwd.h> 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <signal.h> 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdio.h> 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdlib.h> 104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <time.h> 106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h> 107d059297112922cabb0c674840589be8db821fd9aAdam Langley#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <vis.h> 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "xmalloc.h" 112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "atomicio.h" 113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "pathnames.h" 114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h" 115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "misc.h" 116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "progressmeter.h" 117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanextern char *__progname; 119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define COPY_BUFLEN 16384 121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); 123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout); 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Struct for addargs */ 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanarglist args; 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanarglist remote_remote_args; 128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Bandwidth limit */ 130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanlong long limit_kbps = 0; 131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstruct bwlimit bwlimit; 132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Name of current file being transferred. */ 134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar *curfile; 135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* This is set to non-zero to enable verbose mode. */ 137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint verbose_mode = 0; 138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* This is set to zero if the progressmeter is not desired. */ 140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint showprogress = 1; 141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This is set to non-zero if remote-remote copy should be piped 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * through this process. 145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint throughlocal = 0; 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* This is the program to execute for the secured connection. ("ssh" or -S) */ 149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar *ssh_program = _PATH_SSH_PROGRAM; 150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* This is used to store the pid of ssh_program */ 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanpid_t do_cmd_pid = -1; 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmankillchild(int signo) 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd_pid > 1) { 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman kill(do_cmd_pid, signo ? signo : SIGTERM); 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman waitpid(do_cmd_pid, NULL, 0); 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (signo) 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman _exit(1); 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansuspchild(int signo) 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int status; 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd_pid > 1) { 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman kill(do_cmd_pid, signo); 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 && 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno == EINTR) 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ; 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman kill(getpid(), SIGSTOP); 178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int 182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmando_local_cmd(arglist *a) 183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int i; 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int status; 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pid_t pid; 187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (a->num == 0) 189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("do_local_cmd: no arguments"); 190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (verbose_mode) { 192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "Executing:"); 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < a->num; i++) 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, " %s", a->list[i]); 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "\n"); 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((pid = fork()) == -1) 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("do_local_cmd: fork: %s", strerror(errno)); 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pid == 0) { 201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman execvp(a->list[0], a->list); 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror(a->list[0]); 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do_cmd_pid = pid; 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGTERM, killchild); 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGINT, killchild); 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGHUP, killchild); 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (waitpid(pid, &status, 0) == -1) 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errno != EINTR) 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("do_local_cmd: waitpid: %s", strerror(errno)); 214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do_cmd_pid = -1; 216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This function executes the given command as the specified user on the 225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * assigns the input and output file descriptors on success. 227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmando_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) 231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int pin[2], pout[2], reserved[2]; 233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (verbose_mode) 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, 236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "Executing: program %s host %s, user %s, command %s\n", 237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ssh_program, host, 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remuser ? remuser : "(unspecified)", cmd); 239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Reserve two descriptors so that the real pipes won't get 242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * descriptors 0 and 1 because that will screw up dup2 below. 243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pipe(reserved) < 0) 245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("pipe: %s", strerror(errno)); 246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Create a socket pair for communicating with ssh. */ 248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pipe(pin) < 0) 249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("pipe: %s", strerror(errno)); 250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pipe(pout) < 0) 251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("pipe: %s", strerror(errno)); 252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Free the reserved descriptors. */ 254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(reserved[0]); 255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(reserved[1]); 256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGTSTP, suspchild); 258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGTTIN, suspchild); 259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGTTOU, suspchild); 260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Fork a child to execute the command on the remote host using ssh. */ 262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do_cmd_pid = fork(); 263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd_pid == 0) { 264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Child. */ 265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(pin[1]); 266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(pout[0]); 267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dup2(pin[0], 0); 268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dup2(pout[1], 1); 269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(pin[0]); 270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(pout[1]); 271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman replacearg(&args, 0, "%s", ssh_program); 273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (remuser != NULL) { 274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-l"); 275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", remuser); 276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "--"); 278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", host); 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", cmd); 280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman execvp(ssh_program, args.list); 282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror(ssh_program); 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (do_cmd_pid == -1) { 285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("fork: %s", strerror(errno)); 286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Parent. Close the other side, and return the local side. */ 288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(pin[0]); 289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *fdout = pin[1]; 290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(pout[1]); 291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *fdin = pout[0]; 292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGTERM, killchild); 293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGINT, killchild); 294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGHUP, killchild); 295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This functions executes a command simlar to do_cmd(), but expects the 300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * input and output descriptors to be setup by a previous call to do_cmd(). 301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This way the input and output of two commands can be connected. 302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmando_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout) 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pid_t pid; 307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int status; 308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (verbose_mode) 310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, 311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "Executing: 2nd program %s host %s, user %s, command %s\n", 312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ssh_program, host, 313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remuser ? remuser : "(unspecified)", cmd); 314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Fork a child to execute the command on the remote host using ssh. */ 316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pid = fork(); 317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pid == 0) { 318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dup2(fdin, 0); 319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman dup2(fdout, 1); 320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman replacearg(&args, 0, "%s", ssh_program); 322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (remuser != NULL) { 323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-l"); 324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", remuser); 325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "--"); 327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", host); 328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", cmd); 329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman execvp(ssh_program, args.list); 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror(ssh_program); 332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (pid == -1) { 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("fork: %s", strerror(errno)); 335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (waitpid(pid, &status, 0) == -1) 337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errno != EINTR) 338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("do_cmd2: waitpid: %s", strerror(errno)); 339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantypedef struct { 343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size_t cnt; 344bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *buf; 345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} BUF; 346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanBUF *allocbuf(BUF *, int, int); 348bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid lostconn(int); 349bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint okname(char *); 350bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid run_err(const char *,...); 351bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid verifydir(char *); 352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 353bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstruct passwd *pwd; 354bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanuid_t userid; 355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint errs, remin, remout; 356bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint pflag, iamremote, iamrecursive, targetshouldbedirectory; 357bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 358bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define CMDNEEDS 64 359bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ 360bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 361bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint response(void); 362bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid rsource(char *, struct stat *); 363bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid sink(int, char *[]); 364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid source(int, char *[]); 365bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid tolocal(int, char *[]); 366bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid toremote(char *, int, char *[]); 367bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid usage(void); 368bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 369bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 370bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanmain(int argc, char **argv) 371bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 372bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int ch, fflag, tflag, status, n; 373bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *targ, **newargv; 374bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *errstr; 375bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman extern char *optarg; 376bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman extern int optind; 377bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 378bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 379bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sanitise_stdfd(); 380bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 381bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Copy argv, because we modify it */ 382bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv)); 383bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (n = 0; n < argc; n++) 384bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman newargv[n] = xstrdup(argv[n]); 385bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman argv = newargv; 386bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 387bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman __progname = ssh_get_progname(argv[0]); 388bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 389bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(&args, '\0', sizeof(args)); 390bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); 391bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman args.list = remote_remote_args.list = NULL; 392bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", ssh_program); 393bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-x"); 394bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-oForwardAgent=no"); 395bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-oPermitLocalCommand=no"); 396bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-oClearAllForwardings=yes"); 397bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 398bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fflag = tflag = 0; 399bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) 400bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (ch) { 401bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* User-visible flags. */ 402bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '1': 403bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '2': 404bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '4': 405bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '6': 406bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'C': 407bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-%c", ch); 408bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "-%c", ch); 409bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 410bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '3': 411bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman throughlocal = 1; 412bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 413bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'o': 414bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'c': 415bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'i': 416bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'F': 417bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "-%c", ch); 418bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "%s", optarg); 419bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-%c", ch); 420bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", optarg); 421bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 422bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'P': 423bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "-p"); 424bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "%s", optarg); 425bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-p"); 426bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "%s", optarg); 427bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 428bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'B': 429bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "-oBatchmode=yes"); 430bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-oBatchmode=yes"); 431bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 432bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'l': 433bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, 434bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman &errstr); 435bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errstr != NULL) 436bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 437bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman limit_kbps *= 1024; /* kbps */ 438bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); 439bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 440bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'p': 441bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pflag = 1; 442bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 443bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'r': 444bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman iamrecursive = 1; 445bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 446bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'S': 447bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ssh_program = xstrdup(optarg); 448bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 449bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'v': 450bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-v"); 451bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "-v"); 452bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman verbose_mode = 1; 453bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 454bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'q': 455bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&args, "-q"); 456bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&remote_remote_args, "-q"); 457bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman showprogress = 0; 458bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 459bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 460bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Server options. */ 461bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'd': 462bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman targetshouldbedirectory = 1; 463bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 464bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'f': /* "from" */ 465bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman iamremote = 1; 466bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fflag = 1; 467bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 468bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 't': /* "to" */ 469bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman iamremote = 1; 470bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tflag = 1; 471bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_CYGWIN 472bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setmode(0, O_BINARY); 473bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 474bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 475bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 476bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 477bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 478bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman argc -= optind; 479bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman argv += optind; 480bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 481bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((pwd = getpwuid(userid = getuid())) == NULL) 482bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("unknown user %u", (u_int) userid); 483bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 484bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!isatty(STDOUT_FILENO)) 485bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman showprogress = 0; 486bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 487bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remin = STDIN_FILENO; 488bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remout = STDOUT_FILENO; 489bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 490bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fflag) { 491bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Follow "protocol", send data. */ 492bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) response(); 493bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman source(argc, argv); 494bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(errs != 0); 495bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 496bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (tflag) { 497bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Receive data. */ 498bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sink(argc, argv); 499bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(errs != 0); 500bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 501bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (argc < 2) 502bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 503bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (argc > 2) 504bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman targetshouldbedirectory = 1; 505bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 506bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remin = remout = -1; 507bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do_cmd_pid = -1; 508bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Command to be executed on remote system using "ssh". */ 509bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", 510bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman verbose_mode ? " -v" : "", 511bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman iamrecursive ? " -r" : "", pflag ? " -p" : "", 512bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman targetshouldbedirectory ? " -d" : ""); 513bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 514bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) signal(SIGPIPE, lostconn); 515bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 516bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ 517bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman toremote(targ, argc, argv); 518bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else { 519bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (targetshouldbedirectory) 520bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman verifydir(argv[argc - 1]); 521bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tolocal(argc, argv); /* Dest is local host. */ 522bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 523bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 524bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Finally check the exit status of the ssh process, if one was forked 525bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * and no error has occurred yet 526bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 527bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd_pid != -1 && errs == 0) { 528bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (remin != -1) 529bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) close(remin); 530bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (remout != -1) 531bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) close(remout); 532bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (waitpid(do_cmd_pid, &status, 0) == -1) 533bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errs = 1; 534bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else { 535bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 536bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errs = 1; 537bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 538bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 539bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(errs != 0); 540bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 541bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 542bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Callback from atomicio6 to update progress meter and limit bandwidth */ 543bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int 544bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanscpio(void *_cnt, size_t s) 545bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 546bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman off_t *cnt = (off_t *)_cnt; 547bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 548bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cnt += s; 549bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (limit_kbps > 0) 550bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bandwidth_limit(&bwlimit, s); 551bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 552bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 553bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 554d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int 555d059297112922cabb0c674840589be8db821fd9aAdam Langleydo_times(int fd, int verb, const struct stat *sb) 556d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 557d059297112922cabb0c674840589be8db821fd9aAdam Langley /* strlen(2^64) == 20; strlen(10^6) == 7 */ 558d059297112922cabb0c674840589be8db821fd9aAdam Langley char buf[(20 + 7 + 2) * 2 + 2]; 559d059297112922cabb0c674840589be8db821fd9aAdam Langley 560d059297112922cabb0c674840589be8db821fd9aAdam Langley (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n", 561d059297112922cabb0c674840589be8db821fd9aAdam Langley (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime), 562d059297112922cabb0c674840589be8db821fd9aAdam Langley (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime)); 563d059297112922cabb0c674840589be8db821fd9aAdam Langley if (verb) { 564d059297112922cabb0c674840589be8db821fd9aAdam Langley fprintf(stderr, "File mtime %lld atime %lld\n", 565d059297112922cabb0c674840589be8db821fd9aAdam Langley (long long)sb->st_mtime, (long long)sb->st_atime); 566d059297112922cabb0c674840589be8db821fd9aAdam Langley fprintf(stderr, "Sending file timestamps: %s", buf); 567d059297112922cabb0c674840589be8db821fd9aAdam Langley } 568d059297112922cabb0c674840589be8db821fd9aAdam Langley (void) atomicio(vwrite, fd, buf, strlen(buf)); 569d059297112922cabb0c674840589be8db821fd9aAdam Langley return (response()); 570d059297112922cabb0c674840589be8db821fd9aAdam Langley} 571d059297112922cabb0c674840589be8db821fd9aAdam Langley 572bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 573bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantoremote(char *targ, int argc, char **argv) 574bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 575bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *bp, *host, *src, *suser, *thost, *tuser, *arg; 576bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman arglist alist; 577bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int i; 578bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int j; 579bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 580bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(&alist, '\0', sizeof(alist)); 581bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman alist.list = NULL; 582bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 583bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *targ++ = 0; 584bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*targ == 0) 585bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman targ = "."; 586bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 587bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman arg = xstrdup(argv[argc - 1]); 588bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((thost = strrchr(arg, '@'))) { 589bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* user@host */ 590bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *thost++ = 0; 591bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tuser = arg; 592bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*tuser == '\0') 593bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tuser = NULL; 594bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 595bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman thost = arg; 596bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tuser = NULL; 597bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 598bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 599bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (tuser != NULL && !okname(tuser)) { 600d059297112922cabb0c674840589be8db821fd9aAdam Langley free(arg); 601bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 602bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 603bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 604bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < argc - 1; i++) { 605bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman src = colon(argv[i]); 606bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (src && throughlocal) { /* extended remote to remote */ 607bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *src++ = 0; 608bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*src == 0) 609bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman src = "."; 610bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = strrchr(argv[i], '@'); 611bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (host) { 612bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *host++ = 0; 613bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = cleanhostname(host); 614bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = argv[i]; 615bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*suser == '\0') 616bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = pwd->pw_name; 617bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else if (!okname(suser)) 618bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 619bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 620bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = cleanhostname(argv[i]); 621bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = NULL; 622bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 623d059297112922cabb0c674840589be8db821fd9aAdam Langley xasprintf(&bp, "%s -f %s%s", cmd, 624d059297112922cabb0c674840589be8db821fd9aAdam Langley *src == '-' ? "-- " : "", src); 625bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd(host, suser, bp, &remin, &remout) < 0) 626bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 627d059297112922cabb0c674840589be8db821fd9aAdam Langley free(bp); 628bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = cleanhostname(thost); 629d059297112922cabb0c674840589be8db821fd9aAdam Langley xasprintf(&bp, "%s -t %s%s", cmd, 630d059297112922cabb0c674840589be8db821fd9aAdam Langley *targ == '-' ? "-- " : "", targ); 631bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd2(host, tuser, bp, remin, remout) < 0) 632bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 633d059297112922cabb0c674840589be8db821fd9aAdam Langley free(bp); 634bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) close(remin); 635bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) close(remout); 636bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remin = remout = -1; 637bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (src) { /* standard remote to remote */ 638bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman freeargs(&alist); 639bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", ssh_program); 640bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "-x"); 641bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "-oClearAllForwardings=yes"); 642bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "-n"); 643bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (j = 0; j < remote_remote_args.num; j++) { 644bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", 645bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remote_remote_args.list[j]); 646bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 647bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *src++ = 0; 648bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*src == 0) 649bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman src = "."; 650bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = strrchr(argv[i], '@'); 651bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 652bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (host) { 653bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *host++ = 0; 654bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = cleanhostname(host); 655bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = argv[i]; 656bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*suser == '\0') 657bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = pwd->pw_name; 658bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else if (!okname(suser)) 659bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 660bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "-l"); 661bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", suser); 662bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 663bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = cleanhostname(argv[i]); 664bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 665bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "--"); 666bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", host); 667bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", cmd); 668bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", src); 669bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s%s%s:%s", 670bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tuser ? tuser : "", tuser ? "@" : "", 671bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman thost, targ); 672bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_local_cmd(&alist) != 0) 673bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errs = 1; 674bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { /* local to remote */ 675bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (remin == -1) { 676d059297112922cabb0c674840589be8db821fd9aAdam Langley xasprintf(&bp, "%s -t %s%s", cmd, 677d059297112922cabb0c674840589be8db821fd9aAdam Langley *targ == '-' ? "-- " : "", targ); 678bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = cleanhostname(thost); 679bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd(host, tuser, bp, &remin, 680bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman &remout) < 0) 681bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 682bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (response() < 0) 683bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 684d059297112922cabb0c674840589be8db821fd9aAdam Langley free(bp); 685bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 686bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman source(1, argv + i); 687bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 688bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 689d059297112922cabb0c674840589be8db821fd9aAdam Langley free(arg); 690bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 691bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 692bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 693bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantolocal(int argc, char **argv) 694bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 695bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *bp, *host, *src, *suser; 696bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman arglist alist; 697bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int i; 698bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 699bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(&alist, '\0', sizeof(alist)); 700bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman alist.list = NULL; 701bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 702bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < argc - 1; i++) { 703bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!(src = colon(argv[i]))) { /* Local to local. */ 704bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman freeargs(&alist); 705bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", _PATH_CP); 706bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (iamrecursive) 707bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "-r"); 708bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pflag) 709bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "-p"); 710bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "--"); 711bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", argv[i]); 712bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman addargs(&alist, "%s", argv[argc-1]); 713bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_local_cmd(&alist)) 714bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ++errs; 715bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 716bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 717bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *src++ = 0; 718bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*src == 0) 719bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman src = "."; 720bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((host = strrchr(argv[i], '@')) == NULL) { 721bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = argv[i]; 722bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = NULL; 723bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 724bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *host++ = 0; 725bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = argv[i]; 726bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*suser == '\0') 727bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman suser = pwd->pw_name; 728bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 729bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman host = cleanhostname(host); 730d059297112922cabb0c674840589be8db821fd9aAdam Langley xasprintf(&bp, "%s -f %s%s", 731d059297112922cabb0c674840589be8db821fd9aAdam Langley cmd, *src == '-' ? "-- " : "", src); 732bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (do_cmd(host, suser, bp, &remin, &remout) < 0) { 733d059297112922cabb0c674840589be8db821fd9aAdam Langley free(bp); 734bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ++errs; 735bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 736bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 737d059297112922cabb0c674840589be8db821fd9aAdam Langley free(bp); 738bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sink(1, argv + argc - 1); 739bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) close(remin); 740bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman remin = remout = -1; 741bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 742bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 743bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 744bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 745bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansource(int argc, char **argv) 746bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 747bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct stat stb; 748bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static BUF buffer; 749bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BUF *bp; 750bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman off_t i, statbytes; 751d059297112922cabb0c674840589be8db821fd9aAdam Langley size_t amt, nr; 752bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int fd = -1, haderr, indx; 753d059297112922cabb0c674840589be8db821fd9aAdam Langley char *last, *name, buf[2048], encname[PATH_MAX]; 754bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int len; 755bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 756bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (indx = 0; indx < argc; ++indx) { 757bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman name = argv[indx]; 758bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman statbytes = 0; 759bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = strlen(name); 760bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (len > 1 && name[len-1] == '/') 761bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman name[--len] = '\0'; 762bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0) 763bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto syserr; 764bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strchr(name, '\n') != NULL) { 765bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strnvis(encname, name, sizeof(encname), VIS_NL); 766bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman name = encname; 767bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 768bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fstat(fd, &stb) < 0) { 769bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansyserr: run_err("%s: %s", name, strerror(errno)); 770bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto next; 771bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 772bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (stb.st_size < 0) { 773bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: %s", name, "Negative file size"); 774bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto next; 775bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 776bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman unset_nonblock(fd); 777bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (stb.st_mode & S_IFMT) { 778bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case S_IFREG: 779bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 780bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case S_IFDIR: 781bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (iamrecursive) { 782bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rsource(name, &stb); 783bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto next; 784bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 785bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* FALLTHROUGH */ 786bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 787bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: not a regular file", name); 788bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto next; 789bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 790bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((last = strrchr(name, '/')) == NULL) 791bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman last = name; 792bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 793bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ++last; 794bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman curfile = last; 795bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pflag) { 796d059297112922cabb0c674840589be8db821fd9aAdam Langley if (do_times(remout, verbose_mode, &stb) < 0) 797bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto next; 798bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 799bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 800bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(buf, sizeof buf, "C%04o %lld %s\n", 801bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (u_int) (stb.st_mode & FILEMODEMASK), 802bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (long long)stb.st_size, last); 803bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (verbose_mode) { 804bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "Sending file modes: %s", buf); 805bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 806bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, buf, strlen(buf)); 807bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (response() < 0) 808bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto next; 809bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) { 810bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmannext: if (fd != -1) { 811bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) close(fd); 812bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd = -1; 813bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 814bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 815bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 816bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (showprogress) 817bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman start_progress_meter(curfile, stb.st_size, &statbytes); 818bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman set_nonblock(remout); 819bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 820bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman amt = bp->cnt; 821bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (i + (off_t)amt > stb.st_size) 822bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman amt = stb.st_size - i; 823bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!haderr) { 824d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((nr = atomicio(read, fd, 825d059297112922cabb0c674840589be8db821fd9aAdam Langley bp->buf, amt)) != amt) { 826bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman haderr = errno; 827d059297112922cabb0c674840589be8db821fd9aAdam Langley memset(bp->buf + nr, 0, amt - nr); 828d059297112922cabb0c674840589be8db821fd9aAdam Langley } 829bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 830bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Keep writing after error to retain sync */ 831bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (haderr) { 832bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)atomicio(vwrite, remout, bp->buf, amt); 833d059297112922cabb0c674840589be8db821fd9aAdam Langley memset(bp->buf, 0, amt); 834bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 835bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 836bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (atomicio6(vwrite, remout, bp->buf, amt, scpio, 837bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman &statbytes) != amt) 838bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman haderr = errno; 839bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 840bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman unset_nonblock(remout); 841bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (showprogress) 842bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman stop_progress_meter(); 843bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 844bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fd != -1) { 845bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (close(fd) < 0 && !haderr) 846bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman haderr = errno; 847bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd = -1; 848bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 849bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!haderr) 850bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, "", 1); 851bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 852bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: %s", name, strerror(haderr)); 853bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) response(); 854bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 855bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 856bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 857bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 858bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanrsource(char *name, struct stat *statp) 859bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 860bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman DIR *dirp; 861bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct dirent *dp; 862d059297112922cabb0c674840589be8db821fd9aAdam Langley char *last, *vect[1], path[PATH_MAX]; 863bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 864bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!(dirp = opendir(name))) { 865bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: %s", name, strerror(errno)); 866bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 867bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 868bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman last = strrchr(name, '/'); 869bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (last == 0) 870bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman last = name; 871bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 872bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman last++; 873bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pflag) { 874d059297112922cabb0c674840589be8db821fd9aAdam Langley if (do_times(remout, verbose_mode, statp) < 0) { 875bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman closedir(dirp); 876bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 877bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 878bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 879bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", 880bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (u_int) (statp->st_mode & FILEMODEMASK), 0, last); 881bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (verbose_mode) 882bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "Entering directory: %s", path); 883bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, path, strlen(path)); 884bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (response() < 0) { 885bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman closedir(dirp); 886bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 887bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 888bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while ((dp = readdir(dirp)) != NULL) { 889bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (dp->d_ino == 0) 890bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 891bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 892bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 893bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) { 894bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s/%s: name too long", name, dp->d_name); 895bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 896bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 897bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name); 898bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman vect[0] = path; 899bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman source(1, vect); 900bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 901bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) closedir(dirp); 902bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, "E\n", 2); 903bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) response(); 904bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 905bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 906bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 907bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansink(int argc, char **argv) 908bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 909bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static BUF buffer; 910bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct stat stb; 911bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman enum { 912bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman YES, NO, DISPLAYED 913bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } wrerr; 914bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BUF *bp; 915bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman off_t i; 916bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size_t j, count; 917bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int amt, exists, first, ofd; 918bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mode_t mode, omode, mask; 919bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman off_t size, statbytes; 920d059297112922cabb0c674840589be8db821fd9aAdam Langley unsigned long long ull; 921bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int setimes, targisdir, wrerrno = 0; 922bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; 923bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct timeval tv[2]; 924bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 925bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define atime tv[0] 926bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define mtime tv[1] 927bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define SCREWUP(str) { why = str; goto screwup; } 928bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 929bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setimes = targisdir = 0; 930bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mask = umask(0); 931bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!pflag) 932bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) umask(mask); 933bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (argc != 1) { 934bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("ambiguous target"); 935bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 936bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 937bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman targ = *argv; 938bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (targetshouldbedirectory) 939bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman verifydir(targ); 940bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 941bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, "", 1); 942bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 943bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman targisdir = 1; 944bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (first = 1;; first = 0) { 945bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = buf; 946bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (atomicio(read, remin, cp, 1) != 1) 947bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 948bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp++ == '\n') 949bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("unexpected <newline>"); 950bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do { 951bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 952bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("lost connection"); 953bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp++ = ch; 954bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); 955bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp = 0; 956bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (verbose_mode) 957bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "Sink: %s", buf); 958bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 959bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[0] == '\01' || buf[0] == '\02') { 960bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (iamremote == 0) 961bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, STDERR_FILENO, 962bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buf + 1, strlen(buf + 1)); 963bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[0] == '\02') 964bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 965bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ++errs; 966bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 967bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 968bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[0] == 'E') { 969bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, "", 1); 970bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 971bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 972bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ch == '\n') 973bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *--cp = 0; 974bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 975bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = buf; 976bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp == 'T') { 977bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setimes++; 978bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp++; 979d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!isdigit((unsigned char)*cp)) 980d059297112922cabb0c674840589be8db821fd9aAdam Langley SCREWUP("mtime.sec not present"); 981d059297112922cabb0c674840589be8db821fd9aAdam Langley ull = strtoull(cp, &cp, 10); 982bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!cp || *cp++ != ' ') 983bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("mtime.sec not delimited"); 984d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((time_t)ull < 0 || 985d059297112922cabb0c674840589be8db821fd9aAdam Langley (unsigned long long)(time_t)ull != ull) 986d059297112922cabb0c674840589be8db821fd9aAdam Langley setimes = 0; /* out of range */ 987d059297112922cabb0c674840589be8db821fd9aAdam Langley mtime.tv_sec = ull; 988bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mtime.tv_usec = strtol(cp, &cp, 10); 989d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 || 990d059297112922cabb0c674840589be8db821fd9aAdam Langley mtime.tv_usec > 999999) 991bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("mtime.usec not delimited"); 992d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!isdigit((unsigned char)*cp)) 993d059297112922cabb0c674840589be8db821fd9aAdam Langley SCREWUP("atime.sec not present"); 994d059297112922cabb0c674840589be8db821fd9aAdam Langley ull = strtoull(cp, &cp, 10); 995bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!cp || *cp++ != ' ') 996bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("atime.sec not delimited"); 997d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((time_t)ull < 0 || 998d059297112922cabb0c674840589be8db821fd9aAdam Langley (unsigned long long)(time_t)ull != ull) 999d059297112922cabb0c674840589be8db821fd9aAdam Langley setimes = 0; /* out of range */ 1000d059297112922cabb0c674840589be8db821fd9aAdam Langley atime.tv_sec = ull; 1001bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman atime.tv_usec = strtol(cp, &cp, 10); 1002d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || 1003d059297112922cabb0c674840589be8db821fd9aAdam Langley atime.tv_usec > 999999) 1004bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("atime.usec not delimited"); 1005bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, "", 1); 1006bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 1007bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1008bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp != 'C' && *cp != 'D') { 1009bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 1010bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Check for the case "rcp remote:foo\* local:bar". 1011bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * In this case, the line "No match." can be returned 1012bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * by the shell before the rcp command on the remote is 1013bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * executed so the ^Aerror_message convention isn't 1014bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * followed. 1015bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 1016bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (first) { 1017bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s", cp); 1018bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1019bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1020bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("expected control record"); 1021bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1022bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mode = 0; 1023bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (++cp; cp < buf + 5; cp++) { 1024bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp < '0' || *cp > '7') 1025bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("bad mode"); 1026bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mode = (mode << 3) | (*cp - '0'); 1027bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1028bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp++ != ' ') 1029bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("mode not delimited"); 1030bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1031d059297112922cabb0c674840589be8db821fd9aAdam Langley for (size = 0; isdigit((unsigned char)*cp);) 1032bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size = size * 10 + (*cp++ - '0'); 1033bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*cp++ != ' ') 1034bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("size not delimited"); 1035bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) { 1036bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("error: unexpected filename: %s", cp); 1037bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1038bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1039bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (targisdir) { 1040bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static char *namebuf; 1041bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static size_t cursize; 1042bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size_t need; 1043bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1044bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman need = strlen(targ) + strlen(cp) + 250; 1045bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (need > cursize) { 1046d059297112922cabb0c674840589be8db821fd9aAdam Langley free(namebuf); 1047bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman namebuf = xmalloc(need); 1048bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cursize = need; 1049bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1050bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) snprintf(namebuf, need, "%s%s%s", targ, 1051bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strcmp(targ, "/") ? "/" : "", cp); 1052bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman np = namebuf; 1053bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else 1054bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman np = targ; 1055bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman curfile = cp; 1056bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exists = stat(np, &stb) == 0; 1057bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf[0] == 'D') { 1058bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int mod_flag = pflag; 1059bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!iamrecursive) 1060bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SCREWUP("received directory without -r"); 1061bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (exists) { 1062bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!S_ISDIR(stb.st_mode)) { 1063bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno = ENOTDIR; 1064bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto bad; 1065bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1066bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pflag) 1067bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) chmod(np, mode); 1068bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 1069bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Handle copying from a read-only 1070bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman directory */ 1071bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mod_flag = 1; 1072bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (mkdir(np, mode | S_IRWXU) < 0) 1073bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto bad; 1074bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1075bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman vect[0] = xstrdup(np); 1076bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sink(1, vect); 1077bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setimes) { 1078bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setimes = 0; 1079bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (utimes(vect[0], tv) < 0) 1080bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: set times: %s", 1081bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman vect[0], strerror(errno)); 1082bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1083bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (mod_flag) 1084bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) chmod(vect[0], mode); 1085d059297112922cabb0c674840589be8db821fd9aAdam Langley free(vect[0]); 1086bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 1087bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1088bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman omode = mode; 1089bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mode |= S_IWUSR; 1090bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { 1091bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanbad: run_err("%s: %s", np, strerror(errno)); 1092bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 1093bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1094bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, "", 1); 1095bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { 1096bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) close(ofd); 1097bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 1098bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1099bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = bp->buf; 1100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = NO; 1101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman statbytes = 0; 1103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (showprogress) 1104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman start_progress_meter(curfile, size, &statbytes); 1105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman set_nonblock(remin); 1106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (count = i = 0; i < size; i += bp->cnt) { 1107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman amt = bp->cnt; 1108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (i + amt > size) 1109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman amt = size - i; 1110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman count += amt; 1111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do { 1112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman j = atomicio6(read, remin, cp, amt, 1113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman scpio, &statbytes); 1114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (j == 0) { 1115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s", j != EPIPE ? 1116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strerror(errno) : 1117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "dropped connection"); 1118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman amt -= j; 1121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp += j; 1122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } while (amt > 0); 1123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (count == bp->cnt) { 1125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Keep reading so we stay sync'd up. */ 1126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (wrerr == NO) { 1127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (atomicio(vwrite, ofd, bp->buf, 1128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman count) != count) { 1129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = YES; 1130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerrno = errno; 1131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman count = 0; 1134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = bp->buf; 1135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman unset_nonblock(remin); 1138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (showprogress) 1139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman stop_progress_meter(); 1140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (count != 0 && wrerr == NO && 1141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman atomicio(vwrite, ofd, bp->buf, count) != count) { 1142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = YES; 1143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerrno = errno; 1144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) && 1146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ftruncate(ofd, size) != 0) { 1147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: truncate: %s", np, strerror(errno)); 1148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = DISPLAYED; 1149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pflag) { 1151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (exists || omode != mode) 1152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_FCHMOD 1153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fchmod(ofd, omode)) { 1154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else /* HAVE_FCHMOD */ 1155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (chmod(np, omode)) { 1156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* HAVE_FCHMOD */ 1157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: set mode: %s", 1158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman np, strerror(errno)); 1159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = DISPLAYED; 1160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 1162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!exists && omode != mode) 1163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_FCHMOD 1164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fchmod(ofd, omode & ~mask)) { 1165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else /* HAVE_FCHMOD */ 1166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (chmod(np, omode & ~mask)) { 1167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* HAVE_FCHMOD */ 1168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: set mode: %s", 1169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman np, strerror(errno)); 1170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = DISPLAYED; 1171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (close(ofd) == -1) { 1174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = YES; 1175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerrno = errno; 1176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) response(); 1178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setimes && wrerr == NO) { 1179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setimes = 0; 1180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (utimes(np, tv) < 0) { 1181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: set times: %s", 1182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman np, strerror(errno)); 1183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wrerr = DISPLAYED; 1184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (wrerr) { 1187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case YES: 1188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: %s", np, strerror(wrerrno)); 1189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case NO: 1191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, remout, "", 1); 1192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case DISPLAYED: 1194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanscrewup: 1198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("protocol error: %s", why); 1199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 1203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanresponse(void) 1204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char ch, *cp, resp, rbuf[2048]; 1206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) 1208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman lostconn(0); 1209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = rbuf; 1211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (resp) { 1212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 0: /* ok */ 1213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 1214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 1215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp++ = resp; 1216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* FALLTHROUGH */ 1217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 1: /* error, followed by error msg */ 1218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 2: /* fatal error, "" */ 1219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do { 1220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 1221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman lostconn(0); 1222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *cp++ = ch; 1223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); 1224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!iamremote) 1226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf); 1227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ++errs; 1228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (resp == 1) 1229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (-1); 1230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* NOTREACHED */ 1233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanusage(void) 1237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) fprintf(stderr, 1239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" 1240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman " [-l limit] [-o ssh_option] [-P port] [-S program]\n" 1241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman " [[user@]host1:]file1 ... [[user@]host2:]file2\n"); 1242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanrun_err(const char *fmt,...) 1247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static FILE *fp; 1249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_list ap; 1250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ++errs; 1252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) { 1253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) fprintf(fp, "%c", 0x01); 1254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) fprintf(fp, "scp: "); 1255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, fmt); 1256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) vfprintf(fp, fmt, ap); 1257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 1258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) fprintf(fp, "\n"); 1259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) fflush(fp); 1260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!iamremote) { 1263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_start(ap, fmt); 1264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman vfprintf(stderr, fmt, ap); 1265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman va_end(ap); 1266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "\n"); 1267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanverifydir(char *cp) 1272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct stat stb; 1274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!stat(cp, &stb)) { 1276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (S_ISDIR(stb.st_mode)) 1277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 1278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno = ENOTDIR; 1279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("%s: %s", cp, strerror(errno)); 1281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman killchild(0); 1282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 1285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanokname(char *cp0) 1286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int c; 1288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *cp; 1289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = cp0; 1291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman do { 1292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman c = (int)*cp; 1293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (c & 0200) 1294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto bad; 1295d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!isalpha(c) && !isdigit((unsigned char)c)) { 1296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (c) { 1297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '\'': 1298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '"': 1299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '`': 1300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case ' ': 1301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case '#': 1302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto bad; 1303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 1304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } while (*++cp); 1308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (1); 1309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanbad: fprintf(stderr, "%s: invalid user name\n", cp0); 1311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 1312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanBUF * 1315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanallocbuf(BUF *bp, int fd, int blksize) 1316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size_t size; 1318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct stat stb; 1320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fstat(fd, &stb) < 0) { 1322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman run_err("fstat: %s", strerror(errno)); 1323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (0); 1324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size = roundup(stb.st_blksize, blksize); 1326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (size == 0) 1327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size = blksize; 1328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size = blksize; 1330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bp->cnt >= size) 1332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (bp); 1333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bp->buf == NULL) 1334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bp->buf = xmalloc(size); 1335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 1336a2eb7b567692e7a3f435b1ee8ed26c63d395d5eaGreg Hartman bp->buf = xreallocarray(bp->buf, 1, size); 1337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(bp->buf, 0, size); 1338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman bp->cnt = size; 1339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (bp); 1340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanlostconn(int signo) 1344bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!iamremote) 1346d059297112922cabb0c674840589be8db821fd9aAdam Langley (void)write(STDERR_FILENO, "lost connection\n", 16); 1347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (signo) 1348bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman _exit(1); 1349bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 1350bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1351bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1352