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