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