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