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