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