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