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