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