xref: /netbsd-src/crypto/external/bsd/openssh/dist/sftp.c (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
1 /*	$NetBSD: sftp.c,v 1.36 2022/10/05 22:39:36 christos Exp $	*/
2 /* $OpenBSD: sftp.c,v 1.222 2022/09/19 10:46:00 djm Exp $ */
3 
4 /*
5  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "includes.h"
21 __RCSID("$NetBSD: sftp.c,v 1.36 2022/10/05 22:39:36 christos Exp $");
22 
23 #include <sys/param.h>	/* MIN MAX */
24 #include <sys/types.h>
25 #include <sys/ioctl.h>
26 #include <sys/wait.h>
27 #include <sys/stat.h>
28 #include <sys/socket.h>
29 #include <sys/statvfs.h>
30 
31 #include <ctype.h>
32 #include <errno.h>
33 #include <glob.h>
34 #include <histedit.h>
35 #include <paths.h>
36 #include <libgen.h>
37 #include <locale.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <limits.h>
45 #include <util.h>
46 
47 #include "xmalloc.h"
48 #include "log.h"
49 #include "pathnames.h"
50 #include "misc.h"
51 #include "utf8.h"
52 
53 #include "sftp.h"
54 #include "ssherr.h"
55 #include "sshbuf.h"
56 #include "sftp-common.h"
57 #include "sftp-client.h"
58 #include "sftp-usergroup.h"
59 
60 #include "fmt_scaled.h"
61 
62 /* File to read commands from */
63 FILE* infile;
64 
65 /* Are we in batchfile mode? */
66 int batchmode = 0;
67 
68 /* PID of ssh transport process */
69 static volatile pid_t sshpid = -1;
70 
71 /* Suppress diagnostic messages */
72 int quiet = 0;
73 
74 /* This is set to 0 if the progressmeter is not desired. */
75 int showprogress = 1;
76 
77 /* When this option is set, we always recursively download/upload directories */
78 int global_rflag = 0;
79 
80 /* When this option is set, we resume download or upload if possible */
81 int global_aflag = 0;
82 
83 /* When this option is set, the file transfers will always preserve times */
84 int global_pflag = 0;
85 
86 /* When this option is set, transfers will have fsync() called on each file */
87 int global_fflag = 0;
88 
89 /* SIGINT received during command processing */
90 volatile sig_atomic_t interrupted = 0;
91 
92 /* I wish qsort() took a separate ctx for the comparison function...*/
93 int sort_flag;
94 glob_t *sort_glob;
95 
96 /* Context used for commandline completion */
97 struct complete_ctx {
98 	struct sftp_conn *conn;
99 	char **remote_pathp;
100 };
101 
102 int remote_glob(struct sftp_conn *, const char *, int,
103     int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
104 
105 /* Separators for interactive commands */
106 #define WHITESPACE " \t\r\n"
107 
108 /* ls flags */
109 #define LS_LONG_VIEW	0x0001	/* Full view ala ls -l */
110 #define LS_SHORT_VIEW	0x0002	/* Single row view ala ls -1 */
111 #define LS_NUMERIC_VIEW	0x0004	/* Long view with numeric uid/gid */
112 #define LS_NAME_SORT	0x0008	/* Sort by name (default) */
113 #define LS_TIME_SORT	0x0010	/* Sort by mtime */
114 #define LS_SIZE_SORT	0x0020	/* Sort by file size */
115 #define LS_REVERSE_SORT	0x0040	/* Reverse sort order */
116 #define LS_SHOW_ALL	0x0080	/* Don't skip filenames starting with '.' */
117 #define LS_SI_UNITS	0x0100	/* Display sizes as K, M, G, etc. */
118 
119 #define VIEW_FLAGS	(LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW|LS_SI_UNITS)
120 #define SORT_FLAGS	(LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT)
121 
122 /* Commands for interactive mode */
123 enum sftp_command {
124 	I_CHDIR = 1,
125 	I_CHGRP,
126 	I_CHMOD,
127 	I_CHOWN,
128 	I_COPY,
129 	I_DF,
130 	I_GET,
131 	I_HELP,
132 	I_LCHDIR,
133 	I_LINK,
134 	I_LLS,
135 	I_LMKDIR,
136 	I_LPWD,
137 	I_LS,
138 	I_LUMASK,
139 	I_MKDIR,
140 	I_PUT,
141 	I_PWD,
142 	I_QUIT,
143 	I_REGET,
144 	I_RENAME,
145 	I_REPUT,
146 	I_RM,
147 	I_RMDIR,
148 	I_SHELL,
149 	I_SYMLINK,
150 	I_VERSION,
151 	I_PROGRESS,
152 };
153 
154 struct CMD {
155 	const char *c;
156 	const int n;
157 	const int t;	/* Completion type for the first argument */
158 	const int t2;	/* completion type for the optional second argument */
159 };
160 
161 /* Type of completion */
162 #define NOARGS	0
163 #define REMOTE	1
164 #define LOCAL	2
165 
166 static const struct CMD cmds[] = {
167 	{ "bye",	I_QUIT,		NOARGS, 	NOARGS	},
168 	{ "cd",		I_CHDIR,	REMOTE, 	NOARGS	},
169 	{ "chdir",	I_CHDIR,	REMOTE, 	NOARGS	},
170 	{ "chgrp",	I_CHGRP,	REMOTE, 	NOARGS	},
171 	{ "chmod",	I_CHMOD,	REMOTE, 	NOARGS	},
172 	{ "chown",	I_CHOWN,	REMOTE, 	NOARGS	},
173 	{ "copy",	I_COPY,		REMOTE, 	LOCAL	},
174 	{ "cp",		I_COPY,		REMOTE, 	LOCAL	},
175 	{ "df",		I_DF,		REMOTE, 	NOARGS	},
176 	{ "dir",	I_LS,		REMOTE, 	NOARGS	},
177 	{ "exit",	I_QUIT,		NOARGS, 	NOARGS	},
178 	{ "get",	I_GET,		REMOTE, 	LOCAL	},
179 	{ "help",	I_HELP,		NOARGS, 	NOARGS	},
180 	{ "lcd",	I_LCHDIR,	LOCAL,		NOARGS	},
181 	{ "lchdir",	I_LCHDIR,	LOCAL,		NOARGS	},
182 	{ "lls",	I_LLS,		LOCAL,		NOARGS	},
183 	{ "lmkdir",	I_LMKDIR,	LOCAL,		NOARGS	},
184 	{ "ln",		I_LINK,		REMOTE, 	REMOTE	},
185 	{ "lpwd",	I_LPWD,		LOCAL,		NOARGS	},
186 	{ "ls",		I_LS,		REMOTE,		NOARGS	},
187 	{ "lumask",	I_LUMASK,	NOARGS,		NOARGS	},
188 	{ "mkdir",	I_MKDIR,	REMOTE,		NOARGS	},
189 	{ "mget",	I_GET,		REMOTE,		LOCAL	},
190 	{ "mput",	I_PUT,		LOCAL,		REMOTE	},
191 	{ "progress",	I_PROGRESS,	NOARGS,		NOARGS	},
192 	{ "put",	I_PUT,		LOCAL,		REMOTE	},
193 	{ "pwd",	I_PWD,		REMOTE, 	NOARGS	},
194 	{ "quit",	I_QUIT,		NOARGS, 	NOARGS	},
195 	{ "reget",	I_REGET,	REMOTE, 	LOCAL	},
196 	{ "rename",	I_RENAME,	REMOTE, 	REMOTE	},
197 	{ "reput",	I_REPUT,	LOCAL,		REMOTE	},
198 	{ "rm",		I_RM,		REMOTE,		NOARGS	},
199 	{ "rmdir",	I_RMDIR,	REMOTE,		NOARGS	},
200 	{ "symlink",	I_SYMLINK,	REMOTE,		REMOTE	},
201 	{ "version",	I_VERSION,	NOARGS, 	NOARGS	},
202 	{ "!",		I_SHELL,	NOARGS, 	NOARGS	},
203 	{ "?",		I_HELP,		NOARGS, 	NOARGS	},
204 	{ NULL,		-1,		-1,		-1	}
205 };
206 
207 /* ARGSUSED */
208 __dead static void
209 killchild(int signo)
210 {
211 	pid_t pid;
212 
213 	pid = sshpid;
214 	if (pid > 1) {
215 		kill(pid, SIGTERM);
216 		waitpid(pid, NULL, 0);
217 	}
218 
219 	_exit(1);
220 }
221 
222 /* ARGSUSED */
223 static void
224 suspchild(int signo)
225 {
226 	if (sshpid > 1) {
227 		kill(sshpid, signo);
228 		while (waitpid(sshpid, NULL, WUNTRACED) == -1 && errno == EINTR)
229 			continue;
230 	}
231 	kill(getpid(), SIGSTOP);
232 }
233 
234 /* ARGSUSED */
235 static void
236 cmd_interrupt(int signo)
237 {
238 	const char msg[] = "\rInterrupt  \n";
239 	int olderrno = errno;
240 
241 	(void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
242 	interrupted = 1;
243 	errno = olderrno;
244 }
245 
246 /* ARGSUSED */
247 static void
248 read_interrupt(int signo)
249 {
250 	interrupted = 1;
251 }
252 
253 /*ARGSUSED*/
254 static void
255 sigchld_handler(int sig)
256 {
257 	int save_errno = errno;
258 	pid_t pid;
259 	const char msg[] = "\rConnection closed.  \n";
260 
261 	/* Report if ssh transport process dies. */
262 	while ((pid = waitpid(sshpid, NULL, WNOHANG)) == -1 && errno == EINTR)
263 		continue;
264 	if (pid == sshpid) {
265 		(void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
266 		sshpid = -1;
267 	}
268 
269 	errno = save_errno;
270 }
271 
272 static void
273 help(void)
274 {
275 	printf("Available commands:\n"
276 	    "bye                                Quit sftp\n"
277 	    "cd path                            Change remote directory to 'path'\n"
278 	    "chgrp [-h] grp path                Change group of file 'path' to 'grp'\n"
279 	    "chmod [-h] mode path               Change permissions of file 'path' to 'mode'\n"
280 	    "chown [-h] own path                Change owner of file 'path' to 'own'\n"
281 	    "copy oldpath newpath               Copy remote file\n"
282 	    "cp oldpath newpath                 Copy remote file\n"
283 	    "df [-hi] [path]                    Display statistics for current directory or\n"
284 	    "                                   filesystem containing 'path'\n"
285 	    "exit                               Quit sftp\n"
286 	    "get [-afpR] remote [local]         Download file\n"
287 	    "help                               Display this help text\n"
288 	    "lcd path                           Change local directory to 'path'\n"
289 	    "lls [ls-options [path]]            Display local directory listing\n"
290 	    "lmkdir path                        Create local directory\n"
291 	    "ln [-s] oldpath newpath            Link remote file (-s for symlink)\n"
292 	    "lpwd                               Print local working directory\n"
293 	    "ls [-1afhlnrSt] [path]             Display remote directory listing\n"
294 	    "lumask umask                       Set local umask to 'umask'\n"
295 	    "mkdir path                         Create remote directory\n"
296 	    "progress                           Toggle display of progress meter\n"
297 	    "put [-afpR] local [remote]         Upload file\n"
298 	    "pwd                                Display remote working directory\n"
299 	    "quit                               Quit sftp\n"
300 	    "reget [-fpR] remote [local]        Resume download file\n"
301 	    "rename oldpath newpath             Rename remote file\n"
302 	    "reput [-fpR] local [remote]        Resume upload file\n"
303 	    "rm path                            Delete remote file\n"
304 	    "rmdir path                         Remove remote directory\n"
305 	    "symlink oldpath newpath            Symlink remote file\n"
306 	    "version                            Show SFTP version\n"
307 	    "!command                           Execute 'command' in local shell\n"
308 	    "!                                  Escape to local shell\n"
309 	    "?                                  Synonym for help\n");
310 }
311 
312 static void
313 local_do_shell(const char *args)
314 {
315 	int status;
316 	const char *shell;
317 	pid_t pid;
318 
319 	if (!*args)
320 		args = NULL;
321 
322 	if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
323 		shell = _PATH_BSHELL;
324 
325 	if ((pid = fork()) == -1)
326 		fatal("Couldn't fork: %s", strerror(errno));
327 
328 	if (pid == 0) {
329 		/* XXX: child has pipe fds to ssh subproc open - issue? */
330 		if (args) {
331 			debug3("Executing %s -c \"%s\"", shell, args);
332 			execl(shell, shell, "-c", args, (char *)NULL);
333 		} else {
334 			debug3("Executing %s", shell);
335 			execl(shell, shell, (char *)NULL);
336 		}
337 		fprintf(stderr, "Couldn't execute \"%s\": %s\n", shell,
338 		    strerror(errno));
339 		_exit(1);
340 	}
341 	while (waitpid(pid, &status, 0) == -1)
342 		if (errno != EINTR)
343 			fatal("Couldn't wait for child: %s", strerror(errno));
344 	if (!WIFEXITED(status))
345 		error("Shell exited abnormally");
346 	else if (WEXITSTATUS(status))
347 		error("Shell exited with status %d", WEXITSTATUS(status));
348 }
349 
350 static void
351 local_do_ls(const char *args)
352 {
353 	if (!args || !*args)
354 		local_do_shell(_PATH_LS);
355 	else {
356 		int len = strlen(_PATH_LS " ") + strlen(args) + 1;
357 		char *buf = xmalloc(len);
358 
359 		/* XXX: quoting - rip quoting code from ftp? */
360 		snprintf(buf, len, _PATH_LS " %s", args);
361 		local_do_shell(buf);
362 		free(buf);
363 	}
364 }
365 
366 /* Strip one path (usually the pwd) from the start of another */
367 static char *
368 path_strip(const char *path, const char *strip)
369 {
370 	size_t len;
371 
372 	if (strip == NULL)
373 		return (xstrdup(path));
374 
375 	len = strlen(strip);
376 	if (strncmp(path, strip, len) == 0) {
377 		if (strip[len - 1] != '/' && path[len] == '/')
378 			len++;
379 		return (xstrdup(path + len));
380 	}
381 
382 	return (xstrdup(path));
383 }
384 
385 static int
386 parse_getput_flags(const char *cmd, char **argv, int argc,
387     int *aflag, int *fflag, int *pflag, int *rflag)
388 {
389 	extern int opterr, optind, optopt, optreset;
390 	int ch;
391 
392 	optind = optreset = 1;
393 	opterr = 0;
394 
395 	*aflag = *fflag = *rflag = *pflag = 0;
396 	while ((ch = getopt(argc, argv, "afPpRr")) != -1) {
397 		switch (ch) {
398 		case 'a':
399 			*aflag = 1;
400 			break;
401 		case 'f':
402 			*fflag = 1;
403 			break;
404 		case 'p':
405 		case 'P':
406 			*pflag = 1;
407 			break;
408 		case 'r':
409 		case 'R':
410 			*rflag = 1;
411 			break;
412 		default:
413 			error("%s: Invalid flag -%c", cmd, optopt);
414 			return -1;
415 		}
416 	}
417 
418 	return optind;
419 }
420 
421 static int
422 parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
423 {
424 	extern int opterr, optind, optopt, optreset;
425 	int ch;
426 
427 	optind = optreset = 1;
428 	opterr = 0;
429 
430 	*sflag = 0;
431 	while ((ch = getopt(argc, argv, "s")) != -1) {
432 		switch (ch) {
433 		case 's':
434 			*sflag = 1;
435 			break;
436 		default:
437 			error("%s: Invalid flag -%c", cmd, optopt);
438 			return -1;
439 		}
440 	}
441 
442 	return optind;
443 }
444 
445 static int
446 parse_rename_flags(const char *cmd, char **argv, int argc, int *lflag)
447 {
448 	extern int opterr, optind, optopt, optreset;
449 	int ch;
450 
451 	optind = optreset = 1;
452 	opterr = 0;
453 
454 	*lflag = 0;
455 	while ((ch = getopt(argc, argv, "l")) != -1) {
456 		switch (ch) {
457 		case 'l':
458 			*lflag = 1;
459 			break;
460 		default:
461 			error("%s: Invalid flag -%c", cmd, optopt);
462 			return -1;
463 		}
464 	}
465 
466 	return optind;
467 }
468 
469 static int
470 parse_ls_flags(char **argv, int argc, int *lflag)
471 {
472 	extern int opterr, optind, optopt, optreset;
473 	int ch;
474 
475 	optind = optreset = 1;
476 	opterr = 0;
477 
478 	*lflag = LS_NAME_SORT;
479 	while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) {
480 		switch (ch) {
481 		case '1':
482 			*lflag &= ~VIEW_FLAGS;
483 			*lflag |= LS_SHORT_VIEW;
484 			break;
485 		case 'S':
486 			*lflag &= ~SORT_FLAGS;
487 			*lflag |= LS_SIZE_SORT;
488 			break;
489 		case 'a':
490 			*lflag |= LS_SHOW_ALL;
491 			break;
492 		case 'f':
493 			*lflag &= ~SORT_FLAGS;
494 			break;
495 		case 'h':
496 			*lflag |= LS_SI_UNITS;
497 			break;
498 		case 'l':
499 			*lflag &= ~LS_SHORT_VIEW;
500 			*lflag |= LS_LONG_VIEW;
501 			break;
502 		case 'n':
503 			*lflag &= ~LS_SHORT_VIEW;
504 			*lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW;
505 			break;
506 		case 'r':
507 			*lflag |= LS_REVERSE_SORT;
508 			break;
509 		case 't':
510 			*lflag &= ~SORT_FLAGS;
511 			*lflag |= LS_TIME_SORT;
512 			break;
513 		default:
514 			error("ls: Invalid flag -%c", optopt);
515 			return -1;
516 		}
517 	}
518 
519 	return optind;
520 }
521 
522 static int
523 parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
524 {
525 	extern int opterr, optind, optopt, optreset;
526 	int ch;
527 
528 	optind = optreset = 1;
529 	opterr = 0;
530 
531 	*hflag = *iflag = 0;
532 	while ((ch = getopt(argc, argv, "hi")) != -1) {
533 		switch (ch) {
534 		case 'h':
535 			*hflag = 1;
536 			break;
537 		case 'i':
538 			*iflag = 1;
539 			break;
540 		default:
541 			error("%s: Invalid flag -%c", cmd, optopt);
542 			return -1;
543 		}
544 	}
545 
546 	return optind;
547 }
548 
549 static int
550 parse_ch_flags(const char *cmd, char **argv, int argc, int *hflag)
551 {
552 	extern int opterr, optind, optopt, optreset;
553 	int ch;
554 
555 	optind = optreset = 1;
556 	opterr = 0;
557 
558 	*hflag = 0;
559 	while ((ch = getopt(argc, argv, "h")) != -1) {
560 		switch (ch) {
561 		case 'h':
562 			*hflag = 1;
563 			break;
564 		default:
565 			error("%s: Invalid flag -%c", cmd, optopt);
566 			return -1;
567 		}
568 	}
569 
570 	return optind;
571 }
572 
573 static int
574 parse_no_flags(const char *cmd, char **argv, int argc)
575 {
576 	extern int opterr, optind, optopt, optreset;
577 	int ch;
578 
579 	optind = optreset = 1;
580 	opterr = 0;
581 
582 	while ((ch = getopt(argc, argv, "")) != -1) {
583 		switch (ch) {
584 		default:
585 			error("%s: Invalid flag -%c", cmd, optopt);
586 			return -1;
587 		}
588 	}
589 
590 	return optind;
591 }
592 
593 static char *
594 escape_glob(const char *s)
595 {
596 	size_t i, o, len;
597 	char *ret;
598 
599 	len = strlen(s);
600 	ret = xcalloc(2, len + 1);
601 	for (i = o = 0; i < len; i++) {
602 		if (strchr("[]?*\\", s[i]) != NULL)
603 			ret[o++] = '\\';
604 		ret[o++] = s[i];
605 	}
606 	ret[o++] = '\0';
607 	return ret;
608 }
609 
610 static char *
611 make_absolute_pwd_glob(const char *p, const char *pwd)
612 {
613 	char *ret, *escpwd;
614 
615 	escpwd = escape_glob(pwd);
616 	if (p == NULL)
617 		return escpwd;
618 	ret = make_absolute(xstrdup(p), escpwd);
619 	free(escpwd);
620 	return ret;
621 }
622 
623 static int
624 process_get(struct sftp_conn *conn, const char *src, const char *dst,
625     const char *pwd, int pflag, int rflag, int resume, int fflag)
626 {
627 	char *filename, *abs_src = NULL, *abs_dst = NULL, *tmp = NULL;
628 	glob_t g;
629 	int i, r, err = 0;
630 
631 	abs_src = make_absolute_pwd_glob(src, pwd);
632 	memset(&g, 0, sizeof(g));
633 
634 	debug3("Looking up %s", abs_src);
635 	if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
636 		if (r == GLOB_NOSPACE) {
637 			error("Too many matches for \"%s\".", abs_src);
638 		} else {
639 			error("File \"%s\" not found.", abs_src);
640 		}
641 		err = -1;
642 		goto out;
643 	}
644 
645 	/*
646 	 * If multiple matches then dst must be a directory or
647 	 * unspecified.
648 	 */
649 	if (g.gl_matchc > 1 && dst != NULL && !local_is_dir(dst)) {
650 		error("Multiple source paths, but destination "
651 		    "\"%s\" is not a directory", dst);
652 		err = -1;
653 		goto out;
654 	}
655 
656 	for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
657 		tmp = xstrdup(g.gl_pathv[i]);
658 		if ((filename = basename(tmp)) == NULL) {
659 			error("basename %s: %s", tmp, strerror(errno));
660 			free(tmp);
661 			err = -1;
662 			goto out;
663 		}
664 
665 		if (g.gl_matchc == 1 && dst) {
666 			if (local_is_dir(dst)) {
667 				abs_dst = path_append(dst, filename);
668 			} else {
669 				abs_dst = xstrdup(dst);
670 			}
671 		} else if (dst) {
672 			abs_dst = path_append(dst, filename);
673 		} else {
674 			abs_dst = xstrdup(filename);
675 		}
676 		free(tmp);
677 
678 		resume |= global_aflag;
679 		if (!quiet && resume)
680 			mprintf("Resuming %s to %s\n",
681 			    g.gl_pathv[i], abs_dst);
682 		else if (!quiet && !resume)
683 			mprintf("Fetching %s to %s\n",
684 			    g.gl_pathv[i], abs_dst);
685 		/* XXX follow link flag */
686 		if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
687 			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
688 			    pflag || global_pflag, 1, resume,
689 			    fflag || global_fflag, 0, 0) == -1)
690 				err = -1;
691 		} else {
692 			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
693 			    pflag || global_pflag, resume,
694 			    fflag || global_fflag, 0) == -1)
695 				err = -1;
696 		}
697 		free(abs_dst);
698 		abs_dst = NULL;
699 	}
700 
701 out:
702 	free(abs_src);
703 	globfree(&g);
704 	return(err);
705 }
706 
707 static int
708 process_put(struct sftp_conn *conn, const char *src, const char *dst,
709     const char *pwd, int pflag, int rflag, int resume, int fflag)
710 {
711 	char *tmp_dst = NULL;
712 	char *abs_dst = NULL;
713 	char *tmp = NULL, *filename = NULL;
714 	glob_t g;
715 	int err = 0;
716 	int i, dst_is_dir = 1;
717 	struct stat sb;
718 
719 	if (dst) {
720 		tmp_dst = xstrdup(dst);
721 		tmp_dst = make_absolute(tmp_dst, pwd);
722 	}
723 
724 	memset(&g, 0, sizeof(g));
725 	debug3("Looking up %s", src);
726 	if (glob(src, GLOB_NOCHECK | GLOB_LIMIT | GLOB_MARK, NULL, &g)) {
727 		error("File \"%s\" not found.", src);
728 		err = -1;
729 		goto out;
730 	}
731 
732 	/* If we aren't fetching to pwd then stash this status for later */
733 	if (tmp_dst != NULL)
734 		dst_is_dir = remote_is_dir(conn, tmp_dst);
735 
736 	/* If multiple matches, dst may be directory or unspecified */
737 	if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) {
738 		error("Multiple paths match, but destination "
739 		    "\"%s\" is not a directory", tmp_dst);
740 		err = -1;
741 		goto out;
742 	}
743 
744 	for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
745 		if (stat(g.gl_pathv[i], &sb) == -1) {
746 			err = -1;
747 			error("stat %s: %s", g.gl_pathv[i], strerror(errno));
748 			continue;
749 		}
750 
751 		tmp = xstrdup(g.gl_pathv[i]);
752 		if ((filename = basename(tmp)) == NULL) {
753 			error("basename %s: %s", tmp, strerror(errno));
754 			free(tmp);
755 			err = -1;
756 			goto out;
757 		}
758 
759 		if (g.gl_matchc == 1 && tmp_dst) {
760 			/* If directory specified, append filename */
761 			if (dst_is_dir)
762 				abs_dst = path_append(tmp_dst, filename);
763 			else
764 				abs_dst = xstrdup(tmp_dst);
765 		} else if (tmp_dst) {
766 			abs_dst = path_append(tmp_dst, filename);
767 		} else {
768 			abs_dst = make_absolute(xstrdup(filename), pwd);
769 		}
770 		free(tmp);
771 
772 		resume |= global_aflag;
773 		if (!quiet && resume)
774 			mprintf("Resuming upload of %s to %s\n",
775 			    g.gl_pathv[i], abs_dst);
776 		else if (!quiet && !resume)
777 			mprintf("Uploading %s to %s\n",
778 			    g.gl_pathv[i], abs_dst);
779 		/* XXX follow_link_flag */
780 		if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
781 			if (upload_dir(conn, g.gl_pathv[i], abs_dst,
782 			    pflag || global_pflag, 1, resume,
783 			    fflag || global_fflag, 0, 0) == -1)
784 				err = -1;
785 		} else {
786 			if (do_upload(conn, g.gl_pathv[i], abs_dst,
787 			    pflag || global_pflag, resume,
788 			    fflag || global_fflag, 0) == -1)
789 				err = -1;
790 		}
791 		free(abs_dst);
792 		abs_dst = NULL;
793 	}
794 
795 out:
796 	free(abs_dst);
797 	free(tmp_dst);
798 	globfree(&g);
799 	return(err);
800 }
801 
802 static int
803 sdirent_comp(const void *aa, const void *bb)
804 {
805 	const SFTP_DIRENT *a = *(const SFTP_DIRENT * const *)aa;
806 	const SFTP_DIRENT *b = *(const SFTP_DIRENT * const *)bb;
807 	int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
808 
809 #define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
810 	if (sort_flag & LS_NAME_SORT)
811 		return (rmul * strcmp(a->filename, b->filename));
812 	else if (sort_flag & LS_TIME_SORT)
813 		return (rmul * NCMP(a->a.mtime, b->a.mtime));
814 	else if (sort_flag & LS_SIZE_SORT)
815 		return (rmul * NCMP(a->a.size, b->a.size));
816 
817 	fatal("Unknown ls sort type");
818 	/*NOTREACHED*/
819 	return 0;
820 }
821 
822 /* sftp ls.1 replacement for directories */
823 static int
824 do_ls_dir(struct sftp_conn *conn, const char *path,
825     const char *strip_path, int lflag)
826 {
827 	int n;
828 	u_int c = 1, colspace = 0, columns = 1;
829 	SFTP_DIRENT **d;
830 
831 	if ((n = do_readdir(conn, path, &d)) != 0)
832 		return (n);
833 
834 	if (!(lflag & LS_SHORT_VIEW)) {
835 		u_int m = 0, width = 80;
836 		struct winsize ws;
837 		char *tmp;
838 
839 		/* Count entries for sort and find longest filename */
840 		for (n = 0; d[n] != NULL; n++) {
841 			if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL))
842 				m = MAXIMUM(m, strlen(d[n]->filename));
843 		}
844 
845 		/* Add any subpath that also needs to be counted */
846 		tmp = path_strip(path, strip_path);
847 		m += strlen(tmp);
848 		free(tmp);
849 
850 		if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
851 			width = ws.ws_col;
852 
853 		columns = width / (m + 2);
854 		columns = MAXIMUM(columns, 1);
855 		colspace = width / columns;
856 		colspace = MINIMUM(colspace, width);
857 	}
858 
859 	if (lflag & SORT_FLAGS) {
860 		for (n = 0; d[n] != NULL; n++)
861 			;	/* count entries */
862 		sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
863 		qsort(d, n, sizeof(*d), sdirent_comp);
864 	}
865 
866 	get_remote_user_groups_from_dirents(conn, d);
867 	for (n = 0; d[n] != NULL && !interrupted; n++) {
868 		char *tmp, *fname;
869 
870 		if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL))
871 			continue;
872 
873 		tmp = path_append(path, d[n]->filename);
874 		fname = path_strip(tmp, strip_path);
875 		free(tmp);
876 
877 		if (lflag & LS_LONG_VIEW) {
878 			if ((lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) != 0 ||
879 			    can_get_users_groups_by_id(conn)) {
880 				char *lname;
881 				struct stat sb;
882 
883 				memset(&sb, 0, sizeof(sb));
884 				attrib_to_stat(&d[n]->a, &sb);
885 				lname = ls_file(fname, &sb, 1,
886 				    (lflag & LS_SI_UNITS),
887 				    ruser_name(sb.st_uid),
888 				    rgroup_name(sb.st_gid));
889 				mprintf("%s\n", lname);
890 				free(lname);
891 			} else
892 				mprintf("%s\n", d[n]->longname);
893 		} else {
894 			mprintf("%-*s", colspace, fname);
895 			if (c >= columns) {
896 				printf("\n");
897 				c = 1;
898 			} else
899 				c++;
900 		}
901 
902 		free(fname);
903 	}
904 
905 	if (!(lflag & LS_LONG_VIEW) && (c != 1))
906 		printf("\n");
907 
908 	free_sftp_dirents(d);
909 	return (0);
910 }
911 
912 static int
913 sglob_comp(const void *aa, const void *bb)
914 {
915 	u_int a = *(const u_int *)aa;
916 	u_int b = *(const u_int *)bb;
917 	const char *ap = sort_glob->gl_pathv[a];
918 	const char *bp = sort_glob->gl_pathv[b];
919 #if 0
920 	const struct stat *as = sort_glob->gl_statv[a];
921 	const struct stat *bs = sort_glob->gl_statv[b];
922 #else
923 	struct stat ass, bss;
924 	const struct stat *as = &ass;
925 	const struct stat *bs = &bss;
926 #endif
927 	int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
928 
929 #define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
930 #if 1
931 	if (stat(ap, &ass) == -1 || stat(bp, &bss) == -1)
932 		return 0;
933 #endif
934 	if (sort_flag & LS_NAME_SORT)
935 		return (rmul * strcmp(ap, bp));
936 	else if (sort_flag & LS_TIME_SORT) {
937 		if (timespeccmp(&as->st_mtim, &bs->st_mtim, ==))
938 			return 0;
939 		return timespeccmp(&as->st_mtim, &bs->st_mtim, <) ?
940 		    rmul : -rmul;
941 	} else if (sort_flag & LS_SIZE_SORT)
942 		return (rmul * NCMP(as->st_size, bs->st_size));
943 
944 	fatal("Unknown ls sort type");
945 }
946 
947 /* sftp ls.1 replacement which handles path globs */
948 static int
949 do_globbed_ls(struct sftp_conn *conn, const char *path,
950     const char *strip_path, int lflag)
951 {
952 	char *fname, *lname;
953 	glob_t g;
954 	int err, r;
955 	struct winsize ws;
956 	u_int i, j, nentries, *indices = NULL, c = 1;
957 	u_int colspace = 0, columns = 1, m = 0, width = 80;
958 	struct stat *stp;
959 #ifndef GLOB_KEEPSTAT
960 	struct stat st;
961 #define GLOB_KEEPSTAT	0
962 #endif
963 
964 	memset(&g, 0, sizeof(g));
965 
966 	if ((r = remote_glob(conn, path,
967 	    GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT,
968 	    NULL, &g)) != 0 ||
969 	    (g.gl_pathc && !g.gl_matchc)) {
970 		if (g.gl_pathc)
971 			globfree(&g);
972 		if (r == GLOB_NOSPACE) {
973 			error("Can't ls: Too many matches for \"%s\"", path);
974 		} else {
975 			error("Can't ls: \"%s\" not found", path);
976 		}
977 		return -1;
978 	}
979 
980 	if (interrupted)
981 		goto out;
982 
983 	/*
984 	 * If the glob returns a single match and it is a directory,
985 	 * then just list its contents.
986 	 */
987 	if (g.gl_matchc == 1 &&
988 #if GLOB_KEEPSTAT != 0
989 	    (stp = g.gl_statv[0]) != NULL &&
990 #else
991 	    lstat(g.gl_pathv[0], stp = &st) != -1 &&
992 #endif
993 	    S_ISDIR(stp->st_mode)) {
994 		err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
995 		globfree(&g);
996 		return err;
997 	}
998 
999 	if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
1000 		width = ws.ws_col;
1001 
1002 	if (!(lflag & LS_SHORT_VIEW)) {
1003 		/* Count entries for sort and find longest filename */
1004 		for (i = 0; g.gl_pathv[i]; i++)
1005 			m = MAXIMUM(m, strlen(g.gl_pathv[i]));
1006 
1007 		columns = width / (m + 2);
1008 		columns = MAXIMUM(columns, 1);
1009 		colspace = width / columns;
1010 	}
1011 
1012 	/*
1013 	 * Sorting: rather than mess with the contents of glob_t, prepare
1014 	 * an array of indices into it and sort that. For the usual
1015 	 * unsorted case, the indices are just the identity 1=1, 2=2, etc.
1016 	 */
1017 	for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++)
1018 		;	/* count entries */
1019 	indices = calloc(nentries, sizeof(*indices));
1020 	for (i = 0; i < nentries; i++)
1021 		indices[i] = i;
1022 
1023 	if (lflag & SORT_FLAGS) {
1024 		sort_glob = &g;
1025 		sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
1026 		qsort(indices, nentries, sizeof(*indices), sglob_comp);
1027 		sort_glob = NULL;
1028 	}
1029 
1030 	get_remote_user_groups_from_glob(conn, &g);
1031 	for (j = 0; j < nentries && !interrupted; j++) {
1032 		i = indices[j];
1033 		fname = path_strip(g.gl_pathv[i], strip_path);
1034 		if (lflag & LS_LONG_VIEW) {
1035 #if GLOB_KEEPSTAT != 0
1036 			stp = g.gl_statv[i];
1037 #else
1038 			if (lstat(g.gl_pathv[i], stp = &st) == -1)
1039 				stp = NULL;
1040 #endif
1041 			if (stp == NULL) {
1042 				error("no stat information for %s", fname);
1043 				continue;
1044 			}
1045 			lname = ls_file(fname, stp, 1,
1046 			    (lflag & LS_SI_UNITS),
1047 			    ruser_name(stp->st_uid),
1048 			    rgroup_name(stp->st_gid));
1049 			mprintf("%s\n", lname);
1050 			free(lname);
1051 		} else {
1052 			mprintf("%-*s", colspace, fname);
1053 			if (c >= columns) {
1054 				printf("\n");
1055 				c = 1;
1056 			} else
1057 				c++;
1058 		}
1059 		free(fname);
1060 	}
1061 
1062 	if (!(lflag & LS_LONG_VIEW) && (c != 1))
1063 		printf("\n");
1064 
1065  out:
1066 	if (g.gl_pathc)
1067 		globfree(&g);
1068 	free(indices);
1069 
1070 	return 0;
1071 }
1072 
1073 static int
1074 do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag)
1075 {
1076 	struct sftp_statvfs st;
1077 	char s_used[FMT_SCALED_STRSIZE], s_avail[FMT_SCALED_STRSIZE];
1078 	char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE];
1079 	char s_icapacity[16], s_dcapacity[16];
1080 
1081 	if (do_statvfs(conn, path, &st, 1) == -1)
1082 		return -1;
1083 	if (st.f_files == 0)
1084 		strlcpy(s_icapacity, "ERR", sizeof(s_icapacity));
1085 	else {
1086 		snprintf(s_icapacity, sizeof(s_icapacity), "%3llu%%",
1087 		    (unsigned long long)(100 * (st.f_files - st.f_ffree) /
1088 		    st.f_files));
1089 	}
1090 	if (st.f_blocks == 0)
1091 		strlcpy(s_dcapacity, "ERR", sizeof(s_dcapacity));
1092 	else {
1093 		snprintf(s_dcapacity, sizeof(s_dcapacity), "%3llu%%",
1094 		    (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
1095 		    st.f_blocks));
1096 	}
1097 	if (iflag) {
1098 		printf("     Inodes        Used       Avail      "
1099 		    "(root)    %%Capacity\n");
1100 		printf("%11llu %11llu %11llu %11llu         %s\n",
1101 		    (unsigned long long)st.f_files,
1102 		    (unsigned long long)(st.f_files - st.f_ffree),
1103 		    (unsigned long long)st.f_favail,
1104 		    (unsigned long long)st.f_ffree, s_icapacity);
1105 	} else if (hflag) {
1106 		strlcpy(s_used, "error", sizeof(s_used));
1107 		strlcpy(s_avail, "error", sizeof(s_avail));
1108 		strlcpy(s_root, "error", sizeof(s_root));
1109 		strlcpy(s_total, "error", sizeof(s_total));
1110 		fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used);
1111 		fmt_scaled(st.f_bavail * st.f_frsize, s_avail);
1112 		fmt_scaled(st.f_bfree * st.f_frsize, s_root);
1113 		fmt_scaled(st.f_blocks * st.f_frsize, s_total);
1114 		printf("    Size     Used    Avail   (root)    %%Capacity\n");
1115 		printf("%7sB %7sB %7sB %7sB         %s\n",
1116 		    s_total, s_used, s_avail, s_root, s_dcapacity);
1117 	} else {
1118 		printf("        Size         Used        Avail       "
1119 		    "(root)    %%Capacity\n");
1120 		printf("%12llu %12llu %12llu %12llu         %s\n",
1121 		    (unsigned long long)(st.f_frsize * st.f_blocks / 1024),
1122 		    (unsigned long long)(st.f_frsize *
1123 		    (st.f_blocks - st.f_bfree) / 1024),
1124 		    (unsigned long long)(st.f_frsize * st.f_bavail / 1024),
1125 		    (unsigned long long)(st.f_frsize * st.f_bfree / 1024),
1126 		    s_dcapacity);
1127 	}
1128 	return 0;
1129 }
1130 
1131 /*
1132  * Undo escaping of glob sequences in place. Used to undo extra escaping
1133  * applied in makeargv() when the string is destined for a function that
1134  * does not glob it.
1135  */
1136 static void
1137 undo_glob_escape(char *s)
1138 {
1139 	size_t i, j;
1140 
1141 	for (i = j = 0;;) {
1142 		if (s[i] == '\0') {
1143 			s[j] = '\0';
1144 			return;
1145 		}
1146 		if (s[i] != '\\') {
1147 			s[j++] = s[i++];
1148 			continue;
1149 		}
1150 		/* s[i] == '\\' */
1151 		++i;
1152 		switch (s[i]) {
1153 		case '?':
1154 		case '[':
1155 		case '*':
1156 		case '\\':
1157 			s[j++] = s[i++];
1158 			break;
1159 		case '\0':
1160 			s[j++] = '\\';
1161 			s[j] = '\0';
1162 			return;
1163 		default:
1164 			s[j++] = '\\';
1165 			s[j++] = s[i++];
1166 			break;
1167 		}
1168 	}
1169 }
1170 
1171 /*
1172  * Split a string into an argument vector using sh(1)-style quoting,
1173  * comment and escaping rules, but with some tweaks to handle glob(3)
1174  * wildcards.
1175  * The "sloppy" flag allows for recovery from missing terminating quote, for
1176  * use in parsing incomplete commandlines during tab autocompletion.
1177  *
1178  * Returns NULL on error or a NULL-terminated array of arguments.
1179  *
1180  * If "lastquote" is not NULL, the quoting character used for the last
1181  * argument is placed in *lastquote ("\0", "'" or "\"").
1182  *
1183  * If "terminated" is not NULL, *terminated will be set to 1 when the
1184  * last argument's quote has been properly terminated or 0 otherwise.
1185  * This parameter is only of use if "sloppy" is set.
1186  */
1187 #define MAXARGS		128
1188 #define MAXARGLEN	8192
1189 static char **
1190 makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1191     u_int *terminated)
1192 {
1193 	int argc, quot;
1194 	size_t i, j;
1195 	static char argvs[MAXARGLEN];
1196 	static char *argv[MAXARGS + 1];
1197 	enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q;
1198 
1199 	*argcp = argc = 0;
1200 	if (strlen(arg) > sizeof(argvs) - 1) {
1201  args_too_longs:
1202 		error("string too long");
1203 		return NULL;
1204 	}
1205 	if (terminated != NULL)
1206 		*terminated = 1;
1207 	if (lastquote != NULL)
1208 		*lastquote = '\0';
1209 	state = MA_START;
1210 	i = j = 0;
1211 	for (;;) {
1212 		if ((size_t)argc >= sizeof(argv) / sizeof(*argv)){
1213 			error("Too many arguments.");
1214 			return NULL;
1215 		}
1216 		if (isspace((unsigned char)arg[i])) {
1217 			if (state == MA_UNQUOTED) {
1218 				/* Terminate current argument */
1219 				argvs[j++] = '\0';
1220 				argc++;
1221 				state = MA_START;
1222 			} else if (state != MA_START)
1223 				argvs[j++] = arg[i];
1224 		} else if (arg[i] == '"' || arg[i] == '\'') {
1225 			q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE;
1226 			if (state == MA_START) {
1227 				argv[argc] = argvs + j;
1228 				state = q;
1229 				if (lastquote != NULL)
1230 					*lastquote = arg[i];
1231 			} else if (state == MA_UNQUOTED)
1232 				state = q;
1233 			else if (state == q)
1234 				state = MA_UNQUOTED;
1235 			else
1236 				argvs[j++] = arg[i];
1237 		} else if (arg[i] == '\\') {
1238 			if (state == MA_SQUOTE || state == MA_DQUOTE) {
1239 				quot = state == MA_SQUOTE ? '\'' : '"';
1240 				/* Unescape quote we are in */
1241 				/* XXX support \n and friends? */
1242 				if (arg[i + 1] == quot) {
1243 					i++;
1244 					argvs[j++] = arg[i];
1245 				} else if (arg[i + 1] == '?' ||
1246 				    arg[i + 1] == '[' || arg[i + 1] == '*') {
1247 					/*
1248 					 * Special case for sftp: append
1249 					 * double-escaped glob sequence -
1250 					 * glob will undo one level of
1251 					 * escaping. NB. string can grow here.
1252 					 */
1253 					if (j >= sizeof(argvs) - 5)
1254 						goto args_too_longs;
1255 					argvs[j++] = '\\';
1256 					argvs[j++] = arg[i++];
1257 					argvs[j++] = '\\';
1258 					argvs[j++] = arg[i];
1259 				} else {
1260 					argvs[j++] = arg[i++];
1261 					argvs[j++] = arg[i];
1262 				}
1263 			} else {
1264 				if (state == MA_START) {
1265 					argv[argc] = argvs + j;
1266 					state = MA_UNQUOTED;
1267 					if (lastquote != NULL)
1268 						*lastquote = '\0';
1269 				}
1270 				if (arg[i + 1] == '?' || arg[i + 1] == '[' ||
1271 				    arg[i + 1] == '*' || arg[i + 1] == '\\') {
1272 					/*
1273 					 * Special case for sftp: append
1274 					 * escaped glob sequence -
1275 					 * glob will undo one level of
1276 					 * escaping.
1277 					 */
1278 					argvs[j++] = arg[i++];
1279 					argvs[j++] = arg[i];
1280 				} else {
1281 					/* Unescape everything */
1282 					/* XXX support \n and friends? */
1283 					i++;
1284 					argvs[j++] = arg[i];
1285 				}
1286 			}
1287 		} else if (arg[i] == '#') {
1288 			if (state == MA_SQUOTE || state == MA_DQUOTE)
1289 				argvs[j++] = arg[i];
1290 			else
1291 				goto string_done;
1292 		} else if (arg[i] == '\0') {
1293 			if (state == MA_SQUOTE || state == MA_DQUOTE) {
1294 				if (sloppy) {
1295 					state = MA_UNQUOTED;
1296 					if (terminated != NULL)
1297 						*terminated = 0;
1298 					goto string_done;
1299 				}
1300 				error("Unterminated quoted argument");
1301 				return NULL;
1302 			}
1303  string_done:
1304 			if (state == MA_UNQUOTED) {
1305 				argvs[j++] = '\0';
1306 				argc++;
1307 			}
1308 			break;
1309 		} else {
1310 			if (state == MA_START) {
1311 				argv[argc] = argvs + j;
1312 				state = MA_UNQUOTED;
1313 				if (lastquote != NULL)
1314 					*lastquote = '\0';
1315 			}
1316 			if ((state == MA_SQUOTE || state == MA_DQUOTE) &&
1317 			    (arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) {
1318 				/*
1319 				 * Special case for sftp: escape quoted
1320 				 * glob(3) wildcards. NB. string can grow
1321 				 * here.
1322 				 */
1323 				if (j >= sizeof(argvs) - 3)
1324 					goto args_too_longs;
1325 				argvs[j++] = '\\';
1326 				argvs[j++] = arg[i];
1327 			} else
1328 				argvs[j++] = arg[i];
1329 		}
1330 		i++;
1331 	}
1332 	*argcp = argc;
1333 	return argv;
1334 }
1335 
1336 static int
1337 parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag,
1338 	  int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
1339 	  int *rflag, int *sflag,
1340     unsigned long *n_arg, char **path1, char **path2)
1341 {
1342 	const char *cmd, *cp = *cpp;
1343 	char *cp2, **argv;
1344 	int base = 0;
1345 	long long ll;
1346 	int path1_mandatory = 0, i, cmdnum, optidx, argc;
1347 
1348 	/* Skip leading whitespace */
1349 	cp = cp + strspn(cp, WHITESPACE);
1350 
1351 	/*
1352 	 * Check for leading '-' (disable error processing) and '@' (suppress
1353 	 * command echo)
1354 	 */
1355 	*ignore_errors = 0;
1356 	*disable_echo = 0;
1357 	for (;*cp != '\0'; cp++) {
1358 		if (*cp == '-') {
1359 			*ignore_errors = 1;
1360 		} else if (*cp == '@') {
1361 			*disable_echo = 1;
1362 		} else {
1363 			/* all other characters terminate prefix processing */
1364 			break;
1365 		}
1366 	}
1367 	cp = cp + strspn(cp, WHITESPACE);
1368 
1369 	/* Ignore blank lines and lines which begin with comment '#' char */
1370 	if (*cp == '\0' || *cp == '#')
1371 		return (0);
1372 
1373 	if ((argv = makeargv(cp, &argc, 0, NULL, NULL)) == NULL)
1374 		return -1;
1375 
1376 	/* Figure out which command we have */
1377 	for (i = 0; cmds[i].c != NULL; i++) {
1378 		if (argv[0] != NULL && strcasecmp(cmds[i].c, argv[0]) == 0)
1379 			break;
1380 	}
1381 	cmdnum = cmds[i].n;
1382 	cmd = cmds[i].c;
1383 
1384 	/* Special case */
1385 	if (*cp == '!') {
1386 		cp++;
1387 		cmdnum = I_SHELL;
1388 	} else if (cmdnum == -1) {
1389 		error("Invalid command.");
1390 		return -1;
1391 	}
1392 
1393 	/* Get arguments and parse flags */
1394 	*aflag = *fflag = *hflag = *iflag = *lflag = *pflag = 0;
1395 	*rflag = *sflag = 0;
1396 	*path1 = *path2 = NULL;
1397 	optidx = 1;
1398 	switch (cmdnum) {
1399 	case I_GET:
1400 	case I_REGET:
1401 	case I_REPUT:
1402 	case I_PUT:
1403 		if ((optidx = parse_getput_flags(cmd, argv, argc,
1404 		    aflag, fflag, pflag, rflag)) == -1)
1405 			return -1;
1406 		/* Get first pathname (mandatory) */
1407 		if (argc - optidx < 1) {
1408 			error("You must specify at least one path after a "
1409 			    "%s command.", cmd);
1410 			return -1;
1411 		}
1412 		*path1 = xstrdup(argv[optidx]);
1413 		/* Get second pathname (optional) */
1414 		if (argc - optidx > 1) {
1415 			*path2 = xstrdup(argv[optidx + 1]);
1416 			/* Destination is not globbed */
1417 			undo_glob_escape(*path2);
1418 		}
1419 		break;
1420 	case I_LINK:
1421 		if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
1422 			return -1;
1423 		goto parse_two_paths;
1424 	case I_COPY:
1425 		if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1426 			return -1;
1427 		goto parse_two_paths;
1428 	case I_RENAME:
1429 		if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1)
1430 			return -1;
1431 		goto parse_two_paths;
1432 	case I_SYMLINK:
1433 		if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1434 			return -1;
1435  parse_two_paths:
1436 		if (argc - optidx < 2) {
1437 			error("You must specify two paths after a %s "
1438 			    "command.", cmd);
1439 			return -1;
1440 		}
1441 		*path1 = xstrdup(argv[optidx]);
1442 		*path2 = xstrdup(argv[optidx + 1]);
1443 		/* Paths are not globbed */
1444 		undo_glob_escape(*path1);
1445 		undo_glob_escape(*path2);
1446 		break;
1447 	case I_RM:
1448 	case I_MKDIR:
1449 	case I_RMDIR:
1450 	case I_LMKDIR:
1451 		path1_mandatory = 1;
1452 		/* FALLTHROUGH */
1453 	case I_CHDIR:
1454 	case I_LCHDIR:
1455 		if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1456 			return -1;
1457 		/* Get pathname (mandatory) */
1458 		if (argc - optidx < 1) {
1459 			if (!path1_mandatory)
1460 				break; /* return a NULL path1 */
1461 			error("You must specify a path after a %s command.",
1462 			    cmd);
1463 			return -1;
1464 		}
1465 		*path1 = xstrdup(argv[optidx]);
1466 		/* Only "rm" globs */
1467 		if (cmdnum != I_RM)
1468 			undo_glob_escape(*path1);
1469 		break;
1470 	case I_DF:
1471 		if ((optidx = parse_df_flags(cmd, argv, argc, hflag,
1472 		    iflag)) == -1)
1473 			return -1;
1474 		/* Default to current directory if no path specified */
1475 		if (argc - optidx < 1)
1476 			*path1 = NULL;
1477 		else {
1478 			*path1 = xstrdup(argv[optidx]);
1479 			undo_glob_escape(*path1);
1480 		}
1481 		break;
1482 	case I_LS:
1483 		if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1)
1484 			return(-1);
1485 		/* Path is optional */
1486 		if (argc - optidx > 0)
1487 			*path1 = xstrdup(argv[optidx]);
1488 		break;
1489 	case I_LLS:
1490 		/* Skip ls command and following whitespace */
1491 		cp = cp + strlen(cmd) + strspn(cp, WHITESPACE);
1492 	case I_SHELL:
1493 		/* Uses the rest of the line */
1494 		break;
1495 	case I_LUMASK:
1496 	case I_CHMOD:
1497 		base = 8;
1498 		/* FALLTHROUGH */
1499 	case I_CHOWN:
1500 	case I_CHGRP:
1501 		if ((optidx = parse_ch_flags(cmd, argv, argc, hflag)) == -1)
1502 			return -1;
1503 		/* Get numeric arg (mandatory) */
1504 		if (argc - optidx < 1)
1505 			goto need_num_arg;
1506 		errno = 0;
1507 		ll = strtoll(argv[optidx], &cp2, base);
1508 		if (cp2 == argv[optidx] || *cp2 != '\0' ||
1509 		    ((ll == LLONG_MIN || ll == LLONG_MAX) && errno == ERANGE) ||
1510 		    ll < 0 || ll > UINT32_MAX) {
1511  need_num_arg:
1512 			error("You must supply a numeric argument "
1513 			    "to the %s command.", cmd);
1514 			return -1;
1515 		}
1516 		*n_arg = ll;
1517 		if (cmdnum == I_LUMASK)
1518 			break;
1519 		/* Get pathname (mandatory) */
1520 		if (argc - optidx < 2) {
1521 			error("You must specify a path after a %s command.",
1522 			    cmd);
1523 			return -1;
1524 		}
1525 		*path1 = xstrdup(argv[optidx + 1]);
1526 		break;
1527 	case I_QUIT:
1528 	case I_PWD:
1529 	case I_LPWD:
1530 	case I_HELP:
1531 	case I_VERSION:
1532 	case I_PROGRESS:
1533 		if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1534 			return -1;
1535 		break;
1536 	default:
1537 		fatal("Command not implemented");
1538 	}
1539 
1540 	*cpp = cp;
1541 	return(cmdnum);
1542 }
1543 
1544 static int
1545 parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1546     const char *startdir, int err_abort, int echo_command)
1547 {
1548 	const char *ocmd = cmd;
1549 	char *path1, *path2, *tmp;
1550 	int ignore_errors = 0, disable_echo = 1;
1551 	int aflag = 0, fflag = 0, hflag = 0, iflag = 0;
1552 	int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
1553 	int cmdnum, i;
1554 	unsigned long n_arg = 0;
1555 	Attrib a, *aa;
1556 	char path_buf[PATH_MAX];
1557 	int err = 0;
1558 	glob_t g;
1559 
1560 	pflag = 0;	/* XXX gcc */
1561 	lflag = 0;	/* XXX gcc */
1562 	iflag = 0;	/* XXX gcc */
1563 	hflag = 0;	/* XXX gcc */
1564 	n_arg = 0;	/* XXX gcc */
1565 
1566 	path1 = path2 = NULL;
1567 	cmdnum = parse_args(&cmd, &ignore_errors, &disable_echo, &aflag, &fflag,
1568 	    &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg,
1569 	    &path1, &path2);
1570 	if (ignore_errors != 0)
1571 		err_abort = 0;
1572 
1573 	if (echo_command && !disable_echo)
1574 		mprintf("sftp> %s\n", ocmd);
1575 
1576 	memset(&g, 0, sizeof(g));
1577 
1578 	/* Perform command */
1579 	switch (cmdnum) {
1580 	case 0:
1581 		/* Blank line */
1582 		break;
1583 	case -1:
1584 		/* Unrecognized command */
1585 		err = -1;
1586 		break;
1587 	case I_REGET:
1588 		aflag = 1;
1589 		/* FALLTHROUGH */
1590 	case I_GET:
1591 		err = process_get(conn, path1, path2, *pwd, pflag,
1592 		    rflag, aflag, fflag);
1593 		break;
1594 	case I_REPUT:
1595 		aflag = 1;
1596 		/* FALLTHROUGH */
1597 	case I_PUT:
1598 		err = process_put(conn, path1, path2, *pwd, pflag,
1599 		    rflag, aflag, fflag);
1600 		break;
1601 	case I_COPY:
1602 		path1 = make_absolute(path1, *pwd);
1603 		path2 = make_absolute(path2, *pwd);
1604 		err = do_copy(conn, path1, path2);
1605 		break;
1606 	case I_RENAME:
1607 		path1 = make_absolute(path1, *pwd);
1608 		path2 = make_absolute(path2, *pwd);
1609 		err = do_rename(conn, path1, path2, lflag);
1610 		break;
1611 	case I_SYMLINK:
1612 		sflag = 1;
1613 		/* FALLTHROUGH */
1614 	case I_LINK:
1615 		if (!sflag)
1616 			path1 = make_absolute(path1, *pwd);
1617 		path2 = make_absolute(path2, *pwd);
1618 		err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
1619 		break;
1620 	case I_RM:
1621 		path1 = make_absolute_pwd_glob(path1, *pwd);
1622 		remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1623 		for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1624 			if (!quiet)
1625 				mprintf("Removing %s\n", g.gl_pathv[i]);
1626 			err = do_rm(conn, g.gl_pathv[i]);
1627 			if (err != 0 && err_abort)
1628 				break;
1629 		}
1630 		break;
1631 	case I_MKDIR:
1632 		path1 = make_absolute(path1, *pwd);
1633 		attrib_clear(&a);
1634 		a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
1635 		a.perm = 0777;
1636 		err = do_mkdir(conn, path1, &a, 1);
1637 		break;
1638 	case I_RMDIR:
1639 		path1 = make_absolute(path1, *pwd);
1640 		err = do_rmdir(conn, path1);
1641 		break;
1642 	case I_CHDIR:
1643 		if (path1 == NULL || *path1 == '\0')
1644 			path1 = xstrdup(startdir);
1645 		path1 = make_absolute(path1, *pwd);
1646 		if ((tmp = do_realpath(conn, path1)) == NULL) {
1647 			err = 1;
1648 			break;
1649 		}
1650 		if ((aa = do_stat(conn, tmp, 0)) == NULL) {
1651 			free(tmp);
1652 			err = 1;
1653 			break;
1654 		}
1655 		if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
1656 			error("Can't change directory: Can't check target");
1657 			free(tmp);
1658 			err = 1;
1659 			break;
1660 		}
1661 		if (!S_ISDIR(aa->perm)) {
1662 			error("Can't change directory: \"%s\" is not "
1663 			    "a directory", tmp);
1664 			free(tmp);
1665 			err = 1;
1666 			break;
1667 		}
1668 		free(*pwd);
1669 		*pwd = tmp;
1670 		break;
1671 	case I_LS:
1672 		if (!path1) {
1673 			do_ls_dir(conn, *pwd, *pwd, lflag);
1674 			break;
1675 		}
1676 
1677 		/* Strip pwd off beginning of non-absolute paths */
1678 		tmp = NULL;
1679 		if (!path_absolute(path1))
1680 			tmp = *pwd;
1681 
1682 		path1 = make_absolute_pwd_glob(path1, *pwd);
1683 		err = do_globbed_ls(conn, path1, tmp, lflag);
1684 		break;
1685 	case I_DF:
1686 		/* Default to current directory if no path specified */
1687 		if (path1 == NULL)
1688 			path1 = xstrdup(*pwd);
1689 		path1 = make_absolute(path1, *pwd);
1690 		err = do_df(conn, path1, hflag, iflag);
1691 		break;
1692 	case I_LCHDIR:
1693 		if (path1 == NULL || *path1 == '\0')
1694 			path1 = xstrdup("~");
1695 		tmp = tilde_expand_filename(path1, getuid());
1696 		free(path1);
1697 		path1 = tmp;
1698 		if (chdir(path1) == -1) {
1699 			error("Couldn't change local directory to "
1700 			    "\"%s\": %s", path1, strerror(errno));
1701 			err = 1;
1702 		}
1703 		break;
1704 	case I_LMKDIR:
1705 		if (mkdir(path1, 0777) == -1) {
1706 			error("Couldn't create local directory "
1707 			    "\"%s\": %s", path1, strerror(errno));
1708 			err = 1;
1709 		}
1710 		break;
1711 	case I_LLS:
1712 		local_do_ls(cmd);
1713 		break;
1714 	case I_SHELL:
1715 		local_do_shell(cmd);
1716 		break;
1717 	case I_LUMASK:
1718 		umask(n_arg);
1719 		printf("Local umask: %03lo\n", n_arg);
1720 		break;
1721 	case I_CHMOD:
1722 		path1 = make_absolute_pwd_glob(path1, *pwd);
1723 		attrib_clear(&a);
1724 		a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
1725 		a.perm = n_arg;
1726 		remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1727 		for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1728 			if (!quiet)
1729 				mprintf("Changing mode on %s\n",
1730 				    g.gl_pathv[i]);
1731 			err = (hflag ? do_lsetstat : do_setstat)(conn,
1732 			    g.gl_pathv[i], &a);
1733 			if (err != 0 && err_abort)
1734 				break;
1735 		}
1736 		break;
1737 	case I_CHOWN:
1738 	case I_CHGRP:
1739 		path1 = make_absolute_pwd_glob(path1, *pwd);
1740 		remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1741 		for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1742 			if (!(aa = (hflag ? do_lstat : do_stat)(conn,
1743 			    g.gl_pathv[i], 0))) {
1744 				if (err_abort) {
1745 					err = -1;
1746 					break;
1747 				} else
1748 					continue;
1749 			}
1750 			if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
1751 				error("Can't get current ownership of "
1752 				    "remote file \"%s\"", g.gl_pathv[i]);
1753 				if (err_abort) {
1754 					err = -1;
1755 					break;
1756 				} else
1757 					continue;
1758 			}
1759 			aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
1760 			if (cmdnum == I_CHOWN) {
1761 				if (!quiet)
1762 					mprintf("Changing owner on %s\n",
1763 					    g.gl_pathv[i]);
1764 				aa->uid = n_arg;
1765 			} else {
1766 				if (!quiet)
1767 					mprintf("Changing group on %s\n",
1768 					    g.gl_pathv[i]);
1769 				aa->gid = n_arg;
1770 			}
1771 			err = (hflag ? do_lsetstat : do_setstat)(conn,
1772 			    g.gl_pathv[i], aa);
1773 			if (err != 0 && err_abort)
1774 				break;
1775 		}
1776 		break;
1777 	case I_PWD:
1778 		mprintf("Remote working directory: %s\n", *pwd);
1779 		break;
1780 	case I_LPWD:
1781 		if (!getcwd(path_buf, sizeof(path_buf))) {
1782 			error("Couldn't get local cwd: %s", strerror(errno));
1783 			err = -1;
1784 			break;
1785 		}
1786 		mprintf("Local working directory: %s\n", path_buf);
1787 		break;
1788 	case I_QUIT:
1789 		/* Processed below */
1790 		break;
1791 	case I_HELP:
1792 		help();
1793 		break;
1794 	case I_VERSION:
1795 		printf("SFTP protocol version %u\n", sftp_proto_version(conn));
1796 		break;
1797 	case I_PROGRESS:
1798 		showprogress = !showprogress;
1799 		if (showprogress)
1800 			printf("Progress meter enabled\n");
1801 		else
1802 			printf("Progress meter disabled\n");
1803 		break;
1804 	default:
1805 		fatal("%d is not implemented", cmdnum);
1806 	}
1807 
1808 	if (g.gl_pathc)
1809 		globfree(&g);
1810 	free(path1);
1811 	free(path2);
1812 
1813 	/* If an unignored error occurs in batch mode we should abort. */
1814 	if (err_abort && err != 0)
1815 		return (-1);
1816 	else if (cmdnum == I_QUIT)
1817 		return (1);
1818 
1819 	return (0);
1820 }
1821 
1822 static const char *
1823 prompt(EditLine *el)
1824 {
1825 	return ("sftp> ");
1826 }
1827 
1828 /* Display entries in 'list' after skipping the first 'len' chars */
1829 static void
1830 complete_display(char **list, u_int len)
1831 {
1832 	u_int y, m = 0, width = 80, columns = 1, colspace = 0, llen;
1833 	struct winsize ws;
1834 	const char *tmp;
1835 
1836 	/* Count entries for sort and find longest */
1837 	for (y = 0; list[y]; y++)
1838 		m = MAXIMUM(m, strlen(list[y]));
1839 
1840 	if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
1841 		width = ws.ws_col;
1842 
1843 	m = m > len ? m - len : 0;
1844 	columns = width / (m + 2);
1845 	columns = MAXIMUM(columns, 1);
1846 	colspace = width / columns;
1847 	colspace = MINIMUM(colspace, width);
1848 
1849 	printf("\n");
1850 	m = 1;
1851 	for (y = 0; list[y]; y++) {
1852 		llen = strlen(list[y]);
1853 		tmp = llen > len ? list[y] + len : "";
1854 		mprintf("%-*s", colspace, tmp);
1855 		if (m >= columns) {
1856 			printf("\n");
1857 			m = 1;
1858 		} else
1859 			m++;
1860 	}
1861 	printf("\n");
1862 }
1863 
1864 /*
1865  * Given a "list" of words that begin with a common prefix of "word",
1866  * attempt to find an autocompletion to extends "word" by the next
1867  * characters common to all entries in "list".
1868  */
1869 static char *
1870 complete_ambiguous(const char *word, char **list, size_t count)
1871 {
1872 	if (word == NULL)
1873 		return NULL;
1874 
1875 	if (count > 0) {
1876 		u_int y, matchlen = strlen(list[0]);
1877 
1878 		/* Find length of common stem */
1879 		for (y = 1; list[y]; y++) {
1880 			u_int x;
1881 
1882 			for (x = 0; x < matchlen; x++)
1883 				if (list[0][x] != list[y][x])
1884 					break;
1885 
1886 			matchlen = x;
1887 		}
1888 
1889 		if (matchlen > strlen(word)) {
1890 			char *tmp = xstrdup(list[0]);
1891 
1892 			tmp[matchlen] = '\0';
1893 			return tmp;
1894 		}
1895 	}
1896 
1897 	return xstrdup(word);
1898 }
1899 
1900 /* Autocomplete a sftp command */
1901 static int
1902 complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1903     int terminated)
1904 {
1905 	u_int y, count = 0, cmdlen, tmplen;
1906 	char *tmp, **list, argterm[3];
1907 	const LineInfo *lf;
1908 
1909 	list = xcalloc((sizeof(cmds) / sizeof(*cmds)) + 1, sizeof(char *));
1910 
1911 	/* No command specified: display all available commands */
1912 	if (cmd == NULL) {
1913 		for (y = 0; cmds[y].c; y++)
1914 			list[count++] = xstrdup(cmds[y].c);
1915 
1916 		list[count] = NULL;
1917 		complete_display(list, 0);
1918 
1919 		for (y = 0; list[y] != NULL; y++)
1920 			free(list[y]);
1921 		free(list);
1922 		return count;
1923 	}
1924 
1925 	/* Prepare subset of commands that start with "cmd" */
1926 	cmdlen = strlen(cmd);
1927 	for (y = 0; cmds[y].c; y++)  {
1928 		if (!strncasecmp(cmd, cmds[y].c, cmdlen))
1929 			list[count++] = xstrdup(cmds[y].c);
1930 	}
1931 	list[count] = NULL;
1932 
1933 	if (count == 0) {
1934 		free(list);
1935 		return 0;
1936 	}
1937 
1938 	/* Complete ambiguous command */
1939 	tmp = complete_ambiguous(cmd, list, count);
1940 	if (count > 1)
1941 		complete_display(list, 0);
1942 
1943 	for (y = 0; list[y]; y++)
1944 		free(list[y]);
1945 	free(list);
1946 
1947 	if (tmp != NULL) {
1948 		tmplen = strlen(tmp);
1949 		cmdlen = strlen(cmd);
1950 		/* If cmd may be extended then do so */
1951 		if (tmplen > cmdlen)
1952 			if (el_insertstr(el, tmp + cmdlen) == -1)
1953 				fatal("el_insertstr failed.");
1954 		lf = el_line(el);
1955 		/* Terminate argument cleanly */
1956 		if (count == 1) {
1957 			y = 0;
1958 			if (!terminated)
1959 				argterm[y++] = quote;
1960 			if (lastarg || *(lf->cursor) != ' ')
1961 				argterm[y++] = ' ';
1962 			argterm[y] = '\0';
1963 			if (y > 0 && el_insertstr(el, argterm) == -1)
1964 				fatal("el_insertstr failed.");
1965 		}
1966 		free(tmp);
1967 	}
1968 
1969 	return count;
1970 }
1971 
1972 /*
1973  * Determine whether a particular sftp command's arguments (if any) represent
1974  * local or remote files. The "cmdarg" argument specifies the actual argument
1975  * and accepts values 1 or 2.
1976  */
1977 static int
1978 complete_is_remote(char *cmd, int cmdarg) {
1979 	int i;
1980 
1981 	if (cmd == NULL)
1982 		return -1;
1983 
1984 	for (i = 0; cmds[i].c; i++) {
1985 		if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c))) {
1986 			if (cmdarg == 1)
1987 				return cmds[i].t;
1988 			else if (cmdarg == 2)
1989 				return cmds[i].t2;
1990 			break;
1991 		}
1992 	}
1993 
1994 	return -1;
1995 }
1996 
1997 /* Autocomplete a filename "file" */
1998 static int
1999 complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
2000     char *file, int remote, int lastarg, char quote, int terminated)
2001 {
2002 	glob_t g;
2003 	char *tmp, *tmp2, ins[8];
2004 	u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs;
2005 	int clen;
2006 	const LineInfo *lf;
2007 
2008 	/* Glob from "file" location */
2009 	if (file == NULL)
2010 		tmp = xstrdup("*");
2011 	else
2012 		xasprintf(&tmp, "%s*", file);
2013 
2014 	/* Check if the path is absolute. */
2015 	isabs = path_absolute(tmp);
2016 
2017 	memset(&g, 0, sizeof(g));
2018 	if (remote != LOCAL) {
2019 		tmp = make_absolute_pwd_glob(tmp, remote_path);
2020 		remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
2021 	} else
2022 		glob(tmp, GLOB_LIMIT|GLOB_DOOFFS|GLOB_MARK, NULL, &g);
2023 
2024 	/* Determine length of pwd so we can trim completion display */
2025 	for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) {
2026 		/* Terminate counting on first unescaped glob metacharacter */
2027 		if (tmp[tmplen] == '*' || tmp[tmplen] == '?') {
2028 			if (tmp[tmplen] != '*' || tmp[tmplen + 1] != '\0')
2029 				hadglob = 1;
2030 			break;
2031 		}
2032 		if (tmp[tmplen] == '\\' && tmp[tmplen + 1] != '\0')
2033 			tmplen++;
2034 		if (tmp[tmplen] == '/')
2035 			pwdlen = tmplen + 1;	/* track last seen '/' */
2036 	}
2037 	free(tmp);
2038 	tmp = NULL;
2039 
2040 	if (g.gl_matchc == 0)
2041 		goto out;
2042 
2043 	if (g.gl_matchc > 1)
2044 		complete_display(g.gl_pathv, pwdlen);
2045 
2046 	/* Don't try to extend globs */
2047 	if (file == NULL || hadglob)
2048 		goto out;
2049 
2050 	tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc);
2051 	tmp = path_strip(tmp2, isabs ? NULL : remote_path);
2052 	free(tmp2);
2053 
2054 	if (tmp == NULL)
2055 		goto out;
2056 
2057 	tmplen = strlen(tmp);
2058 	filelen = strlen(file);
2059 
2060 	/* Count the number of escaped characters in the input string. */
2061 	cesc = isesc = 0;
2062 	for (i = 0; i < filelen; i++) {
2063 		if (!isesc && file[i] == '\\' && i + 1 < filelen){
2064 			isesc = 1;
2065 			cesc++;
2066 		} else
2067 			isesc = 0;
2068 	}
2069 
2070 	if (tmplen > (filelen - cesc)) {
2071 		tmp2 = tmp + filelen - cesc;
2072 		len = strlen(tmp2);
2073 		/* quote argument on way out */
2074 		for (i = 0; i < len; i += clen) {
2075 			if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
2076 			    (size_t)clen > sizeof(ins) - 2)
2077 				fatal("invalid multibyte character");
2078 			ins[0] = '\\';
2079 			memcpy(ins + 1, tmp2 + i, clen);
2080 			ins[clen + 1] = '\0';
2081 			switch (tmp2[i]) {
2082 			case '\'':
2083 			case '"':
2084 			case '\\':
2085 			case '\t':
2086 			case '[':
2087 			case ' ':
2088 			case '#':
2089 			case '*':
2090 				if (quote == '\0' || tmp2[i] == quote) {
2091 					if (el_insertstr(el, ins) == -1)
2092 						fatal("el_insertstr "
2093 						    "failed.");
2094 					break;
2095 				}
2096 				/* FALLTHROUGH */
2097 			default:
2098 				if (el_insertstr(el, ins + 1) == -1)
2099 					fatal("el_insertstr failed.");
2100 				break;
2101 			}
2102 		}
2103 	}
2104 
2105 	lf = el_line(el);
2106 	if (g.gl_matchc == 1) {
2107 		i = 0;
2108 		if (!terminated && quote != '\0')
2109 			ins[i++] = quote;
2110 		if (*(lf->cursor - 1) != '/' &&
2111 		    (lastarg || *(lf->cursor) != ' '))
2112 			ins[i++] = ' ';
2113 		ins[i] = '\0';
2114 		if (i > 0 && el_insertstr(el, ins) == -1)
2115 			fatal("el_insertstr failed.");
2116 	}
2117 	free(tmp);
2118 
2119  out:
2120 	globfree(&g);
2121 	return g.gl_matchc;
2122 }
2123 
2124 /* tab-completion hook function, called via libedit */
2125 static unsigned char
2126 complete(EditLine *el, int ch)
2127 {
2128 	char **argv, *line, quote;
2129 	int argc, carg;
2130 	u_int cursor, len, terminated, ret = CC_ERROR;
2131 	const LineInfo *lf;
2132 	struct complete_ctx *complete_ctx;
2133 
2134 	lf = el_line(el);
2135 	if (el_get(el, EL_CLIENTDATA, &complete_ctx) != 0)
2136 		fatal_f("el_get failed");
2137 
2138 	/* Figure out which argument the cursor points to */
2139 	cursor = lf->cursor - lf->buffer;
2140 	line = xmalloc(cursor + 1);
2141 	memcpy(line, lf->buffer, cursor);
2142 	line[cursor] = '\0';
2143 	argv = makeargv(line, &carg, 1, &quote, &terminated);
2144 	free(line);
2145 
2146 	/* Get all the arguments on the line */
2147 	len = lf->lastchar - lf->buffer;
2148 	line = xmalloc(len + 1);
2149 	memcpy(line, lf->buffer, len);
2150 	line[len] = '\0';
2151 	argv = makeargv(line, &argc, 1, NULL, NULL);
2152 
2153 	/* Ensure cursor is at EOL or a argument boundary */
2154 	if (line[cursor] != ' ' && line[cursor] != '\0' &&
2155 	    line[cursor] != '\n') {
2156 		free(line);
2157 		return ret;
2158 	}
2159 
2160 	if (carg == 0) {
2161 		/* Show all available commands */
2162 		complete_cmd_parse(el, NULL, argc == carg, '\0', 1);
2163 		ret = CC_REDISPLAY;
2164 	} else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ')  {
2165 		/* Handle the command parsing */
2166 		if (complete_cmd_parse(el, argv[0], argc == carg,
2167 		    quote, terminated) != 0)
2168 			ret = CC_REDISPLAY;
2169 	} else if (carg >= 1) {
2170 		/* Handle file parsing */
2171 		int remote = 0;
2172 		int i = 0, cmdarg = 0;
2173 		char *filematch = NULL;
2174 
2175 		if (carg > 1 && line[cursor-1] != ' ')
2176 			filematch = argv[carg - 1];
2177 
2178 		for (i = 1; i < carg; i++) {
2179 			/* Skip flags */
2180 			if (argv[i][0] != '-')
2181 				cmdarg++;
2182 		}
2183 
2184 		/*
2185 		 * If previous argument is complete, then offer completion
2186 		 * on the next one.
2187 		 */
2188 		if (line[cursor - 1] == ' ')
2189 			cmdarg++;
2190 
2191 		remote = complete_is_remote(argv[0], cmdarg);
2192 
2193 		if ((remote == REMOTE || remote == LOCAL) &&
2194 		    complete_match(el, complete_ctx->conn,
2195 		    *complete_ctx->remote_pathp, filematch,
2196 		    remote, carg == argc, quote, terminated) != 0)
2197 			ret = CC_REDISPLAY;
2198 	}
2199 
2200 	free(line);
2201 	return ret;
2202 }
2203 
2204 static int
2205 interactive_loop(struct sftp_conn *conn, const char *file1, const char *file2)
2206 {
2207 	char *remote_path;
2208 	char *dir = NULL, *startdir = NULL;
2209 	char cmd[2048];
2210 	int err, interactive;
2211 	EditLine *el = NULL;
2212 	History *hl = NULL;
2213 	HistEvent hev;
2214 	extern char *__progname;
2215 	struct complete_ctx complete_ctx;
2216 
2217 	if (!batchmode && isatty(STDIN_FILENO)) {
2218 		if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL)
2219 			fatal("Couldn't initialise editline");
2220 		if ((hl = history_init()) == NULL)
2221 			fatal("Couldn't initialise editline history");
2222 		history(hl, &hev, H_SETSIZE, 100);
2223 		el_set(el, EL_HIST, history, hl);
2224 
2225 		el_set(el, EL_PROMPT, prompt);
2226 		el_set(el, EL_EDITOR, "emacs");
2227 		el_set(el, EL_TERMINAL, NULL);
2228 		el_set(el, EL_SIGNAL, 1);
2229 		el_source(el, NULL);
2230 
2231 		/* Tab Completion */
2232 		el_set(el, EL_ADDFN, "ftp-complete",
2233 		    "Context sensitive argument completion", complete);
2234 		complete_ctx.conn = conn;
2235 		complete_ctx.remote_pathp = &remote_path;
2236 		el_set(el, EL_CLIENTDATA, (void*)&complete_ctx);
2237 		el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
2238 		/* enable ctrl-left-arrow and ctrl-right-arrow */
2239 		el_set(el, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
2240 		el_set(el, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
2241 		el_set(el, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
2242 		el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
2243 		/* make ^w match ksh behaviour */
2244 		el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL);
2245 	}
2246 
2247 	remote_path = do_realpath(conn, ".");
2248 	if (remote_path == NULL)
2249 		fatal("Need cwd");
2250 	startdir = xstrdup(remote_path);
2251 
2252 	if (file1 != NULL) {
2253 		dir = xstrdup(file1);
2254 		dir = make_absolute(dir, remote_path);
2255 
2256 		if (remote_is_dir(conn, dir) && file2 == NULL) {
2257 			if (!quiet)
2258 				mprintf("Changing to: %s\n", dir);
2259 			snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
2260 			if (parse_dispatch_command(conn, cmd,
2261 			    &remote_path, startdir, 1, 0) != 0) {
2262 				free(dir);
2263 				free(startdir);
2264 				free(remote_path);
2265 				free(conn);
2266 				return (-1);
2267 			}
2268 		} else {
2269 			/* XXX this is wrong wrt quoting */
2270 			snprintf(cmd, sizeof cmd, "get%s %s%s%s",
2271 			    global_aflag ? " -a" : "", dir,
2272 			    file2 == NULL ? "" : " ",
2273 			    file2 == NULL ? "" : file2);
2274 			err = parse_dispatch_command(conn, cmd,
2275 			    &remote_path, startdir, 1, 0);
2276 			free(dir);
2277 			free(startdir);
2278 			free(remote_path);
2279 			free(conn);
2280 			return (err);
2281 		}
2282 		free(dir);
2283 	}
2284 
2285 	setvbuf(stdout, NULL, _IOLBF, 0);
2286 	setvbuf(infile, NULL, _IOLBF, 0);
2287 
2288 	interactive = !batchmode && isatty(STDIN_FILENO);
2289 	err = 0;
2290 	for (;;) {
2291 		struct sigaction sa;
2292 		const char *line;
2293 		int count = 0;
2294 
2295 		interrupted = 0;
2296 		memset(&sa, 0, sizeof(sa));
2297 		sa.sa_handler = interactive ? read_interrupt : killchild;
2298 		if (sigaction(SIGINT, &sa, NULL) == -1) {
2299 			debug3("sigaction(%s): %s", strsignal(SIGINT),
2300 			    strerror(errno));
2301 			break;
2302 		}
2303 		if (el == NULL) {
2304 			if (interactive)
2305 				printf("sftp> ");
2306 			if (fgets(cmd, sizeof(cmd), infile) == NULL) {
2307 				if (interactive)
2308 					printf("\n");
2309 				if (interrupted)
2310 					continue;
2311 				break;
2312 			}
2313 		} else {
2314 			if ((line = el_gets(el, &count)) == NULL ||
2315 			    count <= 0) {
2316 				printf("\n");
2317 				if (interrupted)
2318 					continue;
2319 				break;
2320 			}
2321 			history(hl, &hev, H_ENTER, line);
2322 			if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {
2323 				fprintf(stderr, "Error: input line too long\n");
2324 				continue;
2325 			}
2326 		}
2327 
2328 		cmd[strcspn(cmd, "\n")] = '\0';
2329 
2330 		/* Handle user interrupts gracefully during commands */
2331 		interrupted = 0;
2332 		ssh_signal(SIGINT, cmd_interrupt);
2333 
2334 		err = parse_dispatch_command(conn, cmd, &remote_path,
2335 		    startdir, batchmode, !interactive && el == NULL);
2336 		if (err != 0)
2337 			break;
2338 	}
2339 	ssh_signal(SIGCHLD, SIG_DFL);
2340 	free(remote_path);
2341 	free(startdir);
2342 	free(conn);
2343 
2344 	if (el != NULL)
2345 		el_end(el);
2346 
2347 	/* err == 1 signifies normal "quit" exit */
2348 	return (err >= 0 ? 0 : -1);
2349 }
2350 
2351 static void
2352 connect_to_server(const char *path, char **args, int *in, int *out)
2353 {
2354 	int c_in, c_out, inout[2];
2355 
2356 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)
2357 		fatal("socketpair: %s", strerror(errno));
2358 	*in = *out = inout[0];
2359 	c_in = c_out = inout[1];
2360 
2361 	if ((sshpid = fork()) == -1)
2362 		fatal("fork: %s", strerror(errno));
2363 	else if (sshpid == 0) {
2364 		if ((dup2(c_in, STDIN_FILENO) == -1) ||
2365 		    (dup2(c_out, STDOUT_FILENO) == -1)) {
2366 			fprintf(stderr, "dup2: %s\n", strerror(errno));
2367 			_exit(1);
2368 		}
2369 		close(*in);
2370 		close(*out);
2371 		close(c_in);
2372 		close(c_out);
2373 
2374 		/*
2375 		 * The underlying ssh is in the same process group, so we must
2376 		 * ignore SIGINT if we want to gracefully abort commands,
2377 		 * otherwise the signal will make it to the ssh process and
2378 		 * kill it too.  Contrawise, since sftp sends SIGTERMs to the
2379 		 * underlying ssh, it must *not* ignore that signal.
2380 		 */
2381 		ssh_signal(SIGINT, SIG_IGN);
2382 		ssh_signal(SIGTERM, SIG_DFL);
2383 		execvp(path, args);
2384 		fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
2385 		_exit(1);
2386 	}
2387 
2388 	ssh_signal(SIGTERM, killchild);
2389 	ssh_signal(SIGINT, killchild);
2390 	ssh_signal(SIGHUP, killchild);
2391 	ssh_signal(SIGTSTP, suspchild);
2392 	ssh_signal(SIGTTIN, suspchild);
2393 	ssh_signal(SIGTTOU, suspchild);
2394 	ssh_signal(SIGCHLD, sigchld_handler);
2395 	close(c_in);
2396 	close(c_out);
2397 }
2398 
2399 __dead static void
2400 usage(void)
2401 {
2402 	extern char *__progname;
2403 
2404 	fprintf(stderr,
2405 	    "usage: %s [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
2406 	    "          [-D sftp_server_command] [-F ssh_config] [-i identity_file]\n"
2407 	    "          [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
2408 	    "          [-R num_requests] [-S program] [-s subsystem | sftp_server]\n"
2409 	    "          destination\n",
2410 	    __progname);
2411 	exit(1);
2412 }
2413 
2414 int
2415 main(int argc, char **argv)
2416 {
2417 	int r, in, out, ch, err, tmp, port = -1, noisy = 0;
2418 	char *host = NULL, *user, *cp, **cpp, *file1 = NULL, *file2 = NULL;
2419 	int debug_level = 0;
2420 	const char *sftp_server = NULL;
2421 	const char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
2422 	const char *errstr;
2423 	LogLevel ll = SYSLOG_LEVEL_INFO;
2424 	arglist args;
2425 	extern int optind;
2426 	extern char *optarg;
2427 	struct sftp_conn *conn;
2428 	size_t copy_buffer_len = 0;
2429 	size_t num_requests = 0;
2430 	long long limit_kbps = 0;
2431 
2432 	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2433 	sanitise_stdfd();
2434 	setlocale(LC_CTYPE, "");
2435 
2436 	memset(&args, '\0', sizeof(args));
2437 	args.list = NULL;
2438 	addargs(&args, "%s", ssh_program);
2439 	addargs(&args, "-oForwardX11 no");
2440 	addargs(&args, "-oPermitLocalCommand no");
2441 	addargs(&args, "-oClearAllForwardings yes");
2442 
2443 	ll = SYSLOG_LEVEL_INFO;
2444 	infile = stdin;
2445 
2446 	while ((ch = getopt(argc, argv,
2447 	    "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) {
2448 		switch (ch) {
2449 		/* Passed through to ssh(1) */
2450 		case 'A':
2451 		case '4':
2452 		case '6':
2453 		case 'C':
2454 			addargs(&args, "-%c", ch);
2455 			break;
2456 		/* Passed through to ssh(1) with argument */
2457 		case 'F':
2458 		case 'J':
2459 		case 'c':
2460 		case 'i':
2461 		case 'o':
2462 			addargs(&args, "-%c", ch);
2463 			addargs(&args, "%s", optarg);
2464 			break;
2465 		case 'q':
2466 			ll = SYSLOG_LEVEL_ERROR;
2467 			quiet = 1;
2468 			showprogress = 0;
2469 			addargs(&args, "-%c", ch);
2470 			break;
2471 		case 'P':
2472 			port = a2port(optarg);
2473 			if (port <= 0)
2474 				fatal("Bad port \"%s\"\n", optarg);
2475 			break;
2476 		case 'v':
2477 			if (debug_level < 3) {
2478 				addargs(&args, "-v");
2479 				ll = SYSLOG_LEVEL_DEBUG1 + debug_level;
2480 			}
2481 			debug_level++;
2482 			break;
2483 		case '1':
2484 			fatal("SSH protocol v.1 is no longer supported");
2485 			break;
2486 		case '2':
2487 			/* accept silently */
2488 			break;
2489 		case 'a':
2490 			global_aflag = 1;
2491 			break;
2492 		case 'B':
2493 			copy_buffer_len = strtol(optarg, &cp, 10);
2494 			if (copy_buffer_len == 0 || *cp != '\0')
2495 				fatal("Invalid buffer size \"%s\"", optarg);
2496 			break;
2497 		case 'b':
2498 			if (batchmode)
2499 				fatal("Batch file already specified.");
2500 
2501 			/* Allow "-" as stdin */
2502 			if (strcmp(optarg, "-") != 0 &&
2503 			    (infile = fopen(optarg, "r")) == NULL)
2504 				fatal("%s (%s).", strerror(errno), optarg);
2505 			showprogress = 0;
2506 			quiet = batchmode = 1;
2507 			addargs(&args, "-obatchmode yes");
2508 			break;
2509 		case 'f':
2510 			global_fflag = 1;
2511 			break;
2512 		case 'N':
2513 			noisy = 1; /* Used to clear quiet mode after getopt */
2514 			break;
2515 		case 'p':
2516 			global_pflag = 1;
2517 			break;
2518 		case 'D':
2519 			sftp_direct = optarg;
2520 			break;
2521 		case 'l':
2522 			limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
2523 			    &errstr);
2524 			if (errstr != NULL)
2525 				usage();
2526 			limit_kbps *= 1024; /* kbps */
2527 			break;
2528 		case 'r':
2529 			global_rflag = 1;
2530 			break;
2531 		case 'R':
2532 			num_requests = strtol(optarg, &cp, 10);
2533 			if (num_requests == 0 || *cp != '\0')
2534 				fatal("Invalid number of requests \"%s\"",
2535 				    optarg);
2536 			break;
2537 		case 's':
2538 			sftp_server = optarg;
2539 			break;
2540 		case 'S':
2541 			ssh_program = optarg;
2542 			replacearg(&args, 0, "%s", ssh_program);
2543 			break;
2544 		case 'h':
2545 		default:
2546 			usage();
2547 		}
2548 	}
2549 
2550 	/* Do this last because we want the user to be able to override it */
2551 	addargs(&args, "-oForwardAgent no");
2552 
2553 	if (!isatty(STDERR_FILENO))
2554 		showprogress = 0;
2555 
2556 	if (noisy)
2557 		quiet = 0;
2558 
2559 	log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
2560 
2561 	if (sftp_direct == NULL) {
2562 		if (optind == argc || argc > (optind + 2))
2563 			usage();
2564 		argv += optind;
2565 
2566 		switch (parse_uri("sftp", *argv, &user, &host, &tmp, &file1)) {
2567 		case -1:
2568 			usage();
2569 			break;
2570 		case 0:
2571 			if (tmp != -1)
2572 				port = tmp;
2573 			break;
2574 		default:
2575 			/* Try with user, host and path. */
2576 			if (parse_user_host_path(*argv, &user, &host,
2577 			    &file1) == 0)
2578 				break;
2579 			/* Try with user and host. */
2580 			if (parse_user_host_port(*argv, &user, &host, NULL)
2581 			    == 0)
2582 				break;
2583 			/* Treat as a plain hostname. */
2584 			host = xstrdup(*argv);
2585 			host = cleanhostname(host);
2586 			break;
2587 		}
2588 		file2 = *(argv + 1);
2589 
2590 		if (!*host) {
2591 			fprintf(stderr, "Missing hostname\n");
2592 			usage();
2593 		}
2594 
2595 		if (port != -1)
2596 			addargs(&args, "-oPort %d", port);
2597 		if (user != NULL) {
2598 			addargs(&args, "-l");
2599 			addargs(&args, "%s", user);
2600 		}
2601 
2602 		/* no subsystem if the server-spec contains a '/' */
2603 		if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)
2604 			addargs(&args, "-s");
2605 
2606 		addargs(&args, "--");
2607 		addargs(&args, "%s", host);
2608 		addargs(&args, "%s", (sftp_server != NULL ?
2609 		    sftp_server : "sftp"));
2610 
2611 		connect_to_server(ssh_program, args.list, &in, &out);
2612 	} else {
2613 		if ((r = argv_split(sftp_direct, &tmp, &cpp, 1)) != 0)
2614 			fatal_r(r, "Parse -D arguments");
2615 		if (cpp[0] == 0)
2616 			fatal("No sftp server specified via -D");
2617 		connect_to_server(cpp[0], cpp, &in, &out);
2618 		argv_free(cpp, tmp);
2619 	}
2620 	freeargs(&args);
2621 
2622 	conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps);
2623 	if (conn == NULL)
2624 		fatal("Couldn't initialise connection to server");
2625 
2626 	if (!quiet) {
2627 		if (sftp_direct == NULL)
2628 			fprintf(stderr, "Connected to %s.\n", host);
2629 		else
2630 			fprintf(stderr, "Attached to %s.\n", sftp_direct);
2631 	}
2632 
2633 	err = interactive_loop(conn, file1, file2);
2634 
2635 	close(in);
2636 	close(out);
2637 	if (batchmode)
2638 		fclose(infile);
2639 
2640 	while (waitpid(sshpid, NULL, 0) == -1 && sshpid > 1)
2641 		if (errno != EINTR)
2642 			fatal("Couldn't wait for ssh process: %s",
2643 			    strerror(errno));
2644 
2645 	exit(err == 0 ? 0 : 1);
2646 }
2647