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