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