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