# 
# old_revision [701f8835d5e1759b9b73c6fd7d1eab708f3b7882]
# 
# add_file ".mt-attrs"
# 
# add_file "ssh-xfer.c"
# 
# patch ".mt-attrs"
#  from []
#    to [2255fea673e2fa649896aa80a39fe72cb4fb966d]
# 
# patch "Makefile.in"
#  from [2d0423fea68d8a3004e32b7e262dfa36c0391924]
#    to [504fc9e5e067b3e8580f567a93dc758a63fe552d]
# 
# patch "authfd.c"
#  from [eff279634e8dcd5cc9b6c64213a8d36a68092538]
#    to [b05e152abae99780d98530a215db09c602c17711]
# 
# patch "authfd.h"
#  from [298895eee53b2c4cbf05fd16f58d3070e402ed12]
#    to [bbbda6d15a0409823787cb25fef1a7404d0b9132]
# 
# patch "ssh-agent.c"
#  from [e198575e6448e6f553ccbad54bb7cc4900f9d2eb]
#    to [bcc34251bc107b9daa1a7f6283c807aca3479876]
# 
# patch "ssh-xfer.c"
#  from []
#    to [a0ec393c7c91687f1e8f452ad46dbe82a6f27bec]
# 
============================================================
--- Makefile.in	2d0423fea68d8a3004e32b7e262dfa36c0391924
+++ Makefile.in	504fc9e5e067b3e8580f567a93dc758a63fe552d
@@ -59,7 +59,7 @@
 INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
 INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
 
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-xfer$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
 
 LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o buffer.o \
 	canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
@@ -143,6 +143,9 @@
 ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
 	$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
 
+ssh-xfer$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-xfer.o
+	$(LD) -o $@ ssh-xfer.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
 ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o
 	$(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
 
@@ -248,6 +251,7 @@
 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh $(DESTDIR)$(bindir)/ssh
 	$(INSTALL) -m 0755 $(STRIP_OPT) scp $(DESTDIR)$(bindir)/scp
 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-add $(DESTDIR)$(bindir)/ssh-add
+	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-xfer $(DESTDIR)$(bindir)/ssh-xfer
 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent $(DESTDIR)$(bindir)/ssh-agent
 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen $(DESTDIR)$(bindir)/ssh-keygen
 	$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan
@@ -349,6 +353,7 @@
 	-rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+	-rm -f $(DESTDIR)$(bindir)/ssh-xfer$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
============================================================
--- authfd.c	eff279634e8dcd5cc9b6c64213a8d36a68092538
+++ authfd.c	b05e152abae99780d98530a215db09c602c17711
@@ -112,6 +112,27 @@
 }
 
 static int
+ssh_request_noreply(AuthenticationConnection *auth, Buffer *request)
+{
+	int l;
+	u_int len;
+	char buf[1024];
+
+	/* Get the length of the message, and format it in the buffer. */
+	len = buffer_len(request);
+	PUT_32BIT(buf, len);
+
+	/* Send the length and then the packet to the agent. */
+	if (atomicio(vwrite, auth->fd, buf, 4) != 4 ||
+	    atomicio(vwrite, auth->fd, buffer_ptr(request),
+	    buffer_len(request)) != buffer_len(request)) {
+		error("Error writing to authentication socket.");
+		return 0;
+	}
+	return 1;
+}
+
+static int
 ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
 {
 	int l;
@@ -139,7 +160,7 @@
 		if (l == -1 && (errno == EAGAIN || errno == EINTR))
 			continue;
 		if (l <= 0) {
-			error("Error reading response length from authentication socket.");
+			error("Error reading response length from authentication socket: %s", strerror(errno));
 			return 0;
 		}
 		len -= l;
@@ -150,6 +171,7 @@
 	if (len > 256 * 1024)
 		fatal("Authentication response too long: %u", len);
 
+
 	/* Read the rest of the response in to the buffer. */
 	buffer_clear(reply);
 	while (len > 0) {
@@ -160,7 +182,8 @@
 		if (l == -1 && (errno == EAGAIN || errno == EINTR))
 			continue;
 		if (l <= 0) {
-			error("Error reading response from authentication socket.");
+			error("Error reading response from authentication socket: %s",
+					strerror(errno));
 			return 0;
 		}
 		buffer_append(reply, buf, l);
@@ -669,3 +692,63 @@
 	/* NOTREACHED */
 	return 0;
 }
+
+int
+send_xferreq(AuthenticationConnection *auth, char* filename, u_int size,
+		int havesize) {
+
+	Buffer request, reply;
+	int ret;
+
+	buffer_init(&request);
+	buffer_init(&reply);
+
+	buffer_put_char(&request, SSH_AGENTC_XFER_REQUEST);
+	buffer_put_string(&request, filename, strlen(filename));
+	buffer_put_int(&request, size);
+	buffer_put_int(&request, havesize);
+
+	fprintf(stderr, "Sending file\n");
+	ret = ssh_request_reply(auth, &request, &reply);
+
+	buffer_free(&reply);
+	buffer_free(&request);
+	return ret;
+}
+
+int send_xferdata(AuthenticationConnection *auth, char* buf, u_int size) {
+
+	Buffer request;
+	int ret;
+
+	buffer_init(&request);
+
+	buffer_put_char(&request, SSH_AGENTC_XFER_DATA);
+	buffer_put_string(&request, buf, size);
+
+	fprintf(stderr, ".");
+	ret = ssh_request_noreply(auth, &request);
+
+	buffer_free(&request);
+	return ret;
+}
+
+int send_xferdone(AuthenticationConnection *auth) {
+
+	Buffer request, reply;
+	int ret;
+
+	buffer_init(&request);
+	buffer_init(&reply);
+
+	buffer_put_char(&request, SSH_AGENTC_XFER_DONE);
+
+	fprintf(stderr, " done");
+	ret = ssh_request_reply(auth, &request, &reply);
+	fprintf(stderr, ".\n");
+
+	buffer_free(&reply);
+	buffer_free(&request);
+	return ret;
+}
+
============================================================
--- authfd.h	298895eee53b2c4cbf05fd16f58d3070e402ed12
+++ authfd.h	bbbda6d15a0409823787cb25fef1a7404d0b9132
@@ -57,6 +57,12 @@
 /* extended failure messages */
 #define SSH2_AGENT_FAILURE			30
 
+/* matt's filexfer-over-agent */
+#define SSH_AGENTC_XFER_REQUEST 90
+#define SSH_AGENTC_XFER_DONE 91
+#define SSH_AGENTC_XFER_DATA 92
+
+
 /* additional error code for ssh.com's ssh-agent2 */
 #define SSH_COM_AGENT2_FAILURE			102
 
@@ -94,4 +100,10 @@
 ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *,
     u_int);
 
+int
+send_xferreq(AuthenticationConnection *auth, char* filename, u_int size,
+		int havesize);
+int send_xferdata(AuthenticationConnection *auth, char* buf, u_int size);
+int send_xferdone(AuthenticationConnection *auth);
+
 #endif				/* AUTHFD_H */
============================================================
--- ssh-agent.c	e198575e6448e6f553ccbad54bb7cc4900f9d2eb
+++ ssh-agent.c	bcc34251bc107b9daa1a7f6283c807aca3479876
@@ -52,7 +52,11 @@
 #include "log.h"
 #include "readpass.h"
 #include "misc.h"
+#include "tildexpand.h"
 
+/* for basename */
+#include <libgen.h>
+
 #ifdef SMARTCARD
 #include "scard.h"
 #endif
@@ -61,18 +65,33 @@
 #include <sys/prctl.h>	/* For prctl() and PR_SET_DUMPABLE */
 #endif
 
+#define XFER_DEST_DIR "~/Desktop"
+
 typedef enum {
 	AUTH_UNUSED,
 	AUTH_SOCKET,
 	AUTH_CONNECTION
 } sock_type;
 
+/* matt */
 typedef struct {
+
+	char* filename;
+	unsigned int size;
+	unsigned int havesize; /* A flag if we have a filesize */
+	unsigned int progress; /* How far we've got */
+	char filepath[MAXPATHLEN];
 	int fd;
+
+} FileXFer;
+
+typedef struct {
+	int fd;
 	sock_type type;
 	Buffer input;
 	Buffer output;
 	Buffer request;
+	FileXFer xferdata; /* matt */
 } SocketEntry;
 
 u_int sockets_alloc = 0;
@@ -125,6 +144,10 @@
 	buffer_free(&e->input);
 	buffer_free(&e->output);
 	buffer_free(&e->request);
+	if (e->xferdata.filename) {
+		xfree(e->xferdata.filename);
+		e->xferdata.filename = NULL;
+	}
 }
 
 static void
@@ -193,6 +216,156 @@
 	return (ret);
 }
 
+static void
+process_xferdone(SocketEntry *e) {
+
+	/* HACKY */
+	debug("process_xferdone");
+	buffer_clear(&e->request);
+
+	buffer_put_int(&e->output, 1);
+	if (e->xferdata.filename != NULL) {
+		xfree(e->xferdata.filename);
+		e->xferdata.filename = NULL;
+		buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+	} else {
+		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+	}
+	debug("process_xferdone done");
+}
+
+static void
+process_xfer(SocketEntry *e) {
+
+	char* full_filename = NULL;
+	char* filename = NULL;
+	char* filepath = NULL;
+	char* destdir = NULL;
+	int i, fd;
+
+	full_filename = buffer_get_string(&e->request, NULL);
+	e->xferdata.size = buffer_get_int(&e->request);
+	e->xferdata.havesize = buffer_get_int(&e->request);
+
+	if (strstr(full_filename, "..") != NULL) {
+		logit("ssh-xfer remote side tried to send a filename with '..' in it. Bad remote-side!");
+		goto fail;
+	}
+
+	filename = xstrdup(basename(full_filename));
+	xfree(full_filename);
+	full_filename = NULL;
+
+	debug("process_xfer: read data: file '%s' size '%d'", filename,
+			e->xferdata.size);
+
+	destdir = tilde_expand_filename(XFER_DEST_DIR, getuid());
+
+	e->xferdata.fd = -1;
+
+	/* TODO! matt  - make it configurable*/
+	filepath = e->xferdata.filepath;
+	snprintf(filepath, MAXPATHLEN, "%s/%s", destdir, filename);
+
+	fd = open(filepath, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR |
+			S_IWUSR);
+
+	if (fd < 0) {
+		for (i = 0; i < 1000; i++) {
+			snprintf(filepath, MAXPATHLEN, "%s/%s.%d", destdir, filename, i);
+
+			fd = open(filepath, O_CREAT | O_WRONLY | O_EXCL,
+					S_IRUSR | S_IWUSR); 
+			if (fd >= 0) { 
+				break;
+			}
+
+		}
+	}
+
+	if (fd < 0) {
+		debug("failed opening file %s: %s", filepath, strerror(errno));
+		goto fail;
+	}
+
+	debug("filepath is '%s'", filepath);
+	e->xferdata.filename = filename;
+
+	e->xferdata.fd = fd;
+	e->xferdata.progress = 0;
+
+	buffer_clear(&e->request);
+	buffer_put_int(&e->output, 1);
+	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+	debug("finish process: success");
+	return;
+
+fail:
+	if (filename) {
+		xfree(filename);
+	}
+	buffer_clear(&e->request);
+	buffer_put_int(&e->output, 1);
+	buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+	debug("finish process: fail");
+
+}
+
+static void
+process_xferdata(SocketEntry *e) {
+
+	unsigned int size;
+	int val;
+
+	debug("enter process_xferdata");
+	if (e->xferdata.filename == NULL || e->xferdata.fd < 0) {
+		logit("Client tried xferdata with unopened socket: fd %d file %s", 
+				e->xferdata.fd, e->xferdata.filename);
+		close_socket(e);
+		return;
+	}
+
+	size = buffer_get_int(&e->request);
+	
+	/* We fail if:
+	 * - we had a filesize (havesize == 1) and this write would go past the end
+	 * or
+	 * - the buffer doesn't have enough data for this chunk size */
+	if ( (e->xferdata.havesize == 1
+				&& (size + e->xferdata.progress > e->xferdata.size))
+			|| buffer_len(&e->request) < size ) {
+
+		/* Past end of file */
+		logit("ssh-xfer write past end of file: size %d progress %d filesize %d buflen %d", size, e->xferdata.progress, e->xferdata.size, buffer_len(&e->request));
+		goto finishup;
+	}
+
+	val = write(e->xferdata.fd, buffer_ptr(&e->request), size);
+	if (val < 0) {
+		logit("failed write for fd %d: %s", e->xferdata.fd, strerror(errno));
+		goto finishup;
+	}
+
+	e->xferdata.progress += size;
+
+	buffer_clear(&e->request);
+	/*
+	No output is written, that way we don't have problems with
+	latency/windowing etc. The SSH channel layer should handle all of that.
+	*/
+	close(e->xferdata.fd);
+	debug("process_xferdata: success");
+	return;
+
+finishup:
+	close(e->xferdata.fd);
+	unlink(e->xferdata.filepath);
+	debug("process_xferdata: fail");
+
+}
+
+
+
 /* send list of supported public keys to 'client' */
 static void
 process_request_identities(SocketEntry *e, int version)
@@ -682,7 +855,8 @@
 
 /* dispatch incoming messages */
 
-static void
+/* Returns 0 on finished, or 1 on "call me again please" */
+static int
 process_message(SocketEntry *e)
 {
 	u_int msg_len, type;
@@ -692,15 +866,15 @@
 	reaper();
 
 	if (buffer_len(&e->input) < 5)
-		return;		/* Incomplete message. */
+		return 0;		/* Incomplete message. */
 	cp = buffer_ptr(&e->input);
 	msg_len = GET_32BIT(cp);
 	if (msg_len > 256 * 1024) {
 		close_socket(e);
-		return;
+		return 0;
 	}
 	if (buffer_len(&e->input) < msg_len + 4)
-		return;
+		return 0;
 
 	/* move the current input to e->request */
 	buffer_consume(&e->input, 4);
@@ -723,7 +897,7 @@
 			buffer_put_int(&e->output, 1);
 			buffer_put_char(&e->output, SSH_AGENT_FAILURE);
 		}
-		return;
+		return 1;
 	}
 
 	debug("type %d", type);
@@ -775,6 +949,15 @@
 		process_remove_smartcard_key(e);
 		break;
 #endif /* SMARTCARD */
+	case SSH_AGENTC_XFER_REQUEST:
+		process_xfer(e);
+		break;
+	case SSH_AGENTC_XFER_DATA:
+		process_xferdata(e);
+		break;
+	case SSH_AGENTC_XFER_DONE:
+		process_xferdone(e);
+		break;
 	default:
 		/* Unknown message.  Respond with failure. */
 		error("Unknown message %d", type);
@@ -783,6 +966,7 @@
 		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
 		break;
 	}
+	return 1;
 }
 
 static void
@@ -803,6 +987,7 @@
 			buffer_init(&sockets[i].output);
 			buffer_init(&sockets[i].request);
 			sockets[i].type = type;
+			sockets[i].xferdata.filename = NULL;
 			return;
 		}
 	old_alloc = sockets_alloc;
@@ -862,6 +1047,8 @@
 		case AUTH_SOCKET:
 		case AUTH_CONNECTION:
 			FD_SET(sockets[i].fd, *fdrp);
+			debug("fdset, output len (%d) = %d", sockets[i].fd,
+					buffer_len(&sockets[i].output));
 			if (buffer_len(&sockets[i].output) > 0)
 				FD_SET(sockets[i].fd, *fdwp);
 			break;
@@ -883,6 +1070,8 @@
 	uid_t euid;
 	gid_t egid;
 
+	debug("after select");
+
 	for (i = 0; i < sockets_alloc; i++)
 		switch (sockets[i].type) {
 		case AUTH_UNUSED:
@@ -914,6 +1103,7 @@
 			}
 			break;
 		case AUTH_CONNECTION:
+			debug("AUTH_CONNECTION");
 			if (buffer_len(&sockets[i].output) > 0 &&
 			    FD_ISSET(sockets[i].fd, writeset)) {
 				do {
@@ -931,11 +1121,13 @@
 				}
 				buffer_consume(&sockets[i].output, len);
 			}
+
 			if (FD_ISSET(sockets[i].fd, readset)) {
 				do {
 					len = read(sockets[i].fd, buf, sizeof(buf));
 					if (len == -1 && (errno == EAGAIN ||
 					    errno == EINTR))
+						//debug("read EINTR");
 						continue;
 					break;
 				} while (1);
@@ -944,7 +1136,7 @@
 					break;
 				}
 				buffer_append(&sockets[i].input, buf, len);
-				process_message(&sockets[i]);
+				while ( process_message(&sockets[i]) == 1) {};
 			}
 			break;
 		default:
@@ -1233,6 +1425,7 @@
 
 	while (1) {
 		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc);
+
 		if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) {
 			if (errno == EINTR)
 				continue;
============================================================
--- ssh-xfer.c	
+++ ssh-xfer.c	a0ec393c7c91687f1e8f452ad46dbe82a6f27bec
@@ -0,0 +1,165 @@
+/*
+ * ssh-xfer.c (c) 2004 Matt Johnston matt at ucc.asn.au
+ *
+ * Based on ssh-add.c which copyright as below.
+ *
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Adds an identity to the authentication server, or removes an identity.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 implementation,
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include "ssh.h"
+#include "log.h"
+#include "xmalloc.h"
+#include "key.h"
+#include "authfd.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "readpass.h"
+#include "misc.h"
+
+/* for basename */
+#include <libgen.h>
+
+#ifdef HAVE___PROGNAME
+extern char *__progname;
+#else
+char *__progname;
+#endif
+
+
+static void
+usage(void)
+{
+	fprintf(stderr, "Usage: %s <filename> [-]\n", __progname);
+	fprintf(stderr, "If '-' is given as the second argument, <filename> indicates the naming to use,\nwith data taken from standard input.\n");
+
+}
+
+int
+main(int argc, char **argv)
+{
+	AuthenticationConnection *ac = NULL;
+	int ret;
+
+	char* filename = NULL;
+	unsigned int filesize;
+	unsigned int isfile;
+	int filefd = -1;
+	int len;
+	char readbuf[8000]; /* If it's more than about this, the Pageant won't
+						   work.... */
+
+	struct stat sb;
+
+	__progname = ssh_get_progname(argv[0]);
+
+	if (argc < 2 || argc > 3) {
+		usage();
+		exit(1);
+	}
+
+	/* At first, get a connection to the authentication agent. */
+	ac = ssh_get_authentication_connection();
+	if (ac == NULL) {
+		fprintf(stderr, "Could not open a connection to your authentication agent.\n");
+		exit(2);
+	}
+
+	filename = argv[1];
+
+	if (argc == 2) {
+		isfile = 1;
+		filefd = open(filename, O_RDONLY, 0);
+		if (filefd < 0) {
+			fprintf(stderr, "Failed opening file '%s': %s\n", 
+					filename, strerror(errno));
+			exit(1);
+		}
+
+		/* Get the filesize */
+		if (fstat(filefd, &sb) < 0) {
+			fprintf(stderr, "Failed getting size of file: %s\n",
+					strerror(errno));
+			exit(1);
+		}
+		filesize = sb.st_size;
+
+	} else {
+		if (strcmp(argv[2], "-") != 0) {
+			usage();
+			exit(1);
+		}
+		isfile = 0;
+		filefd = STDIN_FILENO;
+	}
+
+	if (send_xferreq(ac, basename(filename), filesize, isfile) == 0) {
+		fprintf(stderr, "Agent responded with failure message.\n");
+		exit(1);
+	}
+
+	/* The sending loop */
+	for (;;) {
+		len = read(filefd, readbuf, sizeof(readbuf));
+		if (len < 0) {
+			if (errno == EINTR) {
+				continue; /* try again */
+			}
+			fprintf(stderr, "Error reading file: %s\n", strerror(errno));
+			ret = 2;
+			goto done;
+		}
+
+		if (len == 0) {
+			close(filefd);
+			send_xferdone(ac);
+			ret = 0;
+			goto done;
+		}
+
+		ret = send_xferdata(ac, readbuf, len);
+		if (ret == 0) {
+			fprintf(stderr, "Error sending file.");
+			ret = 3;
+			goto done;
+		}
+	}
+
+done:
+	close(filefd);
+	ssh_close_authentication_connection(ac);
+	return ret;
+}
