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