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