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