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