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