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