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