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