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