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