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