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