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