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