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