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