summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/ssh/include/atomicio.h32
-rw-r--r--usr/src/cmd/ssh/include/buffer.h5
-rw-r--r--usr/src/cmd/ssh/include/config.h11
-rw-r--r--usr/src/cmd/ssh/include/defines.h29
-rw-r--r--usr/src/cmd/ssh/include/misc.h40
-rw-r--r--usr/src/cmd/ssh/include/openbsd-compat.h32
-rw-r--r--usr/src/cmd/ssh/include/progressmeter.h (renamed from usr/src/cmd/ssh/include/sftp-int.h)30
-rw-r--r--usr/src/cmd/ssh/include/sftp-client.h51
-rw-r--r--usr/src/cmd/ssh/include/sftp-common.h34
-rw-r--r--usr/src/cmd/ssh/include/sftp-glob.h48
-rw-r--r--usr/src/cmd/ssh/libopenbsd-compat/Makefile.com100
-rw-r--r--usr/src/cmd/ssh/libopenbsd-compat/common/bsd-asprintf.c104
-rw-r--r--usr/src/cmd/ssh/libssh/Makefile.com139
-rw-r--r--usr/src/cmd/ssh/libssh/common/atomicio.c54
-rw-r--r--usr/src/cmd/ssh/libssh/common/buffer.c64
-rw-r--r--usr/src/cmd/ssh/libssh/common/llib-lssh9
-rw-r--r--usr/src/cmd/ssh/libssh/common/misc.c126
-rw-r--r--usr/src/cmd/ssh/libssh/common/progressmeter.c308
-rw-r--r--usr/src/cmd/ssh/libssh/common/sftp-common.c52
-rw-r--r--usr/src/cmd/ssh/sftp-server/Makefile29
-rw-r--r--usr/src/cmd/ssh/sftp-server/sftp-server.c530
-rw-r--r--usr/src/cmd/ssh/sftp/Makefile35
-rw-r--r--usr/src/cmd/ssh/sftp/sftp-client.c238
-rw-r--r--usr/src/cmd/ssh/sftp/sftp-glob.c60
-rw-r--r--usr/src/cmd/ssh/sftp/sftp-int.c1098
-rw-r--r--usr/src/cmd/ssh/sftp/sftp.c1509
-rw-r--r--usr/src/cmd/ssh/ssh.po1253
27 files changed, 3701 insertions, 2319 deletions
diff --git a/usr/src/cmd/ssh/include/atomicio.h b/usr/src/cmd/ssh/include/atomicio.h
index 13c9d4b4e6..e1ba7b21e6 100644
--- a/usr/src/cmd/ssh/include/atomicio.h
+++ b/usr/src/cmd/ssh/include/atomicio.h
@@ -1,16 +1,5 @@
-/* $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $ */
-
-#ifndef _ATOMICIO_H
-#define _ATOMICIO_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
/*
+ * Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
@@ -35,11 +24,30 @@ extern "C" {
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _ATOMICIO_H
+#define _ATOMICIO_H
+
+/* $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Ensure all of data on socket comes through. f==read || f==write
*/
ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
+#define vwrite (ssize_t (*)(int, void *, size_t))write
+
+/*
+ * ensure all of data on socket comes through. f==readv || f==writev
+ */
+size_t atomiciov(ssize_t (*)(int, const struct iovec *, int),
+ int, const struct iovec *, int);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/ssh/include/buffer.h b/usr/src/cmd/ssh/include/buffer.h
index 1d09c6335f..4a6c7ad5e1 100644
--- a/usr/src/cmd/ssh/include/buffer.h
+++ b/usr/src/cmd/ssh/include/buffer.h
@@ -30,9 +30,6 @@ typedef struct {
u_int end; /* Offset of last byte containing data. */
} Buffer;
-#define BUFFER_MAX_CHUNK 0x100000
-#define BUFFER_MAX_LEN 0xa00000
-
void buffer_init(Buffer *);
void buffer_clear(Buffer *);
void buffer_free(Buffer *);
@@ -43,6 +40,8 @@ void *buffer_ptr(Buffer *);
void buffer_append(Buffer *, const void *, u_int);
void *buffer_append_space(Buffer *, u_int);
+int buffer_check_alloc(Buffer *, u_int);
+
void buffer_get(Buffer *, void *, u_int);
void buffer_consume(Buffer *, u_int);
diff --git a/usr/src/cmd/ssh/include/config.h b/usr/src/cmd/ssh/include/config.h
index 0441e64951..a2a524204b 100644
--- a/usr/src/cmd/ssh/include/config.h
+++ b/usr/src/cmd/ssh/include/config.h
@@ -2,7 +2,7 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* $Id: acconfig.h,v 1.145 2002/09/26 00:38:48 tim Exp $ */
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -409,6 +409,9 @@ extern "C" {
/* Define if you want smartcard support using sectok */
/* #undef USE_SECTOK */
+/* Use libedit for sftp */
+#undef USE_LIBEDIT
+
/* Define if you want smartcard support using OpenSC */
/* #undef USE_OPENSC */
@@ -434,6 +437,9 @@ extern "C" {
/* Define to 1 if you have the `arc4random' function. */
/* #undef HAVE_ARC4RANDOM */
+/* Define to 1 if you have the `asprintf' function. */
+/* #undef HAVE_ASPRINTF */
+
/* Define to 1 if you have the `b64_ntop' function. */
/* #undef HAVE_B64_NTOP */
@@ -904,6 +910,9 @@ extern "C" {
/* Define to 1 if you have the <utmp.h> header file. */
#define HAVE_UTMP_H 1
+/* Define to 1 if you have the `vasprintf' function. */
+/* #undef HAVE_VASPRINTF */
+
/* Define to 1 if you have the `vhangup' function. */
#define HAVE_VHANGUP 1
diff --git a/usr/src/cmd/ssh/include/defines.h b/usr/src/cmd/ssh/include/defines.h
index 690037ce6b..4b8bbebed6 100644
--- a/usr/src/cmd/ssh/include/defines.h
+++ b/usr/src/cmd/ssh/include/defines.h
@@ -1,5 +1,28 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Damien Miller. 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.
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -403,6 +426,10 @@ struct winsize {
# define __attribute__(x)
#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
+#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__bounded__)
+# define __bounded__(x, y, z)
+#endif
+
/* *-*-nto-qnx doesn't define this macro in the system headers */
#ifdef MISSING_HOWMANY
# define howmany(x,y) (((x)+((y)-1))/(y))
diff --git a/usr/src/cmd/ssh/include/misc.h b/usr/src/cmd/ssh/include/misc.h
index 4951d42013..20937646df 100644
--- a/usr/src/cmd/ssh/include/misc.h
+++ b/usr/src/cmd/ssh/include/misc.h
@@ -1,15 +1,3 @@
-/* $OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $ */
-
-#ifndef _MISC_H
-#define _MISC_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -26,6 +14,17 @@ extern "C" {
* Use is subject to license terms.
*/
+#ifndef _MISC_H
+#define _MISC_H
+
+/* $OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
char *chop(char *);
char *strdelim(char **);
void set_nonblock(int);
@@ -36,6 +35,7 @@ char *cleanhostname(char *);
char *colon(char *);
long convtime(const char *);
char *tohex(const void *, size_t);
+void sanitise_stdfd(void);
int get_yes_no_flag(int *option, const char *arg, const char *filename,
int linenum, int active);
@@ -49,12 +49,28 @@ struct arglist {
int nalloc;
};
void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3)));
+void replacearg(arglist *, u_int, char *, ...)
+ __attribute__((format(printf, 3, 4)));
void freeargs(arglist *);
/* wrapper for signal interface */
typedef void (*mysig_t)(int);
mysig_t mysignal(int sig, mysig_t act);
+/* Functions to extract or store big-endian words of various sizes */
+u_int64_t get_u64(const void *)
+ __attribute__((__bounded__( __minbytes__, 1, 8)));
+u_int32_t get_u32(const void *)
+ __attribute__((__bounded__( __minbytes__, 1, 4)));
+u_int16_t get_u16(const void *)
+ __attribute__((__bounded__( __minbytes__, 1, 2)));
+void put_u64(void *, u_int64_t)
+ __attribute__((__bounded__( __minbytes__, 1, 8)));
+void put_u32(void *, u_int32_t)
+ __attribute__((__bounded__( __minbytes__, 1, 4)));
+void put_u16(void *, u_int16_t)
+ __attribute__((__bounded__( __minbytes__, 1, 2)));
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/ssh/include/openbsd-compat.h b/usr/src/cmd/ssh/include/openbsd-compat.h
index 7520851248..2cdd3952ab 100644
--- a/usr/src/cmd/ssh/include/openbsd-compat.h
+++ b/usr/src/cmd/ssh/include/openbsd-compat.h
@@ -1,8 +1,34 @@
-/* $Id: openbsd-compat.h,v 1.17 2002/09/12 00:33:02 djm Exp $ */
+/*
+ * Copyright (c) 1999-2003 Damien Miller. All rights reserved.
+ * Copyright (c) 2003 Ben Lindstrom. All rights reserved.
+ * Copyright (c) 2002 Tim Rice. 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.
+ */
#ifndef _OPENBSD_COMPAT_H
#define _OPENBSD_COMPAT_H
+/* $Id: openbsd-compat.h,v 1.17 2002/09/12 00:33:02 djm Exp $ */
+
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
@@ -50,6 +76,10 @@ extern "C" {
#include "port-irix.h"
#include "port-aix.h"
+#ifndef HAVE_VASPRINTF
+int vasprintf(char **, const char *, va_list);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/ssh/include/sftp-int.h b/usr/src/cmd/ssh/include/progressmeter.h
index e02c314206..d8a3bc6737 100644
--- a/usr/src/cmd/ssh/include/sftp-int.h
+++ b/usr/src/cmd/ssh/include/progressmeter.h
@@ -1,17 +1,5 @@
-/* $OpenBSD: sftp-int.h,v 1.5 2002/02/13 00:59:23 djm Exp $ */
-
-#ifndef _SFTP_INT_H
-#define _SFTP_INT_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
/*
- * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
+ * Copyright (c) 2002 Nils Nordman. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,10 +22,22 @@ extern "C" {
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-void interactive_loop(int, int, char *, char *);
+#ifndef _PROGRESSMETER_H
+#define _PROGRESSMETER_H
+
+/* $OpenBSD: progressmeter.h,v 1.2 2006/03/25 22:22:43 djm Exp $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void start_progress_meter(char *, off_t, off_t *);
+void stop_progress_meter(void);
#ifdef __cplusplus
}
#endif
-#endif /* _SFTP_INT_H */
+#endif /* _PROGRESSMETER_H */
diff --git a/usr/src/cmd/ssh/include/sftp-client.h b/usr/src/cmd/ssh/include/sftp-client.h
index 9703c69770..1927e3df16 100644
--- a/usr/src/cmd/ssh/include/sftp-client.h
+++ b/usr/src/cmd/ssh/include/sftp-client.h
@@ -1,7 +1,23 @@
-/* $OpenBSD: sftp-client.h,v 1.11 2002/09/11 22:41:50 djm Exp $ */
+/*
+ * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SFTP_CLIENT_H
+#define _SFTP_CLIENT_H
-#ifndef _SFTP_CLIENT_H
-#define _SFTP_CLIENT_H
+/* $OpenBSD: sftp-client.h,v 1.14 2005/04/26 12:59:02 jmc Exp $ */
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -9,31 +25,6 @@
extern "C" {
#endif
-
-/*
- * Copyright (c) 2001,2002 Damien Miller. 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.
- */
-
/* Client side of SSH2 filexfer protocol */
typedef struct SFTP_DIRENT SFTP_DIRENT;
@@ -45,8 +36,8 @@ struct SFTP_DIRENT {
};
/*
- * Initialiase a SSH filexfer connection. Returns -1 on error or
- * protocol version on success.
+ * Initialise a SSH filexfer connection. Returns NULL on error or
+ * a pointer to a initialized sftp_conn struct on success.
*/
struct sftp_conn *do_init(int, int, u_int, u_int);
diff --git a/usr/src/cmd/ssh/include/sftp-common.h b/usr/src/cmd/ssh/include/sftp-common.h
index 98481cd2a7..86225bc175 100644
--- a/usr/src/cmd/ssh/include/sftp-common.h
+++ b/usr/src/cmd/ssh/include/sftp-common.h
@@ -1,15 +1,3 @@
-/* $OpenBSD: sftp-common.h,v 1.4 2002/09/11 22:41:50 djm Exp $ */
-
-#ifndef _SFTP_COMMON_H
-#define _SFTP_COMMON_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Damien Miller. All rights reserved.
@@ -35,6 +23,20 @@ extern "C" {
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _SFTP_COMMON_H
+#define _SFTP_COMMON_H
+
+/* $OpenBSD: sftp-common.h,v 1.10 2006/08/03 03:34:42 deraadt Exp $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Maximum packet that we are willing to send/accept */
+#define SFTP_MAX_MSG_LENGTH (256 * 1024)
+
typedef struct Attrib Attrib;
/* File attributes */
@@ -49,11 +51,11 @@ struct Attrib {
};
void attrib_clear(Attrib *);
-void stat_to_attrib(struct stat *, Attrib *);
-void attrib_to_stat(Attrib *, struct stat *);
+void stat_to_attrib(const struct stat *, Attrib *);
+void attrib_to_stat(const Attrib *, struct stat *);
Attrib *decode_attrib(Buffer *);
-void encode_attrib(Buffer *, Attrib *);
-char *ls_file(char *, struct stat *, int);
+void encode_attrib(Buffer *, const Attrib *);
+char *ls_file(const char *, const struct stat *, int);
const char *fx2txt(int);
diff --git a/usr/src/cmd/ssh/include/sftp-glob.h b/usr/src/cmd/ssh/include/sftp-glob.h
deleted file mode 100644
index 9d835899ee..0000000000
--- a/usr/src/cmd/ssh/include/sftp-glob.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* $OpenBSD: sftp-glob.h,v 1.8 2002/09/11 22:41:50 djm Exp $ */
-
-#ifndef _SFTP_GLOB_H
-#define _SFTP_GLOB_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
- * Copyright (c) 2001,2002 Damien Miller. 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.
- */
-
-/* Remote sftp filename globbing */
-
-#include "sftp-client.h"
-
-int remote_glob(struct sftp_conn *, const char *, int,
- int (*)(const char *, int), glob_t *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SFTP_GLOB_H */
diff --git a/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com b/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com
index 4528402b14..eb665e83da 100644
--- a/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com
+++ b/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -19,7 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -27,69 +26,70 @@
# cmd/ssh/libopenbsd-compat/Makefile.com
#
-LIBRARY= libopenbsd-compat.a
-VERS= .1
+LIBRARY = libopenbsd-compat.a
+VERS = .1
-OBJECTS= \
- bsd-arc4random.o \
- bsd-cray.o \
- bsd-cygwin_util.o \
- bsd-getpeereid.o \
- bsd-misc.o \
- bsd-nextstep.o \
- bsd-snprintf.o \
- bsd-waitpid.o \
- fake-getaddrinfo.o \
- fake-getnameinfo.o \
- xmmap.o \
- base64.o \
- bindresvport.o \
- daemon.o \
- dirname.o \
- getcwd.o \
- getgrouplist.o \
- getopt.o \
- glob.o \
- inet_aton.o \
- inet_ntoa.o \
- inet_ntop.o \
- mktemp.o \
- readpassphrase.o \
- realpath.o \
- rresvport.o \
- setenv.o \
- setproctitle.o \
- sigact.o \
- strlcat.o \
- strlcpy.o \
- strmode.o \
- strsep.o \
- port-irix.o \
- port-aix.o
+OBJECTS = \
+ bsd-arc4random.o \
+ bsd-cray.o \
+ bsd-cygwin_util.o \
+ bsd-getpeereid.o \
+ bsd-misc.o \
+ bsd-nextstep.o \
+ bsd-asprintf.o \
+ bsd-snprintf.o \
+ bsd-waitpid.o \
+ fake-getaddrinfo.o \
+ fake-getnameinfo.o \
+ xmmap.o \
+ base64.o \
+ bindresvport.o \
+ daemon.o \
+ dirname.o \
+ getcwd.o \
+ getgrouplist.o \
+ getopt.o \
+ glob.o \
+ inet_aton.o \
+ inet_ntoa.o \
+ inet_ntop.o \
+ mktemp.o \
+ readpassphrase.o \
+ realpath.o \
+ rresvport.o \
+ setenv.o \
+ setproctitle.o \
+ sigact.o \
+ strlcat.o \
+ strlcpy.o \
+ strmode.o \
+ strsep.o \
+ port-irix.o \
+ port-aix.o
include $(SRC)/lib/Makefile.lib
-BUILD.AR= $(RM) $@ ; $(AR) $(ARFLAGS) $@ $(AROBJS)
+BUILD.AR = $(RM) $@ ; $(AR) $(ARFLAGS) $@ $(AROBJS)
-SRCDIR= ../common
-SRCS= $(OBJECTS:%.o=../common/%.c)
+SRCDIR = ../common
+SRCS = $(OBJECTS:%.o=../common/%.c)
LIBS = $(LIBRARY) $(LINTLIB)
-$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
-POFILE_DIR= ../..
+POFILE_DIR = ../..
.KEEP_STATE:
-all: $(LIBS)
+all: $(LIBS)
# lint requires the (non-installed) lint library
-lint: $(LINTLIB) .WAIT lintcheck
+lint: $(LINTLIB) .WAIT lintcheck
include $(SRC)/lib/Makefile.targ
-objs/%.o: $(SRCDIR)/%.c
+objs/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
diff --git a/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-asprintf.c b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-asprintf.c
new file mode 100644
index 0000000000..f06e7415de
--- /dev/null
+++ b/usr/src/cmd/ssh/libopenbsd-compat/common/bsd-asprintf.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2004 Darren Tucker.
+ *
+ * Based originally on asprintf.c from OpenBSD:
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "includes.h"
+
+#ifndef HAVE_VASPRINTF
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifndef VA_COPY
+#ifdef HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#else
+#ifdef HAVE___VA_COPY
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#else
+#define VA_COPY(dest, src) (dest) = (src)
+#endif
+#endif
+#endif
+
+#define INIT_SZ 128
+
+int
+vasprintf(char **str, const char *fmt, va_list ap)
+{
+ int ret = -1;
+ va_list ap2;
+ char *string, *newstr;
+ size_t len;
+
+ VA_COPY(ap2, ap);
+ if ((string = malloc(INIT_SZ)) == NULL)
+ goto fail;
+
+ ret = vsnprintf(string, INIT_SZ, fmt, ap2);
+ if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
+ *str = string;
+ } else if (ret == INT_MAX || ret < 0) { /* Bad length */
+ free(string);
+ goto fail;
+ } else { /* bigger than initial, realloc allowing for nul */
+ len = (size_t)ret + 1;
+ if ((newstr = realloc(string, len)) == NULL) {
+ free(string);
+ goto fail;
+ } else {
+ va_end(ap2);
+ VA_COPY(ap2, ap);
+ ret = vsnprintf(newstr, len, fmt, ap2);
+ if (ret >= 0 && (size_t)ret < len) {
+ *str = newstr;
+ } else { /* failed with realloc'ed string, give up */
+ free(newstr);
+ goto fail;
+ }
+ }
+ }
+ va_end(ap2);
+ return (ret);
+
+fail:
+ *str = NULL;
+ errno = ENOMEM;
+ va_end(ap2);
+ return (-1);
+}
+#endif
+
+#ifndef HAVE_ASPRINTF
+int
+asprintf(char **str, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ *str = NULL;
+ va_start(ap, fmt);
+ ret = vasprintf(str, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
+#endif
diff --git a/usr/src/cmd/ssh/libssh/Makefile.com b/usr/src/cmd/ssh/libssh/Makefile.com
index b8f4d30de9..ed02ab1de2 100644
--- a/usr/src/cmd/ssh/libssh/Makefile.com
+++ b/usr/src/cmd/ssh/libssh/Makefile.com
@@ -24,94 +24,95 @@
# ident "%Z%%M% %I% %E% SMI"
#
-LIBRARY= libssh.a
-VERS= .1
+LIBRARY = libssh.a
+VERS = .1
-OBJECTS= \
- atomicio.o \
- authfd.o \
- authfile.o \
- bufaux.o \
- buffer.o \
- canohost.o \
- channels.o \
- cipher.o \
- cipher-ctr.o \
- compat.o \
- compress.o \
- crc32.o \
- deattack.o \
- dh.o \
- dispatch.o \
- fatal.o \
- g11n.o \
- mac.o \
- msg.o \
- hostfile.o \
- key.o \
- kex.o \
- kexdh.o \
- kexdhc.o \
- kexdhs.o \
- kexgex.o \
- kexgexc.o \
- kexgexs.o \
- kexgssc.o \
- kexgsss.o \
- log.o \
- match.o \
- misc.o \
- mpaux.o \
- nchan.o \
- packet.o \
- radix.o \
- entropy.o \
- readpass.o \
- rsa.o \
- scard.o \
- scard-opensc.o \
- ssh-dss.o \
- ssh-gss.o \
- ssh-rsa.o \
- tildexpand.o \
- ttymodes.o \
- uidswap.o \
- uuencode.o \
- xlist.o \
- xmalloc.o \
- monitor_wrap.o \
- monitor_fdpass.o \
- readconf.o \
- sftp-common.o \
- proxy-io.o
+OBJECTS = \
+ atomicio.o \
+ authfd.o \
+ authfile.o \
+ bufaux.o \
+ buffer.o \
+ canohost.o \
+ channels.o \
+ cipher.o \
+ cipher-ctr.o \
+ compat.o \
+ compress.o \
+ crc32.o \
+ deattack.o \
+ dh.o \
+ dispatch.o \
+ fatal.o \
+ g11n.o \
+ mac.o \
+ msg.o \
+ hostfile.o \
+ key.o \
+ kex.o \
+ kexdh.o \
+ kexdhc.o \
+ kexdhs.o \
+ kexgex.o \
+ kexgexc.o \
+ kexgexs.o \
+ kexgssc.o \
+ kexgsss.o \
+ log.o \
+ match.o \
+ misc.o \
+ mpaux.o \
+ nchan.o \
+ packet.o \
+ progressmeter.o \
+ radix.o \
+ entropy.o \
+ readpass.o \
+ rsa.o \
+ scard.o \
+ scard-opensc.o \
+ ssh-dss.o \
+ ssh-gss.o \
+ ssh-rsa.o \
+ tildexpand.o \
+ ttymodes.o \
+ uidswap.o \
+ uuencode.o \
+ xlist.o \
+ xmalloc.o \
+ monitor_wrap.o \
+ monitor_fdpass.o \
+ readconf.o \
+ sftp-common.o \
+ proxy-io.o
include $(SRC)/lib/Makefile.lib
-BUILD.AR= $(RM) $@ ; $(AR) $(ARFLAGS) $@ $(AROBJS)
+BUILD.AR = $(RM) $@ ; $(AR) $(ARFLAGS) $@ $(AROBJS)
-SRCDIR= ../common
-SRCS= $(OBJECTS:%.o=../common/%.c)
+SRCDIR = ../common
+SRCS = $(OBJECTS:%.o=../common/%.c)
LIBS = $(LIBRARY) $(LINTLIB)
# definitions for lint
# Until libz is compiled against unsigned uid/gid ON bits.
-#LINTFLAGS += $(OPENSSL_LDFLAGS) -lcrypto -lz -lsocket -lnsl -lc
-LINTFLAGS += $(OPENSSL_LDFLAGS) -lcrypto -lsocket -lnsl -lc
-$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+#LINTFLAGS += $(OPENSSL_LDFLAGS) -lcrypto -lz -lsocket -lnsl -lc
+LINTFLAGS += $(OPENSSL_LDFLAGS) -lcrypto -lsocket -lnsl -lc
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
-POFILE_DIR= ../..
+POFILE_DIR = ../..
.KEEP_STATE:
-all: $(LIBS)
+all: $(LIBS)
# lint requires the (not installed) lint library
-lint: $(LINTLIB) .WAIT lintcheck
+lint: $(LINTLIB) .WAIT lintcheck
include $(SRC)/lib/Makefile.targ
-objs/%.o: $(SRCDIR)/%.c
+objs/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
diff --git a/usr/src/cmd/ssh/libssh/common/atomicio.c b/usr/src/cmd/ssh/libssh/common/atomicio.c
index 806876e24e..f4a7945702 100644
--- a/usr/src/cmd/ssh/libssh/common/atomicio.c
+++ b/usr/src/cmd/ssh/libssh/common/atomicio.c
@@ -1,4 +1,6 @@
/*
+ * Copyright (c) 2006 Damien Miller. All rights reserved.
+ * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
@@ -62,3 +64,55 @@ atomicio(f, fd, _s, n)
}
return (pos);
}
+
+/*
+ * ensure all of data on socket comes through. f==readv || f==writev
+ */
+size_t
+atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
+ const struct iovec *_iov, int iovcnt)
+{
+ size_t pos = 0, rem;
+ ssize_t res;
+ struct iovec iov_array[IOV_MAX], *iov = iov_array;
+
+ if (iovcnt > IOV_MAX) {
+ errno = EINVAL;
+ return 0;
+ }
+ /* Make a copy of the iov array because we may modify it below */
+ memcpy(iov, _iov, iovcnt * sizeof(*_iov));
+
+ for (; iovcnt > 0 && iov[0].iov_len > 0;) {
+ res = (f) (fd, iov, iovcnt);
+ switch (res) {
+ case -1:
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return 0;
+ case 0:
+ errno = EPIPE;
+ return pos;
+ default:
+ rem = (size_t)res;
+ pos += rem;
+ /* skip completed iov entries */
+ while (iovcnt > 0 && rem >= iov[0].iov_len) {
+ rem -= iov[0].iov_len;
+ iov++;
+ iovcnt--;
+ }
+ /* This shouldn't happen... */
+ if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) {
+ errno = EFAULT;
+ return 0;
+ }
+ if (iovcnt == 0)
+ break;
+ /* update pointer in partially complete iov */
+ iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
+ iov[0].iov_len -= rem;
+ }
+ }
+ return pos;
+}
diff --git a/usr/src/cmd/ssh/libssh/common/buffer.c b/usr/src/cmd/ssh/libssh/common/buffer.c
index 9d95851d68..45d6860157 100644
--- a/usr/src/cmd/ssh/libssh/common/buffer.c
+++ b/usr/src/cmd/ssh/libssh/common/buffer.c
@@ -11,15 +11,20 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-#include "includes.h"
-RCSID("$OpenBSD: buffer.c,v 1.23 2005/03/14 11:46:56 markus Exp $");
+/* $OpenBSD: buffer.c,v 1.31 2006/08/03 03:34:41 deraadt Exp $ */
#pragma ident "%Z%%M% %I% %E% SMI"
+#include "includes.h"
+
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
+#define BUFFER_MAX_CHUNK 0x100000
+#define BUFFER_MAX_LEN 0xa00000
+#define BUFFER_ALLOCSZ 0x008000
+
/* Initializes the buffer structure. */
void
@@ -68,6 +73,23 @@ buffer_append(Buffer *buffer, const void *data, u_int len)
memcpy(p, data, len);
}
+static int
+buffer_compact(Buffer *buffer)
+{
+ /*
+ * If the buffer is quite empty, but all data is at the end, move the
+ * data to the beginning.
+ */
+ if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {
+ memmove(buffer->buf, buffer->buf + buffer->offset,
+ buffer->end - buffer->offset);
+ buffer->end -= buffer->offset;
+ buffer->offset = 0;
+ return (1);
+ }
+ return (0);
+}
+
/*
* Appends space to the buffer, expanding the buffer if necessary. This does
* not actually copy the data into the buffer, but instead returns a pointer
@@ -95,20 +117,13 @@ restart:
buffer->end += len;
return p;
}
- /*
- * If the buffer is quite empty, but all data is at the end, move the
- * data to the beginning and retry.
- */
- if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {
- memmove(buffer->buf, buffer->buf + buffer->offset,
- buffer->end - buffer->offset);
- buffer->end -= buffer->offset;
- buffer->offset = 0;
+
+ /* Compact data back to the start of the buffer if necessary */
+ if (buffer_compact(buffer))
goto restart;
- }
+
/* Increase the size of the buffer and retry. */
-
- newlen = buffer->alloc + len + 32768;
+ newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
if (newlen > BUFFER_MAX_LEN)
fatal("buffer_append_space: alloc %u not supported",
newlen);
@@ -118,6 +133,27 @@ restart:
/* NOTREACHED */
}
+/*
+ * Check whether an allocation of 'len' will fit in the buffer
+ * This must follow the same math as buffer_append_space
+ */
+int
+buffer_check_alloc(Buffer *buffer, u_int len)
+{
+ if (buffer->offset == buffer->end) {
+ buffer->offset = 0;
+ buffer->end = 0;
+ }
+ restart:
+ if (buffer->end + len < buffer->alloc)
+ return (1);
+ if (buffer_compact(buffer))
+ goto restart;
+ if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
+ return (1);
+ return (0);
+}
+
/* Returns the number of bytes of data in the buffer. */
u_int
diff --git a/usr/src/cmd/ssh/libssh/common/llib-lssh b/usr/src/cmd/ssh/libssh/common/llib-lssh
index 321ed7d2e3..f827580891 100644
--- a/usr/src/cmd/ssh/libssh/common/llib-lssh
+++ b/usr/src/cmd/ssh/libssh/common/llib-lssh
@@ -5,9 +5,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -22,7 +21,7 @@
*
* CDDL HEADER END
*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -110,8 +109,6 @@
#include <setproctitle.h>
#include <sftp-common.h>
#include <sftp.h>
-#include <sftp-int.h>
-#include <sftp-glob.h>
#include <sftp-client.h>
#include <sigact.h>
#include <ssh1.h>
diff --git a/usr/src/cmd/ssh/libssh/common/misc.c b/usr/src/cmd/ssh/libssh/common/misc.c
index 9fe8d8c1b8..21b683c3cd 100644
--- a/usr/src/cmd/ssh/libssh/common/misc.c
+++ b/usr/src/cmd/ssh/libssh/common/misc.c
@@ -363,6 +363,26 @@ addargs(arglist *args, char *fmt, ...)
}
void
+replacearg(arglist *args, u_int which, char *fmt, ...)
+{
+ va_list ap;
+ char *cp;
+ int r;
+
+ va_start(ap, fmt);
+ r = vasprintf(&cp, fmt, ap);
+ va_end(ap);
+ if (r == -1)
+ fatal("replacearg: argument too long");
+
+ if (which >= args->num)
+ fatal("replacearg: tried to replace invalid arg %d >= %d",
+ which, args->num);
+ xfree(args->list[which]);
+ args->list[which] = cp;
+}
+
+void
freeargs(arglist *args)
{
u_int i;
@@ -376,6 +396,32 @@ freeargs(arglist *args)
}
}
+/*
+ * Ensure that file descriptors 0, 1 and 2 are open or directed to /dev/null,
+ * do not touch those that are already open.
+ */
+void
+sanitise_stdfd(void)
+{
+ int nullfd, dupfd;
+
+ if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
+ exit(1);
+ }
+ while (++dupfd <= 2) {
+ /* Only clobber closed fds */
+ if (fcntl(dupfd, F_GETFL, 0) >= 0)
+ continue;
+ if (dup2(nullfd, dupfd) == -1) {
+ fprintf(stderr, "dup2: %s", strerror(errno));
+ exit(1);
+ }
+ }
+ if (nullfd > 2)
+ close(nullfd);
+}
+
char *
tohex(const void *vp, size_t l)
{
@@ -395,6 +441,86 @@ tohex(const void *vp, size_t l)
return (r);
}
+u_int64_t
+get_u64(const void *vp)
+{
+ const u_char *p = (const u_char *)vp;
+ u_int64_t v;
+
+ v = (u_int64_t)p[0] << 56;
+ v |= (u_int64_t)p[1] << 48;
+ v |= (u_int64_t)p[2] << 40;
+ v |= (u_int64_t)p[3] << 32;
+ v |= (u_int64_t)p[4] << 24;
+ v |= (u_int64_t)p[5] << 16;
+ v |= (u_int64_t)p[6] << 8;
+ v |= (u_int64_t)p[7];
+
+ return (v);
+}
+
+u_int32_t
+get_u32(const void *vp)
+{
+ const u_char *p = (const u_char *)vp;
+ u_int32_t v;
+
+ v = (u_int32_t)p[0] << 24;
+ v |= (u_int32_t)p[1] << 16;
+ v |= (u_int32_t)p[2] << 8;
+ v |= (u_int32_t)p[3];
+
+ return (v);
+}
+
+u_int16_t
+get_u16(const void *vp)
+{
+ const u_char *p = (const u_char *)vp;
+ u_int16_t v;
+
+ v = (u_int16_t)p[0] << 8;
+ v |= (u_int16_t)p[1];
+
+ return (v);
+}
+
+void
+put_u64(void *vp, u_int64_t v)
+{
+ u_char *p = (u_char *)vp;
+
+ p[0] = (u_char)(v >> 56) & 0xff;
+ p[1] = (u_char)(v >> 48) & 0xff;
+ p[2] = (u_char)(v >> 40) & 0xff;
+ p[3] = (u_char)(v >> 32) & 0xff;
+ p[4] = (u_char)(v >> 24) & 0xff;
+ p[5] = (u_char)(v >> 16) & 0xff;
+ p[6] = (u_char)(v >> 8) & 0xff;
+ p[7] = (u_char)v & 0xff;
+}
+
+void
+put_u32(void *vp, u_int32_t v)
+{
+ u_char *p = (u_char *)vp;
+
+ p[0] = (u_char)(v >> 24) & 0xff;
+ p[1] = (u_char)(v >> 16) & 0xff;
+ p[2] = (u_char)(v >> 8) & 0xff;
+ p[3] = (u_char)v & 0xff;
+}
+
+
+void
+put_u16(void *vp, u_int16_t v)
+{
+ u_char *p = (u_char *)vp;
+
+ p[0] = (u_char)(v >> 8) & 0xff;
+ p[1] = (u_char)v & 0xff;
+}
+
mysig_t
mysignal(int sig, mysig_t act)
{
diff --git a/usr/src/cmd/ssh/libssh/common/progressmeter.c b/usr/src/cmd/ssh/libssh/common/progressmeter.c
new file mode 100644
index 0000000000..65d28fb596
--- /dev/null
+++ b/usr/src/cmd/ssh/libssh/common/progressmeter.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2003 Nils Nordman. 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.
+ */
+
+/* $OpenBSD: progressmeter.c,v 1.37 2006/08/03 03:34:42 deraadt Exp $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "progressmeter.h"
+#include "atomicio.h"
+#include "misc.h"
+
+#define DEFAULT_WINSIZE 80
+#define MAX_WINSIZE 512
+#define PADDING 1 /* padding between the progress indicators */
+#define UPDATE_INTERVAL 1 /* update the progress meter every second */
+#define STALL_TIME 5 /* we're stalled after this many seconds */
+
+/* determines whether we can output to the terminal */
+static int can_output(void);
+
+/* formats and inserts the specified size into the given buffer */
+static void format_size(char *, int, off_t);
+static void format_rate(char *, int, off_t);
+
+/* window resizing */
+static void sig_winch(int);
+static void setscreensize(void);
+
+/* updates the progressmeter to reflect the current state of the transfer */
+void refresh_progress_meter(void);
+
+/* signal handler for updating the progress meter */
+static void update_progress_meter(int);
+
+static time_t start; /* start progress */
+static time_t last_update; /* last progress update */
+static char *file; /* name of the file being transferred */
+static off_t end_pos; /* ending position of transfer */
+static off_t cur_pos; /* transfer position as of last refresh */
+static volatile off_t *counter; /* progress counter */
+static long stalled; /* how long we have been stalled */
+static int bytes_per_second; /* current speed in bytes per second */
+static int win_size; /* terminal window size */
+static volatile sig_atomic_t win_resized; /* for window resizing */
+
+/* units for format_size */
+static const char unit[] = " KMGT";
+
+static int
+can_output(void)
+{
+ return (getpgrp() == tcgetpgrp(STDOUT_FILENO));
+}
+
+static void
+format_rate(char *buf, int size, off_t bytes)
+{
+ int i;
+
+ bytes *= 100;
+ for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++)
+ bytes = (bytes + 512) / 1024;
+ if (i == 0) {
+ i++;
+ bytes = (bytes + 512) / 1024;
+ }
+ snprintf(buf, size, "%3lld.%1lld%c%s",
+ (long long) (bytes + 5) / 100,
+ (long long) (bytes + 5) / 10 % 10,
+ unit[i],
+ i ? "B" : " ");
+}
+
+static void
+format_size(char *buf, int size, off_t bytes)
+{
+ int i;
+
+ for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
+ bytes = (bytes + 512) / 1024;
+ snprintf(buf, size, "%4lld%c%s",
+ (long long) bytes,
+ unit[i],
+ i ? "B" : " ");
+}
+
+void
+refresh_progress_meter(void)
+{
+ char buf[MAX_WINSIZE + 1];
+ time_t now;
+ off_t transferred;
+ double elapsed;
+ int percent;
+ off_t bytes_left;
+ int cur_speed;
+ int hours, minutes, seconds;
+ int i, len;
+ int file_len;
+
+ transferred = *counter - cur_pos;
+ cur_pos = *counter;
+ now = time(NULL);
+ bytes_left = end_pos - cur_pos;
+
+ if (bytes_left > 0)
+ elapsed = now - last_update;
+ else {
+ elapsed = now - start;
+ /* Calculate true total speed when done */
+ transferred = end_pos;
+ bytes_per_second = 0;
+ }
+
+ /* calculate speed */
+ if (elapsed != 0)
+ cur_speed = (int)(transferred / elapsed);
+ else
+ cur_speed = transferred;
+
+#define AGE_FACTOR 0.9
+ if (bytes_per_second != 0) {
+ bytes_per_second = (int)((bytes_per_second * AGE_FACTOR) +
+ (cur_speed * (1.0 - AGE_FACTOR)));
+ } else
+ bytes_per_second = cur_speed;
+
+ /* filename */
+ buf[0] = '\0';
+ file_len = win_size - 35;
+ if (file_len > 0) {
+ len = snprintf(buf, file_len + 1, "\r%s", file);
+ if (len < 0)
+ len = 0;
+ if (len >= file_len + 1)
+ len = file_len;
+ for (i = len; i < file_len; i++)
+ buf[i] = ' ';
+ buf[file_len] = '\0';
+ }
+
+ /* percent of transfer done */
+ if (end_pos != 0)
+ percent = (int)(((float)cur_pos / end_pos) * 100);
+ else
+ percent = 100;
+ snprintf(buf + strlen(buf), win_size - strlen(buf),
+ " %3d%% ", percent);
+
+ /* amount transferred */
+ format_size(buf + strlen(buf), win_size - strlen(buf),
+ cur_pos);
+ strlcat(buf, " ", win_size);
+
+ /* bandwidth usage */
+ format_rate(buf + strlen(buf), win_size - strlen(buf),
+ (off_t)bytes_per_second);
+ strlcat(buf, "/s ", win_size);
+
+ /* ETA */
+ if (!transferred)
+ stalled += elapsed;
+ else
+ stalled = 0;
+
+ if (stalled >= STALL_TIME)
+ strlcat(buf, "- stalled -", win_size);
+ else if (bytes_per_second == 0 && bytes_left)
+ strlcat(buf, " --:-- ETA", win_size);
+ else {
+ if (bytes_left > 0)
+ seconds = bytes_left / bytes_per_second;
+ else
+ seconds = (int)elapsed;
+
+ hours = seconds / 3600;
+ seconds -= hours * 3600;
+ minutes = seconds / 60;
+ seconds -= minutes * 60;
+
+ if (hours != 0)
+ snprintf(buf + strlen(buf), win_size - strlen(buf),
+ "%d:%02d:%02d", hours, minutes, seconds);
+ else
+ snprintf(buf + strlen(buf), win_size - strlen(buf),
+ " %02d:%02d", minutes, seconds);
+
+ if (bytes_left > 0)
+ strlcat(buf, " ETA", win_size);
+ else
+ strlcat(buf, " ", win_size);
+ }
+
+ atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
+ last_update = now;
+}
+
+/*ARGSUSED*/
+static void
+update_progress_meter(int ignore)
+{
+ int save_errno;
+
+ save_errno = errno;
+
+ if (win_resized) {
+ setscreensize();
+ win_resized = 0;
+ }
+ if (can_output())
+ refresh_progress_meter();
+
+ signal(SIGALRM, update_progress_meter);
+ alarm(UPDATE_INTERVAL);
+ errno = save_errno;
+}
+
+void
+start_progress_meter(char *f, off_t filesize, off_t *ctr)
+{
+ start = last_update = time(NULL);
+ file = f;
+ end_pos = filesize;
+ cur_pos = 0;
+ counter = ctr;
+ stalled = 0;
+ bytes_per_second = 0;
+
+ setscreensize();
+ if (can_output())
+ refresh_progress_meter();
+
+ signal(SIGALRM, update_progress_meter);
+ signal(SIGWINCH, sig_winch);
+ alarm(UPDATE_INTERVAL);
+}
+
+void
+stop_progress_meter(void)
+{
+ alarm(0);
+
+ if (!can_output())
+ return;
+
+ /* Ensure we complete the progress */
+ if (cur_pos != end_pos)
+ refresh_progress_meter();
+
+ atomicio(vwrite, STDOUT_FILENO, "\n", 1);
+}
+
+/*ARGSUSED*/
+static void
+sig_winch(int sig)
+{
+ win_resized = 1;
+}
+
+static void
+setscreensize(void)
+{
+ struct winsize winsize;
+
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
+ winsize.ws_col != 0) {
+ if (winsize.ws_col > MAX_WINSIZE)
+ win_size = MAX_WINSIZE;
+ else
+ win_size = winsize.ws_col;
+ } else
+ win_size = DEFAULT_WINSIZE;
+ win_size += 1; /* trailing \0 */
+}
diff --git a/usr/src/cmd/ssh/libssh/common/sftp-common.c b/usr/src/cmd/ssh/libssh/common/sftp-common.c
index 7cbe72c44c..ead9e2406f 100644
--- a/usr/src/cmd/ssh/libssh/common/sftp-common.c
+++ b/usr/src/cmd/ssh/libssh/common/sftp-common.c
@@ -23,15 +23,27 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "includes.h"
-RCSID("$OpenBSD: sftp-common.c,v 1.7 2002/09/11 22:41:50 djm Exp $");
+/* $OpenBSD: sftp-common.c,v 1.20 2006/08/03 03:34:42 deraadt Exp $ */
#pragma ident "%Z%%M% %I% %E% SMI"
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+
+#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include "log.h"
-#include "xmalloc.h"
#include "sftp.h"
#include "sftp-common.h"
@@ -51,7 +63,7 @@ attrib_clear(Attrib *a)
/* Convert from struct stat to filexfer attribs */
void
-stat_to_attrib(struct stat *st, Attrib *a)
+stat_to_attrib(const struct stat *st, Attrib *a)
{
attrib_clear(a);
a->flags = 0;
@@ -69,7 +81,7 @@ stat_to_attrib(struct stat *st, Attrib *a)
/* Convert from filexfer attribs to struct stat */
void
-attrib_to_stat(Attrib *a, struct stat *st)
+attrib_to_stat(const Attrib *a, struct stat *st)
{
memset(st, 0, sizeof(*st));
@@ -126,7 +138,7 @@ decode_attrib(Buffer *b)
/* Encode attributes to buffer */
void
-encode_attrib(Buffer *b, Attrib *a)
+encode_attrib(Buffer *b, const Attrib *a)
{
buffer_put_int(b, a->flags);
if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
@@ -149,25 +161,25 @@ fx2txt(int status)
{
switch (status) {
case SSH2_FX_OK:
- return("No error");
+ return(gettext("No error"));
case SSH2_FX_EOF:
- return("End of file");
+ return(gettext("End of file"));
case SSH2_FX_NO_SUCH_FILE:
- return("No such file or directory");
+ return(gettext("No such file or directory"));
case SSH2_FX_PERMISSION_DENIED:
- return("Permission denied");
+ return(gettext("Permission denied"));
case SSH2_FX_FAILURE:
- return("Failure");
+ return(gettext("Failure"));
case SSH2_FX_BAD_MESSAGE:
- return("Bad message");
+ return(gettext("Bad message"));
case SSH2_FX_NO_CONNECTION:
- return("No connection");
+ return(gettext("No connection"));
case SSH2_FX_CONNECTION_LOST:
- return("Connection lost");
+ return(gettext("Connection lost"));
case SSH2_FX_OP_UNSUPPORTED:
- return("Operation unsupported");
+ return(gettext("Operation unsupported"));
default:
- return("Unknown status");
+ return(gettext("Unknown status"));
}
/* NOTREACHED */
}
@@ -176,7 +188,7 @@ fx2txt(int status)
* drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
*/
char *
-ls_file(char *name, struct stat *st, int remote)
+ls_file(const char *name, const struct stat *st, int remote)
{
int ulen, glen, sz = 0;
struct passwd *pw;
@@ -208,8 +220,8 @@ ls_file(char *name, struct stat *st, int remote)
tbuf[0] = '\0';
ulen = MAX(strlen(user), 8);
glen = MAX(strlen(group), 8);
- snprintf(buf, sizeof buf, "%s %3d %-*s %-*s %8llu %s %s", mode,
- st->st_nlink, ulen, user, glen, group,
- (u_int64_t)st->st_size, tbuf, name);
+ snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode,
+ (u_int)st->st_nlink, ulen, user, glen, group,
+ (unsigned long long)st->st_size, tbuf, name);
return xstrdup(buf);
}
diff --git a/usr/src/cmd/ssh/sftp-server/Makefile b/usr/src/cmd/ssh/sftp-server/Makefile
index 491b0f44b2..4743387ab4 100644
--- a/usr/src/cmd/ssh/sftp-server/Makefile
+++ b/usr/src/cmd/ssh/sftp-server/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -19,43 +18,43 @@
#
# CDDL HEADER END
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
# cmd/ssh/sftp-server/Makefile
-PROG= sftp-server
+PROG = sftp-server
-OBJS = sftp-server.o
-SRCS = $(OBJS:.o=.c)
+OBJS = sftp-server.o
+SRCS = $(OBJS:.o=.c)
include ../../Makefile.cmd
include ../Makefile.ssh-common
-LDLIBS += $(SSH_COMMON_LDLIBS) $(OPENSSL_LDFLAGS) -lcrypto
+LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket $(OPENSSL_LDFLAGS) -lcrypto
-DYNFLAGS += $(OPENSSL_DYNFLAGS)
+DYNFLAGS += $(OPENSSL_DYNFLAGS)
-POFILE_DIR= ..
+POFILE_DIR = ..
.KEEP_STATE:
-.PARALLEL: $(OBJS)
+.PARALLEL: $(OBJS)
-all: $(PROG)
+all: $(PROG)
-$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a
+$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a
$(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS)
$(POST_PROCESS)
-install: all $(ROOTLIBSSHPROG) $(ROOTLIBSSH)
+install: all $(ROOTLIBSSHPROG) $(ROOTLIBSSH)
clean:
$(RM) -f $(OBJS) $(PROG)
-lint: lint_SRCS
+lint: lint_SRCS
include ../Makefile.msg.targ
include ../../Makefile.targ
diff --git a/usr/src/cmd/ssh/sftp-server/sftp-server.c b/usr/src/cmd/ssh/sftp-server/sftp-server.c
index 6897c1c930..aeef13d013 100644
--- a/usr/src/cmd/ssh/sftp-server/sftp-server.c
+++ b/usr/src/cmd/ssh/sftp-server/sftp-server.c
@@ -1,57 +1,74 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
+ * Copyright (c) 2000-2004 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.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "includes.h"
-RCSID("$OpenBSD: sftp-server.c,v 1.38 2002/09/11 22:41:50 djm Exp $");
+
+/* $OpenBSD: sftp-server.c,v 1.71 2007/01/03 07:22:36 stevesk Exp $ */
#pragma ident "%Z%%M% %I% %E% SMI"
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
-#include "getput.h"
#include "log.h"
-#include "xmalloc.h"
+#include "misc.h"
+#include "uidswap.h"
#include "sftp.h"
#include "sftp-common.h"
-/* helper */
-#define get_int64() buffer_get_int64(&iqueue);
-#define get_int() buffer_get_int(&iqueue);
-#define get_string(lenp) buffer_get_string(&iqueue, lenp);
-#define TRACE debug
-
#ifdef HAVE___PROGNAME
extern char *__progname;
#else
char *__progname;
#endif
+/* helper */
+#define get_int64() buffer_get_int64(&iqueue);
+#define get_int() buffer_get_int(&iqueue);
+#define get_string(lenp) buffer_get_string(&iqueue, lenp);
+
+static void cleanup_exit(int i);
+
+/* Our verbosity */
+LogLevel log_level = SYSLOG_LEVEL_ERROR;
+
+/* Our client */
+struct passwd *pw = NULL;
+char *client_addr = NULL;
+
/* input and output queue */
Buffer iqueue;
Buffer oqueue;
@@ -59,7 +76,7 @@ Buffer oqueue;
/* Version of client */
int version;
-/* portable attibutes, etc. */
+/* portable attributes, etc. */
typedef struct Stat Stat;
@@ -122,6 +139,33 @@ flags_from_portable(int pflags)
return flags;
}
+static const char *
+string_from_portable(int pflags)
+{
+ static char ret[128];
+
+ *ret = '\0';
+
+#define PAPPEND(str) { \
+ if (*ret != '\0') \
+ strlcat(ret, ",", sizeof(ret)); \
+ strlcat(ret, str, sizeof(ret)); \
+ }
+
+ if (pflags & SSH2_FXF_READ)
+ PAPPEND("READ")
+ if (pflags & SSH2_FXF_WRITE)
+ PAPPEND("WRITE")
+ if (pflags & SSH2_FXF_CREAT)
+ PAPPEND("CREATE")
+ if (pflags & SSH2_FXF_TRUNC)
+ PAPPEND("TRUNCATE")
+ if (pflags & SSH2_FXF_EXCL)
+ PAPPEND("EXCL")
+
+ return ret;
+}
+
static Attrib *
get_attrib(void)
{
@@ -136,6 +180,7 @@ struct Handle {
DIR *dirp;
int fd;
char *name;
+ u_int64_t bytes_read, bytes_write;
};
enum {
@@ -149,23 +194,24 @@ Handle handles[100];
static void
handle_init(void)
{
- int i;
+ u_int i;
for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
handles[i].use = HANDLE_UNUSED;
}
static int
-handle_new(int use, char *name, int fd, DIR *dirp)
+handle_new(int use, const char *name, int fd, DIR *dirp)
{
- int i;
+ u_int i;
for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) {
if (handles[i].use == HANDLE_UNUSED) {
handles[i].use = use;
handles[i].dirp = dirp;
handles[i].fd = fd;
- handles[i].name = name;
+ handles[i].name = xstrdup(name);
+ handles[i].bytes_read = handles[i].bytes_write = 0;
return i;
}
}
@@ -175,7 +221,7 @@ handle_new(int use, char *name, int fd, DIR *dirp)
static int
handle_is_ok(int i, int type)
{
- return i >= 0 && i < sizeof(handles)/sizeof(Handle) &&
+ return i >= 0 && (u_int)i < sizeof(handles)/sizeof(Handle) &&
handles[i].use == type;
}
@@ -185,19 +231,19 @@ handle_to_string(int handle, char **stringp, int *hlenp)
if (stringp == NULL || hlenp == NULL)
return -1;
*stringp = xmalloc(sizeof(int32_t));
- PUT_32BIT(*stringp, handle);
+ put_u32(*stringp, handle);
*hlenp = sizeof(int32_t);
return 0;
}
static int
-handle_from_string(char *handle, u_int hlen)
+handle_from_string(const char *handle, u_int hlen)
{
int val;
if (hlen != sizeof(int32_t))
return -1;
- val = GET_32BIT(handle);
+ val = get_u32(handle);
if (handle_is_ok(val, HANDLE_FILE) ||
handle_is_ok(val, HANDLE_DIR))
return val;
@@ -229,6 +275,36 @@ handle_to_fd(int handle)
return -1;
}
+static void
+handle_update_read(int handle, ssize_t bytes)
+{
+ if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
+ handles[handle].bytes_read += bytes;
+}
+
+static void
+handle_update_write(int handle, ssize_t bytes)
+{
+ if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
+ handles[handle].bytes_write += bytes;
+}
+
+static u_int64_t
+handle_bytes_read(int handle)
+{
+ if (handle_is_ok(handle, HANDLE_FILE))
+ return (handles[handle].bytes_read);
+ return 0;
+}
+
+static u_int64_t
+handle_bytes_write(int handle)
+{
+ if (handle_is_ok(handle, HANDLE_FILE))
+ return (handles[handle].bytes_write);
+ return 0;
+}
+
static int
handle_close(int handle)
{
@@ -237,15 +313,43 @@ handle_close(int handle)
if (handle_is_ok(handle, HANDLE_FILE)) {
ret = close(handles[handle].fd);
handles[handle].use = HANDLE_UNUSED;
+ xfree(handles[handle].name);
} else if (handle_is_ok(handle, HANDLE_DIR)) {
ret = closedir(handles[handle].dirp);
handles[handle].use = HANDLE_UNUSED;
+ xfree(handles[handle].name);
} else {
errno = ENOENT;
}
return ret;
}
+static void
+handle_log_close(int handle, char *emsg)
+{
+ if (handle_is_ok(handle, HANDLE_FILE)) {
+ log("%s%sclose \"%s\" bytes read %llu written %llu",
+ emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
+ handle_to_name(handle),
+ (unsigned long long)handle_bytes_read(handle),
+ (unsigned long long)handle_bytes_write(handle));
+ } else {
+ log("%s%sclosedir \"%s\"",
+ emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
+ handle_to_name(handle));
+ }
+}
+
+static void
+handle_log_exit(void)
+{
+ u_int i;
+
+ for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
+ if (handles[i].use != HANDLE_UNUSED)
+ handle_log_close(i, "forced");
+}
+
static int
get_handle(void)
{
@@ -272,10 +376,9 @@ send_msg(Buffer *m)
buffer_consume(m, mlen);
}
-static void
-send_status(u_int32_t id, u_int32_t error)
+static const char *
+status_to_message(u_int32_t status)
{
- Buffer msg;
const char *status_messages[] = {
"Success", /* SSH_FX_OK */
"End of file", /* SSH_FX_EOF */
@@ -288,22 +391,31 @@ send_status(u_int32_t id, u_int32_t error)
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
"Unknown error" /* Others */
};
+ return (status_messages[MIN(status,SSH2_FX_MAX)]);
+}
+
+static void
+send_status(u_int32_t id, u_int32_t status)
+{
+ Buffer msg;
- TRACE("sent status id %u error %u", id, error);
+ debug3("request %u: sent status %u", id, status);
+ if (log_level > SYSLOG_LEVEL_VERBOSE ||
+ (status != SSH2_FX_OK && status != SSH2_FX_EOF))
+ log("sent status %s", status_to_message(status));
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_STATUS);
buffer_put_int(&msg, id);
- buffer_put_int(&msg, error);
+ buffer_put_int(&msg, status);
if (version >= 3) {
- buffer_put_cstring(&msg,
- status_messages[MIN(error,SSH2_FX_MAX)]);
+ buffer_put_cstring(&msg, status_to_message(status));
buffer_put_cstring(&msg, "");
}
send_msg(&msg);
buffer_free(&msg);
}
static void
-send_data_or_handle(char type, u_int32_t id, char *data, int dlen)
+send_data_or_handle(char type, u_int32_t id, const char *data, int dlen)
{
Buffer msg;
@@ -316,9 +428,9 @@ send_data_or_handle(char type, u_int32_t id, char *data, int dlen)
}
static void
-send_data(u_int32_t id, char *data, int dlen)
+send_data(u_int32_t id, const char *data, int dlen)
{
- TRACE("sent data id %u len %d", id, dlen);
+ debug("request %u: sent data len %d", id, dlen);
send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
}
@@ -329,13 +441,13 @@ send_handle(u_int32_t id, int handle)
int hlen;
handle_to_string(handle, &string, &hlen);
- TRACE("sent handle id %u handle %d", id, handle);
+ debug("request %u: sent handle handle %d", id, handle);
send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
xfree(string);
}
static void
-send_names(u_int32_t id, int count, Stat *stats)
+send_names(u_int32_t id, int count, const Stat *stats)
{
Buffer msg;
int i;
@@ -344,7 +456,7 @@ send_names(u_int32_t id, int count, Stat *stats)
buffer_put_char(&msg, SSH2_FXP_NAME);
buffer_put_int(&msg, id);
buffer_put_int(&msg, count);
- TRACE("sent names id %u count %d", id, count);
+ debug("request %u: sent names count %d", id, count);
for (i = 0; i < count; i++) {
buffer_put_cstring(&msg, stats[i].name);
buffer_put_cstring(&msg, stats[i].long_name);
@@ -355,11 +467,11 @@ send_names(u_int32_t id, int count, Stat *stats)
}
static void
-send_attrib(u_int32_t id, Attrib *a)
+send_attrib(u_int32_t id, const Attrib *a)
{
Buffer msg;
- TRACE("sent attrib id %u have 0x%x", id, a->flags);
+ debug("request %u: sent attrib have 0x%x", id, a->flags);
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_ATTRS);
buffer_put_int(&msg, id);
@@ -376,7 +488,7 @@ process_init(void)
Buffer msg;
version = get_int();
- TRACE("client version %d", version);
+ verbose("received client version %d", version);
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_VERSION);
buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
@@ -395,15 +507,17 @@ process_open(void)
id = get_int();
name = get_string(NULL);
pflags = get_int(); /* portable flags */
+ debug3("request %u: open flags %d", id, pflags);
a = get_attrib();
flags = flags_from_portable(pflags);
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
- TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode);
+ log("open \"%s\" flags %s mode 0%o",
+ name, string_from_portable(pflags), mode);
fd = open(name, flags, mode);
if (fd < 0) {
status = errno_to_portable(errno);
} else {
- handle = handle_new(HANDLE_FILE, xstrdup(name), fd, NULL);
+ handle = handle_new(HANDLE_FILE, name, fd, NULL);
if (handle < 0) {
close(fd);
} else {
@@ -424,7 +538,8 @@ process_close(void)
id = get_int();
handle = get_handle();
- TRACE("close id %u handle %d", id, handle);
+ debug3("request %u: close handle %u", id, handle);
+ handle_log_close(handle, NULL);
ret = handle_close(handle);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
@@ -443,11 +558,11 @@ process_read(void)
off = get_int64();
len = get_int();
- TRACE("read id %u handle %d off %llu len %d", id, handle,
- (u_int64_t)off, len);
+ debug("request %u: read \"%s\" (handle %d) off %llu len %d",
+ id, handle_to_name(handle), handle, (unsigned long long)off, len);
if (len > sizeof buf) {
len = sizeof buf;
- log("read change len %d", len);
+ debug2("read change len %d", len);
}
fd = handle_to_fd(handle);
if (fd >= 0) {
@@ -463,6 +578,7 @@ process_read(void)
} else {
send_data(id, buf, ret);
status = SSH2_FX_OK;
+ handle_update_read(handle, ret);
}
}
}
@@ -484,8 +600,8 @@ process_write(void)
off = get_int64();
data = get_string(&len);
- TRACE("write id %u handle %d off %llu len %d", id, handle,
- (u_int64_t)off, len);
+ debug("request %u: write \"%s\" (handle %d) off %llu len %d",
+ id, handle_to_name(handle), handle, (unsigned long long)off, len);
fd = handle_to_fd(handle);
if (fd >= 0) {
if (lseek(fd, off, SEEK_SET) < 0) {
@@ -494,13 +610,14 @@ process_write(void)
} else {
/* XXX ATOMICIO ? */
ret = write(fd, data, len);
- if (ret == -1) {
+ if (ret < 0) {
error("process_write: write failed");
status = errno_to_portable(errno);
- } else if (ret == len) {
+ } else if ((size_t)ret == len) {
status = SSH2_FX_OK;
+ handle_update_write(handle, ret);
} else {
- log("nothing at all written");
+ debug2("nothing at all written");
}
}
}
@@ -519,7 +636,8 @@ process_do_stat(int do_lstat)
id = get_int();
name = get_string(NULL);
- TRACE("%sstat id %u name %s", do_lstat ? "l" : "", id, name);
+ debug3("request %u: %sstat", id, do_lstat ? "l" : "");
+ verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
ret = do_lstat ? lstat(name, &st) : stat(name, &st);
if (ret < 0) {
status = errno_to_portable(errno);
@@ -555,9 +673,10 @@ process_fstat(void)
id = get_int();
handle = get_handle();
- TRACE("fstat id %u handle %d", id, handle);
+ debug("request %u: fstat \"%s\" (handle %u)",
+ id, handle_to_name(handle), handle);
fd = handle_to_fd(handle);
- if (fd >= 0) {
+ if (fd >= 0) {
ret = fstat(fd, &st);
if (ret < 0) {
status = errno_to_portable(errno);
@@ -572,7 +691,7 @@ process_fstat(void)
}
static struct timeval *
-attrib_to_tv(Attrib *a)
+attrib_to_tv(const Attrib *a)
{
static struct timeval tv[2];
@@ -594,23 +713,34 @@ process_setstat(void)
id = get_int();
name = get_string(NULL);
a = get_attrib();
- TRACE("setstat id %u name %s", id, name);
+ debug("request %u: setstat name \"%s\"", id, name);
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
+ log("set \"%s\" size %llu",
+ name, (unsigned long long)a->size);
ret = truncate(name, a->size);
if (ret == -1)
status = errno_to_portable(errno);
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+ log("set \"%s\" mode %04o", name, a->perm);
ret = chmod(name, a->perm & 0777);
if (ret == -1)
status = errno_to_portable(errno);
}
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+ char buf[64];
+ time_t t = a->mtime;
+
+ strftime(buf, sizeof(buf), "%Y" "%m%d-%H:%M:%S",
+ localtime(&t));
+ log("set \"%s\" modtime %s", name, buf);
ret = utimes(name, attrib_to_tv(a));
if (ret == -1)
status = errno_to_portable(errno);
}
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ log("set \"%s\" owner %lu group %lu", name,
+ (u_long)a->uid, (u_long)a->gid);
ret = chown(name, a->uid, a->gid);
if (ret == -1)
status = errno_to_portable(errno);
@@ -626,23 +756,26 @@ process_fsetstat(void)
u_int32_t id;
int handle, fd, ret;
int status = SSH2_FX_OK;
- char *name;
id = get_int();
handle = get_handle();
a = get_attrib();
- TRACE("fsetstat id %u handle %d", id, handle);
+ debug("request %u: fsetstat handle %d", id, handle);
fd = handle_to_fd(handle);
- name = handle_to_name(handle);
- if (fd < 0 || name == NULL) {
+ if (fd < 0) {
status = SSH2_FX_FAILURE;
} else {
+ char *name = handle_to_name(handle);
+
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
+ log("set \"%s\" size %llu",
+ name, (unsigned long long)a->size);
ret = ftruncate(fd, a->size);
if (ret == -1)
status = errno_to_portable(errno);
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+ log("set \"%s\" mode %04o", name, a->perm);
#ifdef HAVE_FCHMOD
ret = fchmod(fd, a->perm & 0777);
#else
@@ -652,6 +785,12 @@ process_fsetstat(void)
status = errno_to_portable(errno);
}
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+ char buf[64];
+ time_t t = a->mtime;
+
+ strftime(buf, sizeof(buf), "%Y" "%m%d-%H:%M:%S",
+ localtime(&t));
+ log("set \"%s\" modtime %s", name, buf);
#ifdef HAVE_FUTIMES
ret = futimes(fd, attrib_to_tv(a));
#else
@@ -661,6 +800,8 @@ process_fsetstat(void)
status = errno_to_portable(errno);
}
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ log("set \"%s\" owner %lu group %lu", name,
+ (u_long)a->uid, (u_long)a->gid);
#ifdef HAVE_FCHOWN
ret = fchown(fd, a->uid, a->gid);
#else
@@ -683,12 +824,13 @@ process_opendir(void)
id = get_int();
path = get_string(NULL);
- TRACE("opendir id %u path %s", id, path);
+ debug3("request %u: opendir", id);
+ log("opendir \"%s\"", path);
dirp = opendir(path);
if (dirp == NULL) {
status = errno_to_portable(errno);
} else {
- handle = handle_new(HANDLE_DIR, xstrdup(path), 0, dirp);
+ handle = handle_new(HANDLE_DIR, path, 0, dirp);
if (handle < 0) {
closedir(dirp);
} else {
@@ -713,18 +855,19 @@ process_readdir(void)
id = get_int();
handle = get_handle();
- TRACE("readdir id %u handle %d", id, handle);
+ debug("request %u: readdir \"%s\" (handle %d)", id,
+ handle_to_name(handle), handle);
dirp = handle_to_dir(handle);
path = handle_to_name(handle);
if (dirp == NULL || path == NULL) {
send_status(id, SSH2_FX_FAILURE);
} else {
struct stat st;
- char pathname[1024];
+ char pathname[MAXPATHLEN];
Stat *stats;
int nstats = 10, count = 0, i;
- stats = xmalloc(nstats * sizeof(Stat));
+ stats = xcalloc(nstats, sizeof(Stat));
while ((dp = readdir(dirp)) != NULL) {
if (count >= nstats) {
nstats *= 2;
@@ -767,7 +910,8 @@ process_remove(void)
id = get_int();
name = get_string(NULL);
- TRACE("remove id %u name %s", id, name);
+ debug3("request %u: remove", id);
+ log("remove name \"%s\"", name);
ret = unlink(name);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
@@ -787,7 +931,8 @@ process_mkdir(void)
a = get_attrib();
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
a->perm & 0777 : 0777;
- TRACE("mkdir id %u name %s mode 0%o", id, name, mode);
+ debug3("request %u: mkdir", id);
+ log("mkdir name \"%s\" mode 0%o", name, mode);
ret = mkdir(name, mode);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
@@ -803,7 +948,8 @@ process_rmdir(void)
id = get_int();
name = get_string(NULL);
- TRACE("rmdir id %u name %s", id, name);
+ debug3("request %u: rmdir", id);
+ log("rmdir name \"%s\"", name);
ret = rmdir(name);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
@@ -823,7 +969,8 @@ process_realpath(void)
xfree(path);
path = xstrdup(".");
}
- TRACE("realpath id %u path %s", id, path);
+ debug3("request %u: realpath", id);
+ verbose("realpath \"%s\"", path);
if (realpath(path, resolvedname) == NULL) {
send_status(id, errno_to_portable(errno));
} else {
@@ -839,18 +986,53 @@ static void
process_rename(void)
{
u_int32_t id;
- struct stat st;
char *oldpath, *newpath;
- int ret, status = SSH2_FX_FAILURE;
+ int status;
+ struct stat sb;
id = get_int();
oldpath = get_string(NULL);
newpath = get_string(NULL);
- TRACE("rename id %u old %s new %s", id, oldpath, newpath);
- /* fail if 'newpath' exists */
- if (stat(newpath, &st) == -1) {
- ret = rename(oldpath, newpath);
- status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+ debug3("request %u: rename", id);
+ log("rename old \"%s\" new \"%s\"", oldpath, newpath);
+ status = SSH2_FX_FAILURE;
+ if (lstat(oldpath, &sb) == -1)
+ status = errno_to_portable(errno);
+ else if (S_ISREG(sb.st_mode)) {
+ /* Race-free rename of regular files */
+ if (link(oldpath, newpath) == -1) {
+ if (errno == EOPNOTSUPP
+#ifdef LINK_OPNOTSUPP_ERRNO
+ || errno == LINK_OPNOTSUPP_ERRNO
+#endif
+ ) {
+ struct stat st;
+
+ /*
+ * fs doesn't support links, so fall back to
+ * stat+rename. This is racy.
+ */
+ if (stat(newpath, &st) == -1) {
+ if (rename(oldpath, newpath) == -1)
+ status =
+ errno_to_portable(errno);
+ else
+ status = SSH2_FX_OK;
+ }
+ } else {
+ status = errno_to_portable(errno);
+ }
+ } else if (unlink(oldpath) == -1) {
+ status = errno_to_portable(errno);
+ /* clean spare link */
+ unlink(newpath);
+ } else
+ status = SSH2_FX_OK;
+ } else if (stat(newpath, &sb) == -1) {
+ if (rename(oldpath, newpath) == -1)
+ status = errno_to_portable(errno);
+ else
+ status = SSH2_FX_OK;
}
send_status(id, status);
xfree(oldpath);
@@ -862,20 +1044,21 @@ process_readlink(void)
{
u_int32_t id;
int len;
- char link[MAXPATHLEN];
+ char buf[MAXPATHLEN];
char *path;
id = get_int();
path = get_string(NULL);
- TRACE("readlink id %u path %s", id, path);
- if ((len = readlink(path, link, sizeof(link) - 1)) == -1)
+ debug3("request %u: readlink", id);
+ verbose("readlink \"%s\"", path);
+ if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
send_status(id, errno_to_portable(errno));
else {
Stat s;
- link[len] = '\0';
+ buf[len] = '\0';
attrib_clear(&s.attrib);
- s.name = s.long_name = link;
+ s.name = s.long_name = buf;
send_names(id, 1, &s);
}
xfree(path);
@@ -885,19 +1068,17 @@ static void
process_symlink(void)
{
u_int32_t id;
- struct stat st;
char *oldpath, *newpath;
- int ret, status = SSH2_FX_FAILURE;
+ int ret, status;
id = get_int();
oldpath = get_string(NULL);
newpath = get_string(NULL);
- TRACE("symlink id %u old %s new %s", id, oldpath, newpath);
- /* fail if 'newpath' exists */
- if (stat(newpath, &st) == -1) {
- ret = symlink(oldpath, newpath);
- status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
- }
+ debug3("request %u: symlink", id);
+ log("symlink old \"%s\" new \"%s\"", oldpath, newpath);
+ /* this will fail if 'newpath' exists */
+ ret = symlink(oldpath, newpath);
+ status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
xfree(oldpath);
xfree(newpath);
@@ -930,10 +1111,11 @@ process(void)
if (buf_len < 5)
return; /* Incomplete message. */
cp = buffer_ptr(&iqueue);
- msg_len = GET_32BIT(cp);
- if (msg_len > 256 * 1024) {
- error("bad message ");
- exit(11);
+ msg_len = get_u32(cp);
+ if (msg_len > SFTP_MAX_MSG_LENGTH) {
+ error("bad message from %s local user %s",
+ client_addr, pw->pw_name);
+ cleanup_exit(11);
}
if (buf_len < msg_len + 4)
return;
@@ -1007,7 +1189,7 @@ process(void)
}
/* discard the remaining bytes from the current packet */
if (buf_len < buffer_len(&iqueue))
- fatal("iqueue grows");
+ fatal("iqueue grew unexpectedly");
consumed = buf_len - buffer_len(&iqueue);
if (msg_len < consumed)
fatal("msg_len %d < consumed %d", msg_len, consumed);
@@ -1015,24 +1197,93 @@ process(void)
buffer_consume(&iqueue, msg_len - consumed);
}
+/* Cleanup handler that logs active handles upon normal exit */
+static void
+cleanup_exit(int i)
+{
+ if (pw != NULL && client_addr != NULL) {
+ handle_log_exit();
+ log("session closed for local user %s from [%s]",
+ pw->pw_name, client_addr);
+ }
+ _exit(i);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s [-he] [-l log_level] [-f log_facility]\n", __progname);
+ exit(1);
+}
+
int
-main(int ac, char **av)
+main(int argc, char **argv)
{
fd_set *rset, *wset;
- int in, out, max;
+ int in, out, max, ch, skipargs = 0, log_stderr = 0;
ssize_t len, olen, set_size;
+ SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
+ char *cp, buf[4*4096];
- /* XXX should use getopt */
+ extern char *optarg;
- __progname = get_progname(av[0]);
+ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+ sanitise_stdfd();
+
+ __progname = get_progname(argv[0]);
(void) g11n_setlocale(LC_ALL, "");
- handle_init();
+ log_init(__progname, log_level, log_facility, log_stderr);
+
+ while (!skipargs && (ch = getopt(argc, argv, "C:f:l:che")) != -1) {
+ switch (ch) {
+ case 'c':
+ /*
+ * Ignore all arguments if we are invoked as a
+ * shell using "sftp-server -c command"
+ */
+ skipargs = 1;
+ break;
+ case 'e':
+ log_stderr = 1;
+ break;
+ case 'l':
+ log_level = log_level_number(optarg);
+ if (log_level == SYSLOG_LEVEL_NOT_SET)
+ error("Invalid log level \"%s\"", optarg);
+ break;
+ case 'f':
+ log_facility = log_facility_number(optarg);
+ if (log_facility == SYSLOG_FACILITY_NOT_SET)
+ error("Invalid log facility \"%s\"", optarg);
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
-#ifdef DEBUG_SFTP_SERVER
- log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0);
-#endif
+ log_init(__progname, log_level, log_facility, log_stderr);
+
+ if ((cp = getenv("SSH_CONNECTION")) != NULL) {
+ client_addr = xstrdup(cp);
+ if ((cp = strchr(client_addr, ' ')) == NULL)
+ fatal("Malformed SSH_CONNECTION variable: \"%s\"",
+ getenv("SSH_CONNECTION"));
+ *cp = '\0';
+ } else
+ client_addr = xstrdup("UNKNOWN");
+
+ if ((pw = getpwuid(getuid())) == NULL)
+ fatal("No user found for uid %lu", (u_long)getuid());
+ pw = pwcopy(pw);
+
+ log("session opened for local user %s from [%s]",
+ pw->pw_name, client_addr);
+
+ handle_init();
in = dup(STDIN_FILENO);
out = dup(STDOUT_FILENO);
@@ -1059,7 +1310,15 @@ main(int ac, char **av)
memset(rset, 0, set_size);
memset(wset, 0, set_size);
- FD_SET(in, rset);
+ /*
+ * Ensure that we can read a full buffer and handle
+ * the worst-case length packet it can generate,
+ * otherwise apply backpressure by stopping reads.
+ */
+ if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
+ buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
+ FD_SET(in, rset);
+
olen = buffer_len(&oqueue);
if (olen > 0)
FD_SET(out, wset);
@@ -1067,19 +1326,19 @@ main(int ac, char **av)
if (select(max+1, rset, wset, NULL, NULL) < 0) {
if (errno == EINTR)
continue;
- return (2);
+ error("select: %s", strerror(errno));
+ cleanup_exit(2);
}
/* copy stdin to iqueue */
if (FD_ISSET(in, rset)) {
- char buf[4*4096];
len = read(in, buf, sizeof buf);
if (len == 0) {
debug("read eof");
- return (0);
+ cleanup_exit(0);
} else if (len < 0) {
- error("read error");
- return (1);
+ error("read: %s", strerror(errno));
+ cleanup_exit(1);
} else {
buffer_append(&iqueue, buf, len);
}
@@ -1088,13 +1347,22 @@ main(int ac, char **av)
if (FD_ISSET(out, wset)) {
len = write(out, buffer_ptr(&oqueue), olen);
if (len < 0) {
- error("write error");
- return (1);
+ error("write: %s", strerror(errno));
+ cleanup_exit(1);
} else {
buffer_consume(&oqueue, len);
}
}
- /* process requests from client */
- process();
+
+ /*
+ * Process requests from client if we can fit the results
+ * into the output buffer, otherwise stop processing input
+ * and let the output queue drain.
+ */
+ if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
+ process();
}
+
+ /* NOTREACHED */
+ return (0);
}
diff --git a/usr/src/cmd/ssh/sftp/Makefile b/usr/src/cmd/ssh/sftp/Makefile
index c91fe3f9cc..f99b2b7c03 100644
--- a/usr/src/cmd/ssh/sftp/Makefile
+++ b/usr/src/cmd/ssh/sftp/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -19,47 +18,47 @@
#
# CDDL HEADER END
#
-# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
#
# cmd/ssh/sftp/Makefile
-PROG= sftp
+PROG = sftp
-OBJS = \
- sftp.o \
- sftp-client.o \
- sftp-int.o \
- sftp-glob.o
-SRCS = $(OBJS:.o=.c)
+OBJS = \
+ sftp.o \
+ sftp-client.o \
+ sftp-glob.o
+
+SRCS = $(OBJS:.o=.c)
include ../../Makefile.cmd
include ../Makefile.ssh-common
-LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket $(OPENSSL_LDFLAGS) -lcrypto
+LDLIBS += $(SSH_COMMON_LDLIBS) -lsocket $(OPENSSL_LDFLAGS) -lcrypto
-DYNFLAGS += $(OPENSSL_DYNFLAGS)
+DYNFLAGS += $(OPENSSL_DYNFLAGS)
-POFILE_DIR= ..
+POFILE_DIR = ..
.KEEP_STATE:
-.PARALLEL: $(OBJS)
+.PARALLEL: $(OBJS)
all: $(PROG)
-$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a
+$(PROG): $(OBJS) ../libssh/$(MACH)/libssh.a ../libopenbsd-compat/$(MACH)/libopenbsd-compat.a
$(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(DYNFLAGS)
$(POST_PROCESS)
-install: all $(ROOTPROG)
+install: all $(ROOTPROG)
clean:
$(RM) -f $(OBJS) $(PROG)
-lint: lint_SRCS
+lint: lint_SRCS
include ../Makefile.msg.targ
include ../../Makefile.targ
diff --git a/usr/src/cmd/ssh/sftp/sftp-client.c b/usr/src/cmd/ssh/sftp/sftp-client.c
index 420384476e..4c5f823e2f 100644
--- a/usr/src/cmd/ssh/sftp/sftp-client.c
+++ b/usr/src/cmd/ssh/sftp/sftp-client.c
@@ -1,55 +1,65 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
+ * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
- * 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.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/* $OpenBSD: sftp-client.c,v 1.76 2007/01/22 11:32:50 djm Exp $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
/* XXX: memleaks */
/* XXX: signed vs unsigned */
/* XXX: remove all logging, only return status codes */
/* XXX: copy between two remote sites */
#include "includes.h"
-RCSID("$OpenBSD: sftp-client.c,v 1.35 2002/09/11 22:41:49 djm Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+#include <sys/types.h>
+#include <sys/param.h>
#include "sys-queue.h"
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
-#include "getput.h"
-#include "xmalloc.h"
#include "log.h"
#include "atomicio.h"
+#include "progressmeter.h"
+#include "misc.h"
#include "sftp.h"
#include "sftp-common.h"
#include "sftp-client.h"
-/* Minimum amount of data to read at at time */
+extern volatile sig_atomic_t interrupted;
+extern int showprogress;
+
+/* Minimum amount of data to read at a time */
#define MIN_READ_SIZE 512
struct sftp_conn {
@@ -64,47 +74,48 @@ struct sftp_conn {
static void
send_msg(int fd, Buffer *m)
{
- int mlen = buffer_len(m);
- int len;
- Buffer oqueue;
+ char mlen[4];
+ struct iovec iov[2];
- buffer_init(&oqueue);
- buffer_put_int(&oqueue, mlen);
- buffer_append(&oqueue, buffer_ptr(m), mlen);
- buffer_consume(m, mlen);
+ if (buffer_len(m) > SFTP_MAX_MSG_LENGTH)
+ fatal("Outbound message too long %u", buffer_len(m));
- len = atomicio(write, fd, buffer_ptr(&oqueue), buffer_len(&oqueue));
- if (len <= 0)
+ /* Send length first */
+ put_u32(mlen, buffer_len(m));
+ iov[0].iov_base = mlen;
+ iov[0].iov_len = sizeof(mlen);
+ iov[1].iov_base = buffer_ptr(m);
+ iov[1].iov_len = buffer_len(m);
+
+ if (atomiciov(writev, fd, iov, 2) != buffer_len(m) + sizeof(mlen))
fatal("Couldn't send packet: %s", strerror(errno));
- buffer_free(&oqueue);
+ buffer_clear(m);
}
static void
get_msg(int fd, Buffer *m)
{
- u_int len, msg_len;
- unsigned char buf[4096];
+ u_int msg_len;
- len = atomicio(read, fd, buf, 4);
- if (len == 0)
- fatal("Connection closed");
- else if (len == (u_int) -1)
- fatal("Couldn't read packet: %s", strerror(errno));
+ buffer_append_space(m, 4);
+ if (atomicio(read, fd, buffer_ptr(m), 4) != 4) {
+ if (errno == EPIPE)
+ fatal("Connection closed");
+ else
+ fatal("Couldn't read packet: %s", strerror(errno));
+ }
- msg_len = GET_32BIT(buf);
- if (msg_len > 256 * 1024)
+ msg_len = buffer_get_int(m);
+ if (msg_len > SFTP_MAX_MSG_LENGTH)
fatal("Received message too long %u", msg_len);
- while (msg_len) {
- len = atomicio(read, fd, buf, MIN(msg_len, sizeof(buf)));
- if (len == 0)
+ buffer_append_space(m, msg_len);
+ if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) {
+ if (errno == EPIPE)
fatal("Connection closed");
- else if (len == (u_int) -1)
- fatal("Couldn't read packet: %s", strerror(errno));
-
- msg_len -= len;
- buffer_append(m, buf, len);
+ else
+ fatal("Read packet: %s", strerror(errno));
}
}
@@ -182,6 +193,7 @@ get_handle(int fd, u_int expected_id, u_int *len)
int status = buffer_get_int(&msg);
error("Couldn't get handle: %s", fx2txt(status));
+ buffer_free(&msg);
return(NULL);
} else if (type != SSH2_FXP_HANDLE)
fatal("Expected SSH2_FXP_HANDLE(%u) packet, got %u",
@@ -216,6 +228,7 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
debug("Couldn't stat remote file: %s", fx2txt(status));
else
error("Couldn't stat remote file: %s", fx2txt(status));
+ buffer_free(&msg);
return(NULL);
} else if (type != SSH2_FXP_ATTRS) {
fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
@@ -318,7 +331,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
SFTP_DIRENT ***dir)
{
Buffer msg;
- u_int type, id, handle_len, i, expected_id, ents = 0;
+ u_int count, type, id, handle_len, i, expected_id, ents = 0;
char *handle;
id = conn->msg_id++;
@@ -341,9 +354,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
(*dir)[0] = NULL;
}
- for (;;) {
- int count;
-
+ for (; !interrupted;) {
id = expected_id = conn->msg_id++;
debug3("Sending SSH2_FXP_READDIR I:%u", id);
@@ -377,6 +388,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
error("Couldn't read directory: %s",
fx2txt(status));
do_close(conn, handle, handle_len);
+ xfree(handle);
return(status);
}
} else if (type != SSH2_FXP_NAME)
@@ -399,8 +411,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
printf("%s\n", longname);
if (dir) {
- *dir = xrealloc(*dir, sizeof(**dir) *
- (ents + 2));
+ *dir = xrealloc(*dir, (ents + 2) * sizeof(**dir));
(*dir)[ents] = xmalloc(sizeof(***dir));
(*dir)[ents]->filename = xstrdup(filename);
(*dir)[ents]->longname = xstrdup(longname);
@@ -417,6 +428,13 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
do_close(conn, handle, handle_len);
xfree(handle);
+ /* Don't return partial matches on interrupt */
+ if (interrupted && dir != NULL && *dir != NULL) {
+ free_sftp_dirents(*dir);
+ *dir = xmalloc(sizeof(**dir));
+ **dir = NULL;
+ }
+
return(0);
}
@@ -520,6 +538,7 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet)
return(get_decode_stat(conn->fd_in, id, quiet));
}
+/* this is never used so hush the lint */
#if 0
Attrib *
do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
@@ -574,6 +593,8 @@ do_realpath(struct sftp_conn *conn, char *path)
Buffer msg;
u_int type, expected_id, count, id;
char *filename, *longname;
+ /* LINTED */
+ Attrib *a;
expected_id = id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path,
@@ -603,7 +624,7 @@ do_realpath(struct sftp_conn *conn, char *path)
filename = buffer_get_string(&msg, NULL);
longname = buffer_get_string(&msg, NULL);
- (void) decode_attrib(&msg);
+ a = decode_attrib(&msg);
debug3("SSH_FXP_REALPATH %s -> %s", path, filename);
@@ -654,7 +675,7 @@ do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
buffer_init(&msg);
- /* Send rename request */
+ /* Send symlink request */
id = conn->msg_id++;
buffer_put_char(&msg, SSH2_FXP_SYMLINK);
buffer_put_int(&msg, id);
@@ -667,12 +688,13 @@ do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
status = get_status(conn->fd_in, id);
if (status != SSH2_FX_OK)
- error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
+ error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
newpath, fx2txt(status));
return(status);
}
+/* this is never used so hush the lint */
#if 0
char *
do_readlink(struct sftp_conn *conn, char *path)
@@ -680,6 +702,7 @@ do_readlink(struct sftp_conn *conn, char *path)
Buffer msg;
u_int type, expected_id, count, id;
char *filename, *longname;
+ Attrib *a;
expected_id = id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path,
@@ -709,7 +732,7 @@ do_readlink(struct sftp_conn *conn, char *path)
filename = buffer_get_string(&msg, NULL);
longname = buffer_get_string(&msg, NULL);
- (void) decode_attrib(&msg);
+ a = decode_attrib(&msg);
debug3("SSH_FXP_READLINK %s -> %s", path, filename);
@@ -745,10 +768,11 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
Attrib junk, *a;
Buffer msg;
char *handle;
- int local_fd, status, num_req, max_req, write_error;
+ int local_fd, status = 0, write_error;
int read_error, write_errno;
u_int64_t offset, size;
- u_int handle_len, mode, type, id, buflen;
+ u_int handle_len, mode, type, id, buflen, num_req, max_req;
+ off_t progress_counter;
struct request {
u_int id;
u_int len;
@@ -766,13 +790,13 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
/* XXX: should we preserve set[ug]id? */
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
- mode = S_IWRITE | (a->perm & 0777);
+ mode = a->perm & 0777;
else
mode = 0666;
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
- S_ISDIR(a->perm)) {
- error("Cannot download a directory: %s", remote_path);
+ (!S_ISREG(a->perm))) {
+ error("Cannot download non-regular file: %s", remote_path);
return(-1);
}
@@ -801,7 +825,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
return(-1);
}
- local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+ local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
+ mode | S_IWRITE);
if (local_fd == -1) {
error("Couldn't open local file \"%s\" for writing: %s",
local_path, strerror(errno));
@@ -813,10 +838,25 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
/* Read from remote and write to local */
write_error = read_error = write_errno = num_req = offset = 0;
max_req = 1;
+ progress_counter = 0;
+
+ if (showprogress && size != 0)
+ start_progress_meter(remote_path, size, &progress_counter);
+
while (num_req > 0 || max_req > 0) {
char *data;
u_int len;
+ /*
+ * Simulate EOF on interrupt: stop sending new requests and
+ * allow outstanding requests to drain gracefully
+ */
+ if (interrupted) {
+ if (num_req == 0) /* If we haven't started yet... */
+ break;
+ max_req = 0;
+ }
+
/* Send some more requests */
while (num_req < max_req) {
debug3("Request range %llu -> %llu (%d/%d)",
@@ -841,7 +881,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
/* Find the request in our queue */
- for(req = TAILQ_FIRST(&requests);
+ for (req = TAILQ_FIRST(&requests);
req != NULL && req->id != id;
req = TAILQ_NEXT(req, tq))
;
@@ -865,14 +905,15 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
(unsigned long long)req->offset + len - 1);
if (len > req->len)
fatal("Received more data than asked for "
- "%u > %u", len, req->len);
+ "%u > %u", len, req->len);
if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
- atomicio(write, local_fd, data, len) != len) &&
+ atomicio(vwrite, local_fd, data, len) != len) &&
!write_error) {
write_errno = errno;
write_error = 1;
max_req = 0;
}
+ progress_counter += len;
xfree(data);
if (len == req->len) {
@@ -903,8 +944,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
(unsigned long long)offset,
num_req);
max_req = 1;
- }
- else if (max_req < conn->num_requests + 1) {
+ } else if (max_req <= conn->num_requests) {
++max_req;
}
}
@@ -915,6 +955,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
}
}
+ if (showprogress && size)
+ stop_progress_meter();
+
/* Sanity check */
if (TAILQ_FIRST(&requests) != NULL)
fatal("Transfer complete, but requests still in queue");
@@ -934,11 +977,11 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
/* Override umask and utimes if asked */
#ifdef HAVE_FCHMOD
if (pflag && fchmod(local_fd, mode) == -1)
-#else
+#else
if (pflag && chmod(local_path, mode) == -1)
#endif /* HAVE_FCHMOD */
error("Couldn't set mode on \"%s\": %s", local_path,
- strerror(errno));
+ strerror(errno));
if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
struct timeval tv[2];
tv[0].tv_sec = a->atime;
@@ -946,7 +989,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
tv[0].tv_usec = tv[1].tv_usec = 0;
if (utimes(local_path, tv) == -1)
error("Can't set times on \"%s\": %s",
- local_path, strerror(errno));
+ local_path, strerror(errno));
}
}
close(local_fd);
@@ -976,7 +1019,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
TAILQ_ENTRY(outstanding_ack) tq;
};
TAILQ_HEAD(ackhead, outstanding_ack) acks;
- struct outstanding_ack *ack;
+ struct outstanding_ack *ack = NULL;
TAILQ_INIT(&acks);
@@ -991,6 +1034,11 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
close(local_fd);
return(-1);
}
+ if (!S_ISREG(sb.st_mode)) {
+ error("%s is not a regular file", local_path);
+ close(local_fd);
+ return(-1);
+ }
stat_to_attrib(&sb, &a);
a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
@@ -1025,14 +1073,21 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
/* Read from local and write to remote */
offset = 0;
+ if (showprogress)
+ start_progress_meter(local_path, sb.st_size, (off_t *)&offset);
+
for (;;) {
int len;
/*
- * Can't use atomicio here because it returns 0 on EOF, thus losing
- * the last block of the file
+ * Can't use atomicio here because it returns 0 on EOF,
+ * thus losing the last block of the file.
+ * Simulate an EOF on interrupt, allowing ACKs from the
+ * server to drain.
*/
- do
+ if (interrupted)
+ len = 0;
+ else do
len = read(local_fd, data, conn->transfer_buflen);
while ((len == -1) && (errno == EINTR || errno == EAGAIN));
@@ -1055,7 +1110,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
buffer_put_string(&msg, data, len);
send_msg(conn->fd_out, &msg);
debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
- id, (unsigned long long)offset, len);
+ id, (unsigned long long)offset, len);
} else if (TAILQ_FIRST(&acks) == NULL)
break;
@@ -1079,7 +1134,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
debug3("SSH2_FXP_STATUS %d", status);
/* Find the request in our queue */
- for(ack = TAILQ_FIRST(&acks);
+ for (ack = TAILQ_FIRST(&acks);
ack != NULL && ack->id != r_id;
ack = TAILQ_NEXT(ack, tq))
;
@@ -1089,18 +1144,25 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
if (status != SSH2_FX_OK) {
error("Couldn't write to remote file \"%s\": %s",
- remote_path, fx2txt(status));
+ remote_path, fx2txt(status));
+ if (showprogress)
+ stop_progress_meter();
do_close(conn, handle, handle_len);
close(local_fd);
+ xfree(data);
+ xfree(ack);
+ status = -1;
goto done;
}
debug3("In write loop, ack for %u %u bytes at %llu",
- ack->id, ack->len, (unsigned long long)ack->offset);
+ ack->id, ack->len, (unsigned long long)ack->offset);
++ackid;
xfree(ack);
}
offset += len;
}
+ if (showprogress)
+ stop_progress_meter();
xfree(data);
if (close(local_fd) == -1) {
diff --git a/usr/src/cmd/ssh/sftp/sftp-glob.c b/usr/src/cmd/ssh/sftp/sftp-glob.c
index 2d2d18e64f..856b3a2635 100644
--- a/usr/src/cmd/ssh/sftp/sftp-glob.c
+++ b/usr/src/cmd/ssh/sftp/sftp-glob.c
@@ -1,45 +1,41 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
+ * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
- * 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.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "includes.h"
-RCSID("$OpenBSD: sftp-glob.c,v 1.13 2002/09/11 22:41:50 djm Exp $");
+/* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */
#pragma ident "%Z%%M% %I% %E% SMI"
-#include "buffer.h"
-#include "bufaux.h"
-#include "xmalloc.h"
-#include "log.h"
+#include "includes.h"
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#include <dirent.h>
+#include <string.h>
+
+#include "xmalloc.h"
#include "sftp.h"
+#include "buffer.h"
#include "sftp-common.h"
#include "sftp-client.h"
-#include "sftp-glob.h"
+
+int remote_glob(struct sftp_conn *, const char *, int,
+ int (*)(const char *, int), glob_t *);
struct SFTP_OPENDIR {
SFTP_DIRENT **dir;
@@ -79,7 +75,7 @@ fudge_readdir(struct SFTP_OPENDIR *od)
#ifdef __GNU_LIBRARY__
static int inum = 1;
#endif /* __GNU_LIBRARY__ */
-
+
if (od->dir[od->offset] == NULL)
return(NULL);
@@ -98,7 +94,7 @@ fudge_readdir(struct SFTP_OPENDIR *od)
#ifdef __GNU_LIBRARY__
/*
* Idiot glibc uses extensions to struct dirent for readdir with
- * ALTDIRFUNCs. Not that this is documented anywhere but the
+ * ALTDIRFUNCs. Not that this is documented anywhere but the
* source... Fake an inode number to appease it.
*/
ret->d_ino = inum++;
diff --git a/usr/src/cmd/ssh/sftp/sftp-int.c b/usr/src/cmd/ssh/sftp/sftp-int.c
deleted file mode 100644
index 8c7d375752..0000000000
--- a/usr/src/cmd/ssh/sftp/sftp-int.c
+++ /dev/null
@@ -1,1098 +0,0 @@
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2001,2002 Damien Miller. 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.
- */
-
-/* XXX: recursive operations */
-
-#include "includes.h"
-RCSID("$OpenBSD: sftp-int.c,v 1.49 2002/09/12 00:13:06 djm Exp $");
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include "buffer.h"
-#include "xmalloc.h"
-#include "log.h"
-#include "pathnames.h"
-
-#include "sftp.h"
-#include "sftp-common.h"
-#include "sftp-glob.h"
-#include "sftp-client.h"
-#include "sftp-int.h"
-
-/* File to read commands from */
-extern FILE *infile;
-
-/* Size of buffer used when copying files */
-extern size_t copy_buffer_len;
-
-/* Number of concurrent outstanding requests */
-extern int num_requests;
-
-/* Seperators for interactive commands */
-#define WHITESPACE " \t\r\n"
-
-/* Commands for interactive mode */
-#define I_CHDIR 1
-#define I_CHGRP 2
-#define I_CHMOD 3
-#define I_CHOWN 4
-#define I_GET 5
-#define I_HELP 6
-#define I_LCHDIR 7
-#define I_LLS 8
-#define I_LMKDIR 9
-#define I_LPWD 10
-#define I_LS 11
-#define I_LUMASK 12
-#define I_MKDIR 13
-#define I_PUT 14
-#define I_PWD 15
-#define I_QUIT 16
-#define I_RENAME 17
-#define I_RM 18
-#define I_RMDIR 19
-#define I_SHELL 20
-#define I_SYMLINK 21
-#define I_VERSION 22
-
-struct CMD {
- const char *c;
- const int n;
-};
-
-const struct CMD cmds[] = {
- { "bye", I_QUIT },
- { "cd", I_CHDIR },
- { "chdir", I_CHDIR },
- { "chgrp", I_CHGRP },
- { "chmod", I_CHMOD },
- { "chown", I_CHOWN },
- { "dir", I_LS },
- { "exit", I_QUIT },
- { "get", I_GET },
- { "mget", I_GET },
- { "help", I_HELP },
- { "lcd", I_LCHDIR },
- { "lchdir", I_LCHDIR },
- { "lls", I_LLS },
- { "lmkdir", I_LMKDIR },
- { "ln", I_SYMLINK },
- { "lpwd", I_LPWD },
- { "ls", I_LS },
- { "lumask", I_LUMASK },
- { "mkdir", I_MKDIR },
- { "put", I_PUT },
- { "mput", I_PUT },
- { "pwd", I_PWD },
- { "quit", I_QUIT },
- { "rename", I_RENAME },
- { "rm", I_RM },
- { "rmdir", I_RMDIR },
- { "symlink", I_SYMLINK },
- { "version", I_VERSION },
- { "!", I_SHELL },
- { "?", I_HELP },
- { NULL, -1}
-};
-
-static void
-help(void)
-{
- printf(gettext("Available commands:\n"
- "cd path Change remote directory to 'path'\n"
- "lcd path Change local directory to 'path'\n"
- "chgrp grp path Change group of file 'path' "
- "to 'grp'\n"
- "chmod mode path Change permissions of file "
- "'path' to 'mode'\n"
- "chown own path Change owner of file 'path' "
- "to 'own'\n"
- "help Display this help text\n"
- "get remote-path [local-path] Download file\n"
- "lls [ls-options [path]] Display local directory listing\n"
- "ln oldpath newpath Symlink remote file\n"
- "lmkdir path Create local directory\n"
- "lpwd Print local working directory\n"
- "ls [path] Display remote directory listing\n"
- "lumask umask Set local umask to 'umask'\n"
- "mkdir path Create remote directory\n"
- "put local-path [remote-path] Upload file\n"
- "pwd Display remote working directory\n"
- "exit Quit sftp\n"
- "quit Quit sftp\n"
- "rename oldpath newpath Rename remote file\n"
- "rmdir path Remove remote directory\n"
- "rm path Delete remote file\n"
- "symlink oldpath newpath Symlink remote file\n"
- "version Show SFTP version\n"
- "!command Execute 'command' in local shell\n"
- "! Escape to local shell\n"
- "? Synonym for help\n"));
-}
-
-static void
-local_do_shell(const char *args)
-{
- int status;
- char *shell;
- pid_t pid;
-
- if (!*args)
- args = NULL;
-
- if ((shell = getenv("SHELL")) == NULL)
- shell = _PATH_BSHELL;
-
- if ((pid = fork()) == -1)
- fatal("Couldn't fork: %s", strerror(errno));
-
- if (pid == 0) {
- /* XXX: child has pipe fds to ssh subproc open - issue? */
- if (args) {
- debug3("Executing %s -c \"%s\"", shell, args);
- execl(shell, shell, "-c", args, (char *)NULL);
- } else {
- debug3("Executing %s", shell);
- execl(shell, shell, (char *)NULL);
- }
- fprintf(stderr, gettext("Couldn't execute \"%s\": %s\n"), shell,
- strerror(errno));
- _exit(1);
- }
- while (waitpid(pid, &status, 0) == -1)
- if (errno != EINTR)
- fatal("Couldn't wait for child: %s", strerror(errno));
- if (!WIFEXITED(status))
- error("Shell exited abnormally");
- else if (WEXITSTATUS(status))
- error("Shell exited with status %d", WEXITSTATUS(status));
-}
-
-static void
-local_do_ls(const char *args)
-{
- if (!args || !*args)
- local_do_shell(_PATH_LS);
- else {
- int len = strlen(_PATH_LS " ") + strlen(args) + 1;
- char *buf = xmalloc(len);
-
- /* XXX: quoting - rip quoting code from ftp? */
- snprintf(buf, len, _PATH_LS " %s", args);
- local_do_shell(buf);
- xfree(buf);
- }
-}
-
-/* Strip one path (usually the pwd) from the start of another */
-static char *
-path_strip(char *path, char *strip)
-{
- size_t len;
-
- if (strip == NULL)
- return (xstrdup(path));
-
- len = strlen(strip);
- if (strip != NULL && strncmp(path, strip, len) == 0) {
- if (strip[len - 1] != '/' && path[len] == '/')
- len++;
- return (xstrdup(path + len));
- }
-
- return (xstrdup(path));
-}
-
-static char *
-path_append(char *p1, char *p2)
-{
- char *ret;
- int len = strlen(p1) + strlen(p2) + 2;
-
- ret = xmalloc(len);
- strlcpy(ret, p1, len);
- if (p1[strlen(p1) - 1] != '/')
- strlcat(ret, "/", len);
- strlcat(ret, p2, len);
-
- return(ret);
-}
-
-static char *
-make_absolute(char *p, char *pwd)
-{
- char *abs;
-
- /* Derelativise */
- if (p && p[0] != '/') {
- abs = path_append(pwd, p);
- xfree(p);
- return(abs);
- } else
- return(p);
-}
-
-static int
-infer_path(const char *p, char **ifp)
-{
- char *cp;
-
- cp = strrchr(p, '/');
- if (cp == NULL) {
- *ifp = xstrdup(p);
- return(0);
- }
-
- if (!cp[1]) {
- error("Invalid path");
- return(-1);
- }
-
- *ifp = xstrdup(cp + 1);
- return(0);
-}
-
-static int
-parse_getput_flags(const char **cpp, int *pflag)
-{
- const char *cp = *cpp;
-
- /* Check for flags */
- if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
- switch (cp[1]) {
- case 'p':
- case 'P':
- *pflag = 1;
- break;
- default:
- error("Invalid flag -%c", cp[1]);
- return(-1);
- }
- cp += 2;
- *cpp = cp + strspn(cp, WHITESPACE);
- }
-
- return(0);
-}
-
-static int
-parse_ls_flags(const char **cpp, int *lflag)
-{
- const char *cp = *cpp;
-
- /* Check for flags */
- if (cp++[0] == '-') {
- for(; strchr(WHITESPACE, *cp) == NULL; cp++) {
- switch (*cp) {
- case 'l':
- *lflag = 1;
- break;
- default:
- error("Invalid flag -%c", *cp);
- return(-1);
- }
- }
- *cpp = cp + strspn(cp, WHITESPACE);
- }
-
- return(0);
-}
-
-static int
-get_pathname(const char **cpp, char **path)
-{
- const char *cp = *cpp, *end;
- char quot;
- int i;
-
- cp += strspn(cp, WHITESPACE);
- if (!*cp) {
- *cpp = cp;
- *path = NULL;
- return (0);
- }
-
- /* Check for quoted filenames */
- if (*cp == '\"' || *cp == '\'') {
- quot = *cp++;
-
- end = strchr(cp, quot);
- if (end == NULL) {
- error("Unterminated quote");
- goto fail;
- }
- if (cp == end) {
- error("Empty quotes");
- goto fail;
- }
- *cpp = end + 1 + strspn(end + 1, WHITESPACE);
- } else {
- /* Read to end of filename */
- end = strpbrk(cp, WHITESPACE);
- if (end == NULL)
- end = strchr(cp, '\0');
- *cpp = end + strspn(end, WHITESPACE);
- }
-
- i = end - cp;
-
- *path = xmalloc(i + 1);
- memcpy(*path, cp, i);
- (*path)[i] = '\0';
- return(0);
-
- fail:
- *path = NULL;
- return (-1);
-}
-
-static int
-is_dir(char *path)
-{
- struct stat sb;
-
- /* XXX: report errors? */
- if (stat(path, &sb) == -1)
- return(0);
-
- return (S_ISDIR(sb.st_mode));
-}
-
-static int
-remote_is_dir(struct sftp_conn *conn, char *path)
-{
- Attrib *a;
-
- /* XXX: report errors? */
- if ((a = do_stat(conn, path, 1)) == NULL)
- return(0);
- if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
- return(0);
- return (S_ISDIR(a->perm));
-}
-
-static int
-process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
-{
- char *abs_src = NULL;
- char *abs_dst = NULL;
- char *tmp;
- glob_t g;
- int err = 0;
- int i;
-
- abs_src = xstrdup(src);
- abs_src = make_absolute(abs_src, pwd);
-
- memset(&g, 0, sizeof(g));
- debug3("Looking up %s", abs_src);
- if (remote_glob(conn, abs_src, 0, NULL, &g)) {
- error("File \"%s\" not found.", abs_src);
- err = -1;
- goto out;
- }
-
- /* Only one match, dst may be file, directory or unspecified */
- if (g.gl_pathv[0] && g.gl_matchc == 1) {
- if (dst) {
- /* If directory specified, append filename */
- if (is_dir(dst)) {
- if (infer_path(g.gl_pathv[0], &tmp)) {
- err = 1;
- goto out;
- }
- abs_dst = path_append(dst, tmp);
- xfree(tmp);
- } else
- abs_dst = xstrdup(dst);
- } else if (infer_path(g.gl_pathv[0], &abs_dst)) {
- err = -1;
- goto out;
- }
- printf(gettext("Fetching %s to %s\n"), g.gl_pathv[0], abs_dst);
- err = do_download(conn, g.gl_pathv[0], abs_dst, pflag);
- goto out;
- }
-
- /* Multiple matches, dst may be directory or unspecified */
- if (dst && !is_dir(dst)) {
- error("Multiple files match, but \"%s\" is not a directory",
- dst);
- err = -1;
- goto out;
- }
-
- for (i = 0; g.gl_pathv[i]; i++) {
- if (infer_path(g.gl_pathv[i], &tmp)) {
- err = -1;
- goto out;
- }
- if (dst) {
- abs_dst = path_append(dst, tmp);
- xfree(tmp);
- } else
- abs_dst = tmp;
-
- printf(gettext("Fetching %s to %s\n"), g.gl_pathv[i], abs_dst);
- if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
- err = -1;
- xfree(abs_dst);
- abs_dst = NULL;
- }
-
-out:
- xfree(abs_src);
- if (abs_dst)
- xfree(abs_dst);
- globfree(&g);
- return(err);
-}
-
-static int
-process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
-{
- char *tmp_dst = NULL;
- char *abs_dst = NULL;
- char *tmp;
- glob_t g;
- int err = 0;
- int i;
-
- if (dst) {
- tmp_dst = xstrdup(dst);
- tmp_dst = make_absolute(tmp_dst, pwd);
- }
-
- memset(&g, 0, sizeof(g));
- debug3("Looking up %s", src);
- if (glob(src, 0, NULL, &g)) {
- error("File \"%s\" not found.", src);
- err = -1;
- goto out;
- }
-
- /* Only one match, dst may be file, directory or unspecified */
- if (g.gl_pathv[0] && g.gl_matchc == 1) {
- if (tmp_dst) {
- /* If directory specified, append filename */
- if (remote_is_dir(conn, tmp_dst)) {
- if (infer_path(g.gl_pathv[0], &tmp)) {
- err = 1;
- goto out;
- }
- abs_dst = path_append(tmp_dst, tmp);
- xfree(tmp);
- } else
- abs_dst = xstrdup(tmp_dst);
- } else {
- if (infer_path(g.gl_pathv[0], &abs_dst)) {
- err = -1;
- goto out;
- }
- abs_dst = make_absolute(abs_dst, pwd);
- }
- printf(gettext("Uploading %s to %s\n"), g.gl_pathv[0], abs_dst);
- err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag);
- goto out;
- }
-
- /* Multiple matches, dst may be directory or unspecified */
- if (tmp_dst && !remote_is_dir(conn, tmp_dst)) {
- error("Multiple files match, but \"%s\" is not a directory",
- tmp_dst);
- err = -1;
- goto out;
- }
-
- for (i = 0; g.gl_pathv[i]; i++) {
- if (infer_path(g.gl_pathv[i], &tmp)) {
- err = -1;
- goto out;
- }
- if (tmp_dst) {
- abs_dst = path_append(tmp_dst, tmp);
- xfree(tmp);
- } else
- abs_dst = make_absolute(tmp, pwd);
-
- printf(gettext("Uploading %s to %s\n"), g.gl_pathv[i], abs_dst);
- if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
- err = -1;
- }
-
-out:
- if (abs_dst)
- xfree(abs_dst);
- if (tmp_dst)
- xfree(tmp_dst);
- return(err);
-}
-
-static int
-sdirent_comp(const void *aa, const void *bb)
-{
- SFTP_DIRENT *a = *(SFTP_DIRENT **)aa;
- SFTP_DIRENT *b = *(SFTP_DIRENT **)bb;
-
- return (strcmp(a->filename, b->filename));
-}
-
-/* sftp ls.1 replacement for directories */
-static int
-do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
-{
- int n;
- SFTP_DIRENT **d;
-
- if ((n = do_readdir(conn, path, &d)) != 0)
- return (n);
-
- /* Count entries for sort */
- for (n = 0; d[n] != NULL; n++)
- ;
-
- qsort(d, n, sizeof(*d), sdirent_comp);
-
- for (n = 0; d[n] != NULL; n++) {
- char *tmp, *fname;
-
- tmp = path_append(path, d[n]->filename);
- fname = path_strip(tmp, strip_path);
- xfree(tmp);
-
- if (lflag) {
- char *lname;
- struct stat sb;
-
- memset(&sb, 0, sizeof(sb));
- attrib_to_stat(&d[n]->a, &sb);
- lname = ls_file(fname, &sb, 1);
- printf("%s\n", lname);
- xfree(lname);
- } else {
- /* XXX - multicolumn display would be nice here */
- printf("%s\n", fname);
- }
-
- xfree(fname);
- }
-
- free_sftp_dirents(d);
- return (0);
-}
-
-/* sftp ls.1 replacement which handles path globs */
-static int
-do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
- int lflag)
-{
- glob_t g;
- int i;
- Attrib *a;
- struct stat sb;
-
- memset(&g, 0, sizeof(g));
-
- if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
- NULL, &g)) {
- error("Can't ls: \"%s\" not found", path);
- return (-1);
- }
-
- /*
- * If the glob returns a single match, which is the same as the
- * input glob, and it is a directory, then just list its contents
- */
- if (g.gl_pathc == 1 &&
- strncmp(path, g.gl_pathv[0], strlen(g.gl_pathv[0]) - 1) == 0) {
- if ((a = do_lstat(conn, path, 1)) == NULL) {
- globfree(&g);
- return (-1);
- }
- if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
- S_ISDIR(a->perm)) {
- globfree(&g);
- return (do_ls_dir(conn, path, strip_path, lflag));
- }
- }
-
- for (i = 0; g.gl_pathv[i]; i++) {
- char *fname, *lname;
-
- fname = path_strip(g.gl_pathv[i], strip_path);
-
- if (lflag) {
- /*
- * XXX: this is slow - 1 roundtrip per path
- * A solution to this is to fork glob() and
- * build a sftp specific version which keeps the
- * attribs (which currently get thrown away)
- * that the server returns as well as the filenames.
- */
- memset(&sb, 0, sizeof(sb));
- a = do_lstat(conn, g.gl_pathv[i], 1);
- if (a != NULL)
- attrib_to_stat(a, &sb);
- lname = ls_file(fname, &sb, 1);
- printf("%s\n", lname);
- xfree(lname);
- } else {
- /* XXX - multicolumn display would be nice here */
- printf("%s\n", fname);
- }
- xfree(fname);
- }
-
- if (g.gl_pathc)
- globfree(&g);
-
- return (0);
-}
-
-static int
-parse_args(const char **cpp, int *pflag, int *lflag,
- unsigned long *n_arg, char **path1, char **path2)
-{
- const char *cmd, *cp = *cpp;
- char *cp2;
- int base = 0;
- long l;
- int i, cmdnum;
-
- /* Skip leading whitespace */
- cp = cp + strspn(cp, WHITESPACE);
-
- /* Ignore blank lines */
- if (!*cp)
- return(-1);
-
- /* Figure out which command we have */
- for (i = 0; cmds[i].c; i++) {
- int cmdlen = strlen(cmds[i].c);
-
- /* Check for command followed by whitespace */
- if (!strncasecmp(cp, cmds[i].c, cmdlen) &&
- strchr(WHITESPACE, cp[cmdlen])) {
- cp += cmdlen;
- cp = cp + strspn(cp, WHITESPACE);
- break;
- }
- }
- cmdnum = cmds[i].n;
- cmd = cmds[i].c;
-
- /* Special case */
- if (*cp == '!') {
- cp++;
- cmdnum = I_SHELL;
- } else if (cmdnum == -1) {
- error("Invalid command.");
- return(-1);
- }
-
- /* Get arguments and parse flags */
- *lflag = *pflag = *n_arg = 0;
- *path1 = *path2 = NULL;
- switch (cmdnum) {
- case I_GET:
- case I_PUT:
- if (parse_getput_flags(&cp, pflag))
- return(-1);
- /* Get first pathname (mandatory) */
- if (get_pathname(&cp, path1))
- return(-1);
- if (*path1 == NULL) {
- error("You must specify at least one path after a "
- "%s command.", cmd);
- return(-1);
- }
- /* Try to get second pathname (optional) */
- if (get_pathname(&cp, path2))
- return(-1);
- break;
- case I_RENAME:
- case I_SYMLINK:
- if (get_pathname(&cp, path1))
- return(-1);
- if (get_pathname(&cp, path2))
- return(-1);
- if (!*path1 || !*path2) {
- error("You must specify two paths after a %s "
- "command.", cmd);
- return(-1);
- }
- break;
- case I_RM:
- case I_MKDIR:
- case I_RMDIR:
- case I_CHDIR:
- case I_LCHDIR:
- case I_LMKDIR:
- /* Get pathname (mandatory) */
- if (get_pathname(&cp, path1))
- return(-1);
- if (*path1 == NULL) {
- error("You must specify a path after a %s command.",
- cmd);
- return(-1);
- }
- break;
- case I_LS:
- if (parse_ls_flags(&cp, lflag))
- return(-1);
- /* Path is optional */
- if (get_pathname(&cp, path1))
- return(-1);
- break;
- case I_LLS:
- case I_SHELL:
- /* Uses the rest of the line */
- break;
- case I_LUMASK:
- base = 8;
- /* FALLTHROUGH */
- case I_CHMOD:
- base = 8;
- /* FALLTHROUGH */
- case I_CHOWN:
- case I_CHGRP:
- /* Get numeric arg (mandatory) */
- l = strtol(cp, &cp2, base);
- if (cp2 == cp || ((l == LONG_MIN || l == LONG_MAX) &&
- errno == ERANGE) || l < 0) {
- error("You must supply a numeric argument "
- "to the %s command.", cmd);
- return(-1);
- }
- cp = cp2;
- *n_arg = l;
- if (cmdnum == I_LUMASK && strchr(WHITESPACE, *cp))
- break;
- if (cmdnum == I_LUMASK || !strchr(WHITESPACE, *cp)) {
- error("You must supply a numeric argument "
- "to the %s command.", cmd);
- return(-1);
- }
- cp += strspn(cp, WHITESPACE);
-
- /* Get pathname (mandatory) */
- if (get_pathname(&cp, path1))
- return(-1);
- if (*path1 == NULL) {
- error("You must specify a path after a %s command.",
- cmd);
- return(-1);
- }
- break;
- case I_QUIT:
- case I_PWD:
- case I_LPWD:
- case I_HELP:
- case I_VERSION:
- break;
- default:
- fatal("Command not implemented");
- }
-
- *cpp = cp;
- return(cmdnum);
-}
-
-static int
-parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
-{
- char *path1, *path2, *tmp;
- int pflag, lflag, cmdnum, i;
- unsigned long n_arg;
- Attrib a, *aa;
- char path_buf[MAXPATHLEN];
- int err = 0;
- glob_t g;
-
- path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &pflag, &lflag, &n_arg,
- &path1, &path2);
-
- memset(&g, 0, sizeof(g));
-
- /* Perform command */
- switch (cmdnum) {
- case -1:
- break;
- case I_GET:
- err = process_get(conn, path1, path2, *pwd, pflag);
- break;
- case I_PUT:
- err = process_put(conn, path1, path2, *pwd, pflag);
- break;
- case I_RENAME:
- path1 = make_absolute(path1, *pwd);
- path2 = make_absolute(path2, *pwd);
- err = do_rename(conn, path1, path2);
- break;
- case I_SYMLINK:
- path2 = make_absolute(path2, *pwd);
- err = do_symlink(conn, path1, path2);
- break;
- case I_RM:
- path1 = make_absolute(path1, *pwd);
- remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
- for (i = 0; g.gl_pathv[i]; i++) {
- printf(gettext("Removing %s\n"), g.gl_pathv[i]);
- if (do_rm(conn, g.gl_pathv[i]) == -1)
- err = -1;
- }
- break;
- case I_MKDIR:
- path1 = make_absolute(path1, *pwd);
- attrib_clear(&a);
- a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
- a.perm = 0777;
- err = do_mkdir(conn, path1, &a);
- break;
- case I_RMDIR:
- path1 = make_absolute(path1, *pwd);
- err = do_rmdir(conn, path1);
- break;
- case I_CHDIR:
- path1 = make_absolute(path1, *pwd);
- if ((tmp = do_realpath(conn, path1)) == NULL) {
- err = 1;
- break;
- }
- if ((aa = do_stat(conn, tmp, 0)) == NULL) {
- xfree(tmp);
- err = 1;
- break;
- }
- if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
- error("Can't change directory: Can't check target");
- xfree(tmp);
- err = 1;
- break;
- }
- if (!S_ISDIR(aa->perm)) {
- error("Can't change directory: \"%s\" is not "
- "a directory", tmp);
- xfree(tmp);
- err = 1;
- break;
- }
- xfree(*pwd);
- *pwd = tmp;
- break;
- case I_LS:
- if (!path1) {
- do_globbed_ls(conn, *pwd, *pwd, lflag);
- break;
- }
-
- /* Strip pwd off beginning of non-absolute paths */
- tmp = NULL;
- if (*path1 != '/')
- tmp = *pwd;
-
- path1 = make_absolute(path1, *pwd);
-
- do_globbed_ls(conn, path1, tmp, lflag);
- break;
- case I_LCHDIR:
- if (chdir(path1) == -1) {
- error("Couldn't change local directory to "
- "\"%s\": %s", path1, strerror(errno));
- err = 1;
- }
- break;
- case I_LMKDIR:
- if (mkdir(path1, 0777) == -1) {
- error("Couldn't create local directory "
- "\"%s\": %s", path1, strerror(errno));
- err = 1;
- }
- break;
- case I_LLS:
- local_do_ls(cmd);
- break;
- case I_SHELL:
- local_do_shell(cmd);
- break;
- case I_LUMASK:
- umask(n_arg);
- printf(gettext("Local umask: %03lo\n"), n_arg);
- break;
- case I_CHMOD:
- path1 = make_absolute(path1, *pwd);
- attrib_clear(&a);
- a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
- a.perm = n_arg;
- remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
- for (i = 0; g.gl_pathv[i]; i++) {
- printf(gettext("Changing mode on %s\n"), g.gl_pathv[i]);
- do_setstat(conn, g.gl_pathv[i], &a);
- }
- break;
- case I_CHOWN:
- path1 = make_absolute(path1, *pwd);
- remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
- for (i = 0; g.gl_pathv[i]; i++) {
- if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
- continue;
- if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
- error("Can't get current ownership of "
- "remote file \"%s\"", g.gl_pathv[i]);
- continue;
- }
- printf(gettext("Changing owner on %s\n"),
- g.gl_pathv[i]);
- aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
- aa->uid = n_arg;
- do_setstat(conn, g.gl_pathv[i], aa);
- }
- break;
- case I_CHGRP:
- path1 = make_absolute(path1, *pwd);
- remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
- for (i = 0; g.gl_pathv[i]; i++) {
- if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
- continue;
- if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
- error("Can't get current ownership of "
- "remote file \"%s\"", g.gl_pathv[i]);
- continue;
- }
- printf(gettext("Changing group on %s\n"),
- g.gl_pathv[i]);
- aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
- aa->gid = n_arg;
- do_setstat(conn, g.gl_pathv[i], aa);
- }
- break;
- case I_PWD:
- printf(gettext("Remote working directory: %s\n"), *pwd);
- break;
- case I_LPWD:
- if (!getcwd(path_buf, sizeof(path_buf)))
- error("Couldn't get local cwd: %s",
- strerror(errno));
- else
- printf(gettext("Local working directory: %s\n"),
- path_buf);
- break;
- case I_QUIT:
- return(-1);
- case I_HELP:
- help();
- break;
- case I_VERSION:
- printf(gettext("SFTP protocol version %u\n"),
- sftp_proto_version(conn));
- break;
- default:
- fatal("%d is not implemented", cmdnum);
- }
-
- if (g.gl_pathc)
- globfree(&g);
- if (path1)
- xfree(path1);
- if (path2)
- xfree(path2);
-
- /* If an error occurs in batch mode we should abort. */
- if (infile != stdin && err > 0)
- return -1;
-
- return(0);
-}
-
-void
-interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
-{
- char *pwd;
- char *dir = NULL;
- char cmd[2048];
- struct sftp_conn *conn;
-
- conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
- if (conn == NULL)
- fatal("Couldn't initialise connection to server");
-
- pwd = do_realpath(conn, ".");
- if (pwd == NULL)
- fatal("Need cwd");
-
- if (file1 != NULL) {
- dir = xstrdup(file1);
- dir = make_absolute(dir, pwd);
-
- if (remote_is_dir(conn, dir) && file2 == NULL) {
- printf(gettext("Changing to: %s\n"), dir);
- snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
- parse_dispatch_command(conn, cmd, &pwd);
- } else {
- if (file2 == NULL)
- snprintf(cmd, sizeof cmd, "get %s", dir);
- else
- snprintf(cmd, sizeof cmd, "get %s %s", dir,
- file2);
-
- parse_dispatch_command(conn, cmd, &pwd);
- xfree(dir);
- return;
- }
- xfree(dir);
- }
-#if HAVE_SETVBUF
- setvbuf(stdout, NULL, _IOLBF, 0);
- setvbuf(infile, NULL, _IOLBF, 0);
-#else
- setlinebuf(stdout);
- setlinebuf(infile);
-#endif
-
- for (;;) {
- char *cp;
-
- printf("sftp> ");
-
- /* XXX: use libedit */
- if (fgets(cmd, sizeof(cmd), infile) == NULL) {
- printf("\n");
- break;
- } else if (infile != stdin) /* Bluff typing */
- printf("%s", cmd);
-
- cp = strrchr(cmd, '\n');
- if (cp)
- *cp = '\0';
-
- if (parse_dispatch_command(conn, cmd, &pwd))
- break;
- }
- xfree(pwd);
-}
diff --git a/usr/src/cmd/ssh/sftp/sftp.c b/usr/src/cmd/ssh/sftp/sftp.c
index 0f2f04638d..a0a2c83879 100644
--- a/usr/src/cmd/ssh/sftp/sftp.c
+++ b/usr/src/cmd/ssh/sftp/sftp.c
@@ -1,49 +1,60 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
+ * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
- * 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.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/* $OpenBSD: sftp.c,v 1.96 2007/01/03 04:09:15 stevesk Exp $ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include "includes.h"
-RCSID("$OpenBSD: sftp.c,v 1.31 2002/07/25 01:16:59 mouring Exp $");
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
-#pragma ident "%Z%%M% %I% %E% SMI"
+#include <errno.h>
-/* XXX: short-form remote directory listings (like 'ls -C') */
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+#ifdef USE_LIBEDIT
+#include <histedit.h>
+#else
+typedef void EditLine;
+#endif
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
-#include "buffer.h"
#include "xmalloc.h"
#include "log.h"
#include "pathnames.h"
#include "misc.h"
#include "sftp.h"
+#include "buffer.h"
#include "sftp-common.h"
#include "sftp-client.h"
-#include "sftp-int.h"
#ifdef HAVE___PROGNAME
extern char *__progname;
@@ -51,12 +62,1349 @@ extern char *__progname;
char *__progname;
#endif
+
+/* File to read commands from */
FILE* infile;
+
+/* Are we in batchfile mode? */
+int batchmode = 0;
+
+/* Size of buffer used when copying files */
size_t copy_buffer_len = 32768;
+
+/* Number of concurrent outstanding requests */
size_t num_requests = 16;
+/* PID of ssh transport process */
+static pid_t sshpid = -1;
+
+/* This is set to 0 if the progressmeter is not desired. */
+int showprogress = 1;
+
+/* SIGINT received during command processing */
+volatile sig_atomic_t interrupted = 0;
+
+/* I wish qsort() took a separate ctx for the comparison function...*/
+int sort_flag;
+
+int remote_glob(struct sftp_conn *, const char *, int,
+ int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
+
+/* Separators for interactive commands */
+#define WHITESPACE " \t\r\n"
+
+/* ls flags */
+#define LS_LONG_VIEW 0x01 /* Full view ala ls -l */
+#define LS_SHORT_VIEW 0x02 /* Single row view ala ls -1 */
+#define LS_NUMERIC_VIEW 0x04 /* Long view with numeric uid/gid */
+#define LS_NAME_SORT 0x08 /* Sort by name (default) */
+#define LS_TIME_SORT 0x10 /* Sort by mtime */
+#define LS_SIZE_SORT 0x20 /* Sort by file size */
+#define LS_REVERSE_SORT 0x40 /* Reverse sort order */
+#define LS_SHOW_ALL 0x80 /* Don't skip filenames starting with '.' */
+
+#define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW)
+#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT)
+
+/* Commands for interactive mode */
+#define I_CHDIR 1
+#define I_CHGRP 2
+#define I_CHMOD 3
+#define I_CHOWN 4
+#define I_GET 5
+#define I_HELP 6
+#define I_LCHDIR 7
+#define I_LLS 8
+#define I_LMKDIR 9
+#define I_LPWD 10
+#define I_LS 11
+#define I_LUMASK 12
+#define I_MKDIR 13
+#define I_PUT 14
+#define I_PWD 15
+#define I_QUIT 16
+#define I_RENAME 17
+#define I_RM 18
+#define I_RMDIR 19
+#define I_SHELL 20
+#define I_SYMLINK 21
+#define I_VERSION 22
+#define I_PROGRESS 23
+
+struct CMD {
+ const char *c;
+ const int n;
+};
+
+static const struct CMD cmds[] = {
+ { "bye", I_QUIT },
+ { "cd", I_CHDIR },
+ { "chdir", I_CHDIR },
+ { "chgrp", I_CHGRP },
+ { "chmod", I_CHMOD },
+ { "chown", I_CHOWN },
+ { "dir", I_LS },
+ { "exit", I_QUIT },
+ { "get", I_GET },
+ { "mget", I_GET },
+ { "help", I_HELP },
+ { "lcd", I_LCHDIR },
+ { "lchdir", I_LCHDIR },
+ { "lls", I_LLS },
+ { "lmkdir", I_LMKDIR },
+ { "ln", I_SYMLINK },
+ { "lpwd", I_LPWD },
+ { "ls", I_LS },
+ { "lumask", I_LUMASK },
+ { "mkdir", I_MKDIR },
+ { "progress", I_PROGRESS },
+ { "put", I_PUT },
+ { "mput", I_PUT },
+ { "pwd", I_PWD },
+ { "quit", I_QUIT },
+ { "rename", I_RENAME },
+ { "rm", I_RM },
+ { "rmdir", I_RMDIR },
+ { "symlink", I_SYMLINK },
+ { "version", I_VERSION },
+ { "!", I_SHELL },
+ { "?", I_HELP },
+ { NULL, -1}
+};
+
+int interactive_loop(int fd_in, int fd_out, char *file1, char *file2);
+
+/* ARGSUSED */
+static void
+killchild(int signo)
+{
+ if (sshpid > 1) {
+ kill(sshpid, SIGTERM);
+ waitpid(sshpid, NULL, 0);
+ }
+
+ _exit(1);
+}
+
+/* ARGSUSED */
+static void
+cmd_interrupt(int signo)
+{
+ const char msg[] = "\rInterrupt \n";
+ int olderrno = errno;
+
+ write(STDERR_FILENO, msg, sizeof(msg) - 1);
+ interrupted = 1;
+ errno = olderrno;
+}
+
+static void
+help(void)
+{
+ printf(gettext("Available commands:\n"
+ "cd path Change remote directory to 'path'\n"
+ "lcd path Change local directory to 'path'\n"
+ "chgrp grp path Change group of file 'path' to 'grp'\n"
+ "chmod mode path Change permissions of file 'path' to 'mode'\n"
+ "chown own path Change owner of file 'path' to 'own'\n"
+ "help Display this help text\n"
+ "get remote-path [local-path] Download file\n"
+ "lls [ls-options [path]] Display local directory listing\n"
+ "ln oldpath newpath Symlink remote file\n"
+ "lmkdir path Create local directory\n"
+ "lpwd Print local working directory\n"
+ "ls [path] Display remote directory listing\n"
+ "lumask umask Set local umask to 'umask'\n"
+ "mkdir path Create remote directory\n"
+ "progress Toggle display of progress meter\n"
+ "put local-path [remote-path] Upload file\n"
+ "pwd Display remote working directory\n"
+ "exit Quit sftp\n"
+ "quit Quit sftp\n"
+ "rename oldpath newpath Rename remote file\n"
+ "rmdir path Remove remote directory\n"
+ "rm path Delete remote file\n"
+ "symlink oldpath newpath Symlink remote file\n"
+ "version Show SFTP version\n"
+ "!command Execute 'command' in local shell\n"
+ "! Escape to local shell\n"
+ "? Synonym for help\n"));
+}
+
+static void
+local_do_shell(const char *args)
+{
+ int status;
+ char *shell;
+ pid_t pid;
+
+ if (!*args)
+ args = NULL;
+
+ if ((shell = getenv("SHELL")) == NULL)
+ shell = _PATH_BSHELL;
+
+ if ((pid = fork()) == -1)
+ fatal("Couldn't fork: %s", strerror(errno));
+
+ if (pid == 0) {
+ /* XXX: child has pipe fds to ssh subproc open - issue? */
+ if (args) {
+ debug3("Executing %s -c \"%s\"", shell, args);
+ execl(shell, shell, "-c", args, (char *)NULL);
+ } else {
+ debug3("Executing %s", shell);
+ execl(shell, shell, (char *)NULL);
+ }
+ fprintf(stderr, gettext("Couldn't execute \"%s\": %s\n"), shell,
+ strerror(errno));
+ _exit(1);
+ }
+ while (waitpid(pid, &status, 0) == -1)
+ if (errno != EINTR)
+ fatal("Couldn't wait for child: %s", strerror(errno));
+ if (!WIFEXITED(status))
+ error("Shell exited abnormally");
+ else if (WEXITSTATUS(status))
+ error("Shell exited with status %d", WEXITSTATUS(status));
+}
+
+static void
+local_do_ls(const char *args)
+{
+ if (!args || !*args)
+ local_do_shell(_PATH_LS);
+ else {
+ int len = strlen(_PATH_LS " ") + strlen(args) + 1;
+ char *buf = xmalloc(len);
+
+ /* XXX: quoting - rip quoting code from ftp? */
+ snprintf(buf, len, _PATH_LS " %s", args);
+ local_do_shell(buf);
+ xfree(buf);
+ }
+}
+
+/* Strip one path (usually the pwd) from the start of another */
+static char *
+path_strip(char *path, char *strip)
+{
+ size_t len;
+
+ if (strip == NULL)
+ return (xstrdup(path));
+
+ len = strlen(strip);
+ if (strncmp(path, strip, len) == 0) {
+ if (strip[len - 1] != '/' && path[len] == '/')
+ len++;
+ return (xstrdup(path + len));
+ }
+
+ return (xstrdup(path));
+}
+
+static char *
+path_append(char *p1, char *p2)
+{
+ char *ret;
+ size_t len = strlen(p1) + strlen(p2) + 2;
+
+ ret = xmalloc(len);
+ strlcpy(ret, p1, len);
+ if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
+ strlcat(ret, "/", len);
+ strlcat(ret, p2, len);
+
+ return(ret);
+}
+
+static char *
+make_absolute(char *p, char *pwd)
+{
+ char *abs_str;
+
+ /* Derelativise */
+ if (p && p[0] != '/') {
+ abs_str = path_append(pwd, p);
+ xfree(p);
+ return(abs_str);
+ } else
+ return(p);
+}
+
+static int
+infer_path(const char *p, char **ifp)
+{
+ char *cp;
+
+ cp = strrchr(p, '/');
+ if (cp == NULL) {
+ *ifp = xstrdup(p);
+ return(0);
+ }
+
+ if (!cp[1]) {
+ error("Invalid path");
+ return(-1);
+ }
+
+ *ifp = xstrdup(cp + 1);
+ return(0);
+}
+
+static int
+parse_getput_flags(const char **cpp, int *pflag)
+{
+ const char *cp = *cpp;
+
+ /* Check for flags */
+ if (cp[0] == '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
+ switch (cp[1]) {
+ case 'p':
+ case 'P':
+ *pflag = 1;
+ break;
+ default:
+ error("Invalid flag -%c", cp[1]);
+ return(-1);
+ }
+ cp += 2;
+ *cpp = cp + strspn(cp, WHITESPACE);
+ }
+
+ return(0);
+}
+
+static int
+parse_ls_flags(const char **cpp, int *lflag)
+{
+ const char *cp = *cpp;
+
+ /* Defaults */
+ *lflag = LS_NAME_SORT;
+
+ /* Check for flags */
+ if (cp++[0] == '-') {
+ for (; strchr(WHITESPACE, *cp) == NULL; cp++) {
+ switch (*cp) {
+ case 'l':
+ *lflag &= ~VIEW_FLAGS;
+ *lflag |= LS_LONG_VIEW;
+ break;
+ case '1':
+ *lflag &= ~VIEW_FLAGS;
+ *lflag |= LS_SHORT_VIEW;
+ break;
+ case 'n':
+ *lflag &= ~VIEW_FLAGS;
+ *lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW;
+ break;
+ case 'S':
+ *lflag &= ~SORT_FLAGS;
+ *lflag |= LS_SIZE_SORT;
+ break;
+ case 't':
+ *lflag &= ~SORT_FLAGS;
+ *lflag |= LS_TIME_SORT;
+ break;
+ case 'r':
+ *lflag |= LS_REVERSE_SORT;
+ break;
+ case 'f':
+ *lflag &= ~SORT_FLAGS;
+ break;
+ case 'a':
+ *lflag |= LS_SHOW_ALL;
+ break;
+ default:
+ error("Invalid flag -%c", *cp);
+ return(-1);
+ }
+ }
+ *cpp = cp + strspn(cp, WHITESPACE);
+ }
+
+ return(0);
+}
+
+static int
+get_pathname(const char **cpp, char **path)
+{
+ const char *cp = *cpp, *end;
+ char quot;
+ u_int i, j;
+
+ cp += strspn(cp, WHITESPACE);
+ if (!*cp) {
+ *cpp = cp;
+ *path = NULL;
+ return (0);
+ }
+
+ *path = xmalloc(strlen(cp) + 1);
+
+ /* Check for quoted filenames */
+ if (*cp == '\"' || *cp == '\'') {
+ quot = *cp++;
+
+ /* Search for terminating quote, unescape some chars */
+ for (i = j = 0; i <= strlen(cp); i++) {
+ if (cp[i] == quot) { /* Found quote */
+ i++;
+ (*path)[j] = '\0';
+ break;
+ }
+ if (cp[i] == '\0') { /* End of string */
+ error("Unterminated quote");
+ goto fail;
+ }
+ if (cp[i] == '\\') { /* Escaped characters */
+ i++;
+ if (cp[i] != '\'' && cp[i] != '\"' &&
+ cp[i] != '\\') {
+ error("Bad escaped character '\\%c'",
+ cp[i]);
+ goto fail;
+ }
+ }
+ (*path)[j++] = cp[i];
+ }
+
+ if (j == 0) {
+ error("Empty quotes");
+ goto fail;
+ }
+ *cpp = cp + i + strspn(cp + i, WHITESPACE);
+ } else {
+ /* Read to end of filename */
+ end = strpbrk(cp, WHITESPACE);
+ if (end == NULL)
+ end = strchr(cp, '\0');
+ *cpp = end + strspn(end, WHITESPACE);
+
+ memcpy(*path, cp, end - cp);
+ (*path)[end - cp] = '\0';
+ }
+ return (0);
+
+ fail:
+ xfree(*path);
+ *path = NULL;
+ return (-1);
+}
+
+static int
+is_dir(char *path)
+{
+ struct stat sb;
+
+ /* XXX: report errors? */
+ if (stat(path, &sb) == -1)
+ return(0);
+
+ return(S_ISDIR(sb.st_mode));
+}
+
+static int
+is_reg(char *path)
+{
+ struct stat sb;
+
+ if (stat(path, &sb) == -1)
+ fatal("stat %s: %s", path, strerror(errno));
+
+ return(S_ISREG(sb.st_mode));
+}
+
+static int
+remote_is_dir(struct sftp_conn *conn, char *path)
+{
+ Attrib *a;
+
+ /* XXX: report errors? */
+ if ((a = do_stat(conn, path, 1)) == NULL)
+ return(0);
+ if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
+ return(0);
+ return(S_ISDIR(a->perm));
+}
+
+static int
+process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
+{
+ char *abs_src = NULL;
+ char *abs_dst = NULL;
+ char *tmp;
+ glob_t g;
+ int err = 0;
+ int i;
+
+ abs_src = xstrdup(src);
+ abs_src = make_absolute(abs_src, pwd);
+
+ memset(&g, 0, sizeof(g));
+ debug3("Looking up %s", abs_src);
+ if (remote_glob(conn, abs_src, 0, NULL, &g)) {
+ error("File \"%s\" not found.", abs_src);
+ err = -1;
+ goto out;
+ }
+
+ /* If multiple matches, dst must be a directory or unspecified */
+ if (g.gl_matchc > 1 && dst && !is_dir(dst)) {
+ error("Multiple files match, but \"%s\" is not a directory",
+ dst);
+ err = -1;
+ goto out;
+ }
+
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ if (infer_path(g.gl_pathv[i], &tmp)) {
+ err = -1;
+ goto out;
+ }
+
+ if (g.gl_matchc == 1 && dst) {
+ /* If directory specified, append filename */
+ xfree(tmp);
+ if (is_dir(dst)) {
+ if (infer_path(g.gl_pathv[0], &tmp)) {
+ err = 1;
+ goto out;
+ }
+ abs_dst = path_append(dst, tmp);
+ xfree(tmp);
+ } else
+ abs_dst = xstrdup(dst);
+ } else if (dst) {
+ abs_dst = path_append(dst, tmp);
+ xfree(tmp);
+ } else
+ abs_dst = tmp;
+
+ printf(gettext("Fetching %s to %s\n"), g.gl_pathv[i], abs_dst);
+ if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
+ err = -1;
+ xfree(abs_dst);
+ abs_dst = NULL;
+ }
+
+out:
+ xfree(abs_src);
+ globfree(&g);
+ return(err);
+}
+
+static int
+process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
+{
+ char *tmp_dst = NULL;
+ char *abs_dst = NULL;
+ char *tmp;
+ glob_t g;
+ int err = 0;
+ int i;
+
+ if (dst) {
+ tmp_dst = xstrdup(dst);
+ tmp_dst = make_absolute(tmp_dst, pwd);
+ }
+
+ memset(&g, 0, sizeof(g));
+ debug3("Looking up %s", src);
+ if (glob(src, 0, NULL, &g)) {
+ error("File \"%s\" not found.", src);
+ err = -1;
+ goto out;
+ }
+
+ /* If multiple matches, dst may be directory or unspecified */
+ if (g.gl_matchc > 1 && tmp_dst && !remote_is_dir(conn, tmp_dst)) {
+ error("Multiple files match, but \"%s\" is not a directory",
+ tmp_dst);
+ err = -1;
+ goto out;
+ }
+
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ if (!is_reg(g.gl_pathv[i])) {
+ error("skipping non-regular file %s",
+ g.gl_pathv[i]);
+ continue;
+ }
+ if (infer_path(g.gl_pathv[i], &tmp)) {
+ err = -1;
+ goto out;
+ }
+
+ if (g.gl_matchc == 1 && tmp_dst) {
+ /* If directory specified, append filename */
+ if (remote_is_dir(conn, tmp_dst)) {
+ if (infer_path(g.gl_pathv[0], &tmp)) {
+ err = 1;
+ goto out;
+ }
+ abs_dst = path_append(tmp_dst, tmp);
+ xfree(tmp);
+ } else
+ abs_dst = xstrdup(tmp_dst);
+
+ } else if (tmp_dst) {
+ abs_dst = path_append(tmp_dst, tmp);
+ xfree(tmp);
+ } else
+ abs_dst = make_absolute(tmp, pwd);
+
+ printf(gettext("Uploading %s to %s\n"), g.gl_pathv[i], abs_dst);
+ if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
+ err = -1;
+ }
+
+out:
+ if (abs_dst)
+ xfree(abs_dst);
+ if (tmp_dst)
+ xfree(tmp_dst);
+ globfree(&g);
+ return(err);
+}
+
+static int
+sdirent_comp(const void *aa, const void *bb)
+{
+ SFTP_DIRENT *a = *(SFTP_DIRENT **)aa;
+ SFTP_DIRENT *b = *(SFTP_DIRENT **)bb;
+ int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
+
+#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
+ if (sort_flag & LS_NAME_SORT)
+ return (rmul * strcmp(a->filename, b->filename));
+ else if (sort_flag & LS_TIME_SORT)
+ return (rmul * NCMP(a->a.mtime, b->a.mtime));
+ else if (sort_flag & LS_SIZE_SORT)
+ return (rmul * NCMP(a->a.size, b->a.size));
+
+ fatal("Unknown ls sort type");
+
+ /* NOTREACHED */
+ return (0);
+}
+
+/* sftp ls.1 replacement for directories */
+static int
+do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
+{
+ int n;
+ u_int c = 1, colspace = 0, columns = 1;
+ SFTP_DIRENT **d;
+
+ if ((n = do_readdir(conn, path, &d)) != 0)
+ return (n);
+
+ if (!(lflag & LS_SHORT_VIEW)) {
+ u_int m = 0, width = 80;
+ struct winsize ws;
+ char *tmp;
+
+ /* Count entries for sort and find longest filename */
+ for (n = 0; d[n] != NULL; n++) {
+ if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL))
+ m = MAX(m, strlen(d[n]->filename));
+ }
+
+ /* Add any subpath that also needs to be counted */
+ tmp = path_strip(path, strip_path);
+ m += strlen(tmp);
+ xfree(tmp);
+
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
+ width = ws.ws_col;
+
+ columns = width / (m + 2);
+ columns = MAX(columns, 1);
+ colspace = width / columns;
+ colspace = MIN(colspace, width);
+ }
+
+ if (lflag & SORT_FLAGS) {
+ for (n = 0; d[n] != NULL; n++)
+ ; /* count entries */
+ sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
+ qsort(d, n, sizeof(*d), sdirent_comp);
+ }
+
+ for (n = 0; d[n] != NULL && !interrupted; n++) {
+ char *tmp, *fname;
+
+ if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL))
+ continue;
+
+ tmp = path_append(path, d[n]->filename);
+ fname = path_strip(tmp, strip_path);
+ xfree(tmp);
+
+ if (lflag & LS_LONG_VIEW) {
+ if (lflag & LS_NUMERIC_VIEW) {
+ char *lname;
+ struct stat sb;
+
+ memset(&sb, 0, sizeof(sb));
+ attrib_to_stat(&d[n]->a, &sb);
+ lname = ls_file(fname, &sb, 1);
+ printf("%s\n", lname);
+ xfree(lname);
+ } else
+ printf("%s\n", d[n]->longname);
+ } else {
+ printf("%-*s", colspace, fname);
+ if (c >= columns) {
+ printf("\n");
+ c = 1;
+ } else
+ c++;
+ }
+
+ xfree(fname);
+ }
+
+ if (!(lflag & LS_LONG_VIEW) && (c != 1))
+ printf("\n");
+
+ free_sftp_dirents(d);
+ return (0);
+}
+
+/* sftp ls.1 replacement which handles path globs */
+static int
+do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
+ int lflag)
+{
+ glob_t g;
+ u_int i, c = 1, colspace = 0, columns = 1;
+ Attrib *a = NULL;
+
+ memset(&g, 0, sizeof(g));
+
+ if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
+ NULL, &g) || (g.gl_pathc && !g.gl_matchc)) {
+ if (g.gl_pathc)
+ globfree(&g);
+ error("Can't ls: \"%s\" not found", path);
+ return (-1);
+ }
+
+ if (interrupted)
+ goto out;
+
+ /*
+ * If the glob returns a single match and it is a directory,
+ * then just list its contents.
+ */
+ if (g.gl_matchc == 1) {
+ if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) {
+ globfree(&g);
+ return (-1);
+ }
+ if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
+ S_ISDIR(a->perm)) {
+ int err;
+
+ err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
+ globfree(&g);
+ return (err);
+ }
+ }
+
+ if (!(lflag & LS_SHORT_VIEW)) {
+ u_int m = 0, width = 80;
+ struct winsize ws;
+
+ /* Count entries for sort and find longest filename */
+ for (i = 0; g.gl_pathv[i]; i++)
+ m = MAX(m, strlen(g.gl_pathv[i]));
+
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
+ width = ws.ws_col;
+
+ columns = width / (m + 2);
+ columns = MAX(columns, 1);
+ colspace = width / columns;
+ }
+
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) {
+ char *fname;
+
+ fname = path_strip(g.gl_pathv[i], strip_path);
+
+ if (lflag & LS_LONG_VIEW) {
+ char *lname;
+ struct stat sb;
+
+ /*
+ * XXX: this is slow - 1 roundtrip per path
+ * A solution to this is to fork glob() and
+ * build a sftp specific version which keeps the
+ * attribs (which currently get thrown away)
+ * that the server returns as well as the filenames.
+ */
+ memset(&sb, 0, sizeof(sb));
+ if (a == NULL)
+ a = do_lstat(conn, g.gl_pathv[i], 1);
+ if (a != NULL)
+ attrib_to_stat(a, &sb);
+ lname = ls_file(fname, &sb, 1);
+ printf("%s\n", lname);
+ xfree(lname);
+ } else {
+ printf("%-*s", colspace, fname);
+ if (c >= columns) {
+ printf("\n");
+ c = 1;
+ } else
+ c++;
+ }
+ xfree(fname);
+ }
+
+ if (!(lflag & LS_LONG_VIEW) && (c != 1))
+ printf("\n");
+
+ out:
+ if (g.gl_pathc)
+ globfree(&g);
+
+ return (0);
+}
+
+static int
+parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
+ unsigned long *n_arg, char **path1, char **path2)
+{
+ const char *cmd, *cp = *cpp;
+ char *cp2;
+ int base = 0;
+ long l;
+ int i, cmdnum;
+
+ /* Skip leading whitespace */
+ cp = cp + strspn(cp, WHITESPACE);
+
+ /* Ignore blank lines and lines which begin with comment '#' char */
+ if (*cp == '\0' || *cp == '#')
+ return (0);
+
+ /* Check for leading '-' (disable error processing) */
+ *iflag = 0;
+ if (*cp == '-') {
+ *iflag = 1;
+ cp++;
+ }
+
+ /* Figure out which command we have */
+ for (i = 0; cmds[i].c; i++) {
+ int cmdlen = strlen(cmds[i].c);
+
+ /* Check for command followed by whitespace */
+ if (!strncasecmp(cp, cmds[i].c, cmdlen) &&
+ strchr(WHITESPACE, cp[cmdlen])) {
+ cp += cmdlen;
+ cp = cp + strspn(cp, WHITESPACE);
+ break;
+ }
+ }
+ cmdnum = cmds[i].n;
+ cmd = cmds[i].c;
+
+ /* Special case */
+ if (*cp == '!') {
+ cp++;
+ cmdnum = I_SHELL;
+ } else if (cmdnum == -1) {
+ error("Invalid command.");
+ return (-1);
+ }
+
+ /* Get arguments and parse flags */
+ *lflag = *pflag = *n_arg = 0;
+ *path1 = *path2 = NULL;
+ switch (cmdnum) {
+ case I_GET:
+ case I_PUT:
+ if (parse_getput_flags(&cp, pflag))
+ return(-1);
+ /* Get first pathname (mandatory) */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (*path1 == NULL) {
+ error("You must specify at least one path after a "
+ "%s command.", cmd);
+ return(-1);
+ }
+ /* Try to get second pathname (optional) */
+ if (get_pathname(&cp, path2))
+ return(-1);
+ break;
+ case I_RENAME:
+ case I_SYMLINK:
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (get_pathname(&cp, path2))
+ return(-1);
+ if (!*path1 || !*path2) {
+ error("You must specify two paths after a %s "
+ "command.", cmd);
+ return(-1);
+ }
+ break;
+ case I_RM:
+ case I_MKDIR:
+ case I_RMDIR:
+ case I_CHDIR:
+ case I_LCHDIR:
+ case I_LMKDIR:
+ /* Get pathname (mandatory) */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (*path1 == NULL) {
+ error("You must specify a path after a %s command.",
+ cmd);
+ return(-1);
+ }
+ break;
+ case I_LS:
+ if (parse_ls_flags(&cp, lflag))
+ return(-1);
+ /* Path is optional */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ break;
+ case I_LLS:
+ case I_SHELL:
+ /* Uses the rest of the line */
+ break;
+ case I_LUMASK:
+ base = 8;
+ /* FALLTHRU */
+ case I_CHMOD:
+ base = 8;
+ /* FALLTHRU */
+ case I_CHOWN:
+ case I_CHGRP:
+ /* Get numeric arg (mandatory) */
+ errno = 0;
+ l = strtol(cp, &cp2, base);
+ if (cp2 == cp || ((l == LONG_MIN || l == LONG_MAX) &&
+ errno == ERANGE) || l < 0) {
+ error("You must supply a numeric argument "
+ "to the %s command.", cmd);
+ return(-1);
+ }
+ cp = cp2;
+ *n_arg = l;
+ if (cmdnum == I_LUMASK && strchr(WHITESPACE, *cp))
+ break;
+ if (cmdnum == I_LUMASK || !strchr(WHITESPACE, *cp)) {
+ error("You must supply a numeric argument "
+ "to the %s command.", cmd);
+ return(-1);
+ }
+ cp += strspn(cp, WHITESPACE);
+
+ /* Get pathname (mandatory) */
+ if (get_pathname(&cp, path1))
+ return(-1);
+ if (*path1 == NULL) {
+ error("You must specify a path after a %s command.",
+ cmd);
+ return(-1);
+ }
+ break;
+ case I_QUIT:
+ case I_PWD:
+ case I_LPWD:
+ case I_HELP:
+ case I_VERSION:
+ case I_PROGRESS:
+ break;
+ default:
+ fatal("Command not implemented");
+ }
+
+ *cpp = cp;
+ return(cmdnum);
+}
+
+static int
+parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
+ int err_abort)
+{
+ char *path1, *path2, *tmp;
+ int pflag, lflag, iflag, cmdnum, i;
+ unsigned long n_arg;
+ Attrib a, *aa;
+ char path_buf[MAXPATHLEN];
+ int err = 0;
+ glob_t g;
+
+ path1 = path2 = NULL;
+ cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg,
+ &path1, &path2);
+
+ if (iflag != 0)
+ err_abort = 0;
+
+ memset(&g, 0, sizeof(g));
+
+ /* Perform command */
+ switch (cmdnum) {
+ case 0:
+ /* Blank line */
+ break;
+ case -1:
+ /* Unrecognized command */
+ err = -1;
+ break;
+ case I_GET:
+ err = process_get(conn, path1, path2, *pwd, pflag);
+ break;
+ case I_PUT:
+ err = process_put(conn, path1, path2, *pwd, pflag);
+ break;
+ case I_RENAME:
+ path1 = make_absolute(path1, *pwd);
+ path2 = make_absolute(path2, *pwd);
+ err = do_rename(conn, path1, path2);
+ break;
+ case I_SYMLINK:
+ path2 = make_absolute(path2, *pwd);
+ err = do_symlink(conn, path1, path2);
+ break;
+ case I_RM:
+ path1 = make_absolute(path1, *pwd);
+ remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ printf(gettext("Removing %s\n"), g.gl_pathv[i]);
+ err = do_rm(conn, g.gl_pathv[i]);
+ if (err != 0 && err_abort)
+ break;
+ }
+ break;
+ case I_MKDIR:
+ path1 = make_absolute(path1, *pwd);
+ attrib_clear(&a);
+ a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
+ a.perm = 0777;
+ err = do_mkdir(conn, path1, &a);
+ break;
+ case I_RMDIR:
+ path1 = make_absolute(path1, *pwd);
+ err = do_rmdir(conn, path1);
+ break;
+ case I_CHDIR:
+ path1 = make_absolute(path1, *pwd);
+ if ((tmp = do_realpath(conn, path1)) == NULL) {
+ err = 1;
+ break;
+ }
+ if ((aa = do_stat(conn, tmp, 0)) == NULL) {
+ xfree(tmp);
+ err = 1;
+ break;
+ }
+ if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
+ error("Can't change directory: Can't check target");
+ xfree(tmp);
+ err = 1;
+ break;
+ }
+ if (!S_ISDIR(aa->perm)) {
+ error("Can't change directory: \"%s\" is not "
+ "a directory", tmp);
+ xfree(tmp);
+ err = 1;
+ break;
+ }
+ xfree(*pwd);
+ *pwd = tmp;
+ break;
+ case I_LS:
+ if (!path1) {
+ do_globbed_ls(conn, *pwd, *pwd, lflag);
+ break;
+ }
+
+ /* Strip pwd off beginning of non-absolute paths */
+ tmp = NULL;
+ if (*path1 != '/')
+ tmp = *pwd;
+
+ path1 = make_absolute(path1, *pwd);
+ err = do_globbed_ls(conn, path1, tmp, lflag);
+ break;
+ case I_LCHDIR:
+ if (chdir(path1) == -1) {
+ error("Couldn't change local directory to "
+ "\"%s\": %s", path1, strerror(errno));
+ err = 1;
+ }
+ break;
+ case I_LMKDIR:
+ if (mkdir(path1, 0777) == -1) {
+ error("Couldn't create local directory "
+ "\"%s\": %s", path1, strerror(errno));
+ err = 1;
+ }
+ break;
+ case I_LLS:
+ local_do_ls(cmd);
+ break;
+ case I_SHELL:
+ local_do_shell(cmd);
+ break;
+ case I_LUMASK:
+ umask(n_arg);
+ printf(gettext("Local umask: %03lo\n"), n_arg);
+ break;
+ case I_CHMOD:
+ path1 = make_absolute(path1, *pwd);
+ attrib_clear(&a);
+ a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
+ a.perm = n_arg;
+ remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ printf(gettext("Changing mode on %s\n"), g.gl_pathv[i]);
+ err = do_setstat(conn, g.gl_pathv[i], &a);
+ if (err != 0 && err_abort)
+ break;
+ }
+ break;
+ case I_CHOWN:
+ case I_CHGRP:
+ path1 = make_absolute(path1, *pwd);
+ remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
+ if (err != 0 && err_abort)
+ break;
+ else
+ continue;
+ }
+ if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
+ error("Can't get current ownership of "
+ "remote file \"%s\"", g.gl_pathv[i]);
+ if (err != 0 && err_abort)
+ break;
+ else
+ continue;
+ }
+ aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
+ if (cmdnum == I_CHOWN) {
+ printf(gettext("Changing owner on %s\n"), g.gl_pathv[i]);
+ aa->uid = n_arg;
+ } else {
+ printf(gettext("Changing group on %s\n"), g.gl_pathv[i]);
+ aa->gid = n_arg;
+ }
+ err = do_setstat(conn, g.gl_pathv[i], aa);
+ if (err != 0 && err_abort)
+ break;
+ }
+ break;
+ case I_PWD:
+ printf(gettext("Remote working directory: %s\n"), *pwd);
+ break;
+ case I_LPWD:
+ if (!getcwd(path_buf, sizeof(path_buf))) {
+ error("Couldn't get local cwd: %s", strerror(errno));
+ err = -1;
+ break;
+ }
+ printf(gettext("Local working directory: %s\n"), path_buf);
+ break;
+ case I_QUIT:
+ /* Processed below */
+ break;
+ case I_HELP:
+ help();
+ break;
+ case I_VERSION:
+ printf(gettext("SFTP protocol version %u\n"), sftp_proto_version(conn));
+ break;
+ case I_PROGRESS:
+ showprogress = !showprogress;
+ if (showprogress)
+ printf("Progress meter enabled\n");
+ else
+ printf("Progress meter disabled\n");
+ break;
+ default:
+ fatal("%d is not implemented", cmdnum);
+ }
+
+ if (g.gl_pathc)
+ globfree(&g);
+ if (path1)
+ xfree(path1);
+ if (path2)
+ xfree(path2);
+
+ /* If an unignored error occurs in batch mode we should abort. */
+ if (err_abort && err != 0)
+ return (-1);
+ else if (cmdnum == I_QUIT)
+ return (1);
+
+ return (0);
+}
+
+#ifdef USE_LIBEDIT
+static char *
+prompt(EditLine *el)
+{
+ return ("sftp> ");
+}
+#endif
+
+int
+interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
+{
+ char *pwd;
+ char *dir = NULL;
+ char cmd[2048];
+ struct sftp_conn *conn;
+ int err, interactive;
+ EditLine *el = NULL;
+#ifdef USE_LIBEDIT
+ History *hl = NULL;
+ HistEvent hev;
+
+ if (!batchmode && isatty(STDIN_FILENO)) {
+ if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL)
+ fatal("Couldn't initialise editline");
+ if ((hl = history_init()) == NULL)
+ fatal("Couldn't initialise editline history");
+ history(hl, &hev, H_SETSIZE, 100);
+ el_set(el, EL_HIST, history, hl);
+
+ el_set(el, EL_PROMPT, prompt);
+ el_set(el, EL_EDITOR, "emacs");
+ el_set(el, EL_TERMINAL, NULL);
+ el_set(el, EL_SIGNAL, 1);
+ el_source(el, NULL);
+ }
+#endif /* USE_LIBEDIT */
+
+ conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
+ if (conn == NULL)
+ fatal("Couldn't initialise connection to server");
+
+ pwd = do_realpath(conn, ".");
+ if (pwd == NULL)
+ fatal("Need cwd");
+
+ if (file1 != NULL) {
+ dir = xstrdup(file1);
+ dir = make_absolute(dir, pwd);
+
+ if (remote_is_dir(conn, dir) && file2 == NULL) {
+ printf(gettext("Changing to: %s\n"), dir);
+ snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
+ if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) {
+ xfree(dir);
+ xfree(pwd);
+ xfree(conn);
+ return (-1);
+ }
+ } else {
+ if (file2 == NULL)
+ snprintf(cmd, sizeof cmd, "get %s", dir);
+ else
+ snprintf(cmd, sizeof cmd, "get %s %s", dir,
+ file2);
+
+ err = parse_dispatch_command(conn, cmd, &pwd, 1);
+ xfree(dir);
+ xfree(pwd);
+ xfree(conn);
+ return (err);
+ }
+ xfree(dir);
+ }
+
+#if defined(HAVE_SETVBUF) && !defined(BROKEN_SETVBUF)
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ setvbuf(infile, NULL, _IOLBF, 0);
+#else
+ setlinebuf(stdout);
+ setlinebuf(infile);
+#endif
+
+ interactive = !batchmode && isatty(STDIN_FILENO);
+ err = 0;
+ for (;;) {
+ char *cp;
+
+ signal(SIGINT, SIG_IGN);
+
+ if (el == NULL) {
+ if (interactive)
+ printf("sftp> ");
+ if (fgets(cmd, sizeof(cmd), infile) == NULL) {
+ if (interactive)
+ printf("\n");
+ break;
+ }
+ if (!interactive) { /* Echo command */
+ printf("sftp> %s", cmd);
+ if (strlen(cmd) > 0 &&
+ cmd[strlen(cmd) - 1] != '\n')
+ printf("\n");
+ }
+ }
+#ifdef USE_LIBEDIT
+ else {
+ const char *line;
+ int count = 0;
+
+ if ((line = el_gets(el, &count)) == NULL || count <= 0) {
+ printf("\n");
+ break;
+ }
+ history(hl, &hev, H_ENTER, line);
+ if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {
+ fprintf(stderr, gettext("Error: input line too long\n"));
+ continue;
+ }
+ }
+#endif /* USE_LIBEDIT */
+
+ cp = strrchr(cmd, '\n');
+ if (cp)
+ *cp = '\0';
+
+ /* Handle user interrupts gracefully during commands */
+ interrupted = 0;
+ signal(SIGINT, cmd_interrupt);
+
+ err = parse_dispatch_command(conn, cmd, &pwd, batchmode);
+ if (err != 0)
+ break;
+ }
+ xfree(pwd);
+ xfree(conn);
+
+#ifdef USE_LIBEDIT
+ if (el != NULL)
+ el_end(el);
+#endif /* USE_LIBEDIT */
+
+ /* err == 1 signifies normal "quit" exit */
+ return (err >= 0 ? 0 : -1);
+}
+
static void
-connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid)
+connect_to_server(char *path, char **args, int *in, int *out)
{
int c_in, c_out;
@@ -78,23 +1426,34 @@ connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid)
c_in = c_out = inout[1];
#endif /* USE_PIPES */
- if ((*sshpid = fork()) == -1)
+ if ((sshpid = fork()) == -1)
fatal("fork: %s", strerror(errno));
- else if (*sshpid == 0) {
+ else if (sshpid == 0) {
if ((dup2(c_in, STDIN_FILENO) == -1) ||
(dup2(c_out, STDOUT_FILENO) == -1)) {
fprintf(stderr, "dup2: %s\n", strerror(errno));
- exit(1);
+ _exit(1);
}
close(*in);
close(*out);
close(c_in);
close(c_out);
- execv(path, args);
+
+ /*
+ * The underlying ssh is in the same process group, so we must
+ * ignore SIGINT if we want to gracefully abort commands,
+ * otherwise the signal will make it to the ssh process and
+ * kill it too
+ */
+ signal(SIGINT, SIG_IGN);
+ execvp(path, args);
fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
- exit(1);
+ _exit(1);
}
+ signal(SIGTERM, killchild);
+ signal(SIGINT, killchild);
+ signal(SIGHUP, killchild);
close(c_in);
close(c_out);
}
@@ -102,24 +1461,20 @@ connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid)
static void
usage(void)
{
- extern char *__progname;
-
fprintf(stderr,
- gettext("Usage: %s [-vC1] [-b batchfile] [-o option] "
- "[-s subsystem|path]\n"
- " [-F config] [-P direct server path] [-S program] "
- "[-B buffer_size]\n"
- " [-R num_requests] [user@]host[:file [file]]\n"),
- __progname);
+ gettext("Usage: %s [-1Cv] [-b batchfile] [-B buffer_size]\n"
+ " [-F ssh_config] [-o ssh_option] [-P sftp_server_path]\n"
+ " [-R num_requests] [-s subsystem | sftp_server]\n"
+ " [-S program] [user@]host[:dir[/] | :file [file]]\n"),
+ __progname, __progname, __progname, __progname);
exit(1);
}
int
main(int argc, char **argv)
{
- int in, out, ch;
- pid_t sshpid;
- char *host, *userhost, *cp, *file2;
+ int in, out, ch, err;
+ char *host, *userhost, *cp, *file2 = NULL;
int debug_level = 0, sshver = 2;
char *file1 = NULL, *sftp_server = NULL;
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
@@ -128,16 +1483,22 @@ main(int argc, char **argv)
extern int optind;
extern char *optarg;
+ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+ sanitise_stdfd();
+
__progname = get_progname(argv[0]);
(void) g11n_setlocale(LC_ALL, "");
+
+ memset(&args, '\0', sizeof(args));
args.list = NULL;
- addargs(&args, "ssh"); /* overwritten with ssh_program */
+ addargs(&args, "%s", ssh_program);
addargs(&args, "-oForwardX11 no");
addargs(&args, "-oForwardAgent no");
addargs(&args, "-oClearAllForwardings yes");
+
ll = SYSLOG_LEVEL_INFO;
- infile = stdin; /* Read from STDIN unless changed by -b */
+ infile = stdin;
while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) {
switch (ch) {
@@ -165,14 +1526,19 @@ main(int argc, char **argv)
break;
case 'S':
ssh_program = optarg;
+ replacearg(&args, 0, "%s", ssh_program);
break;
case 'b':
- if (infile == stdin) {
- infile = fopen(optarg, "r");
- if (infile == NULL)
- fatal("%s (%s).", strerror(errno), optarg);
- } else
- fatal("Filename already specified.");
+ if (batchmode)
+ fatal("Batch file already specified.");
+
+ /* Allow "-" as stdin */
+ if (strcmp(optarg, "-") != 0 &&
+ (infile = fopen(optarg, "r")) == NULL)
+ fatal("%s (%s).", strerror(errno), optarg);
+ showprogress = 0;
+ batchmode = 1;
+ addargs(&args, "-obatchmode yes");
break;
case 'P':
sftp_direct = optarg;
@@ -194,6 +1560,9 @@ main(int argc, char **argv)
}
}
+ if (!isatty(STDERR_FILENO))
+ showprogress = 0;
+
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
if (sftp_direct == NULL) {
@@ -203,12 +1572,7 @@ main(int argc, char **argv)
userhost = xstrdup(argv[optind]);
file2 = argv[optind+1];
- if ((cp = colon(userhost)) != NULL) {
- *cp++ = '\0';
- file1 = cp;
- }
-
- if ((host = strchr(userhost, '@')) == NULL)
+ if ((host = strrchr(userhost, '@')) == NULL)
host = userhost;
else {
*host++ = '\0';
@@ -216,7 +1580,12 @@ main(int argc, char **argv)
fprintf(stderr, gettext("Missing username\n"));
usage();
}
- addargs(&args, "-l%s",userhost);
+ addargs(&args, "-l%s", userhost);
+ }
+
+ if ((cp = colon(host)) != NULL) {
+ *cp++ = '\0';
+ file1 = cp;
}
host = cleanhostname(host);
@@ -234,21 +1603,21 @@ main(int argc, char **argv)
addargs(&args, "%s", host);
addargs(&args, "%s", (sftp_server != NULL ?
sftp_server : "sftp"));
- args.list[0] = ssh_program;
- fprintf(stderr, gettext("Connecting to %s...\n"), host);
- connect_to_server(ssh_program, args.list, &in, &out,
- &sshpid);
+ if (!batchmode)
+ fprintf(stderr, gettext("Connecting to %s...\n"), host);
+ connect_to_server(ssh_program, args.list, &in, &out);
} else {
args.list = NULL;
addargs(&args, "sftp-server");
- fprintf(stderr, gettext("Attaching to %s...\n"), sftp_direct);
- connect_to_server(sftp_direct, args.list, &in, &out,
- &sshpid);
+ if (!batchmode)
+ fprintf(stderr, gettext("Attaching to %s...\n"), sftp_direct);
+ connect_to_server(sftp_direct, args.list, &in, &out);
}
+ freeargs(&args);
- interactive_loop(in, out, file1, file2);
+ err = interactive_loop(in, out, file1, file2);
#if !defined(USE_PIPES)
shutdown(in, SHUT_RDWR);
@@ -257,7 +1626,7 @@ main(int argc, char **argv)
close(in);
close(out);
- if (infile != stdin)
+ if (batchmode)
fclose(infile);
while (waitpid(sshpid, NULL, 0) == -1)
@@ -265,5 +1634,5 @@ main(int argc, char **argv)
fatal("Couldn't wait for ssh process: %s",
strerror(errno));
- return (0);
+ return (err == 0 ? 0 : 1);
}
diff --git a/usr/src/cmd/ssh/ssh.po b/usr/src/cmd/ssh/ssh.po
index ff264a13ca..0bb056d810 100644
--- a/usr/src/cmd/ssh/ssh.po
+++ b/usr/src/cmd/ssh/ssh.po
@@ -4,6 +4,7 @@
#
#pragma ident "%Z%%M% %I% %E% SMI"
#
+
#
# File: ../common/bsd-arc4random.c, line: 76
#, c-format
@@ -239,34 +240,34 @@ msgstr ""
msgid "buffer_get_char: buffer error"
msgstr ""
#
-# File: ../common/buffer.c, line: 86
+# File: ../common/buffer.c, line: 107
#, c-format
msgid "buffer_append_space: len %u not supported"
msgstr ""
#
-# File: ../common/buffer.c, line: 116
+# File: ../common/buffer.c, line: 129
#, c-format
msgid "buffer_append_space: alloc %u not supported"
msgstr ""
#
-# File: ../common/buffer.c, line: 138
+# File: ../common/buffer.c, line: 173
#, c-format
msgid "buffer_get_ret: trying to get more bytes %d than in buffer %d"
msgstr ""
#
-# File: ../common/buffer.c, line: 151
+# File: ../common/buffer.c, line: 186
msgid "buffer_get: buffer error"
msgstr ""
#
-# File: ../common/buffer.c, line: 160
+# File: ../common/buffer.c, line: 195
msgid "buffer_consume_ret: trying to get more bytes than in buffer"
msgstr ""
#
-# File: ../common/buffer.c, line: 171
+# File: ../common/buffer.c, line: 206
msgid "buffer_consume: buffer error"
msgstr ""
#
-# File: ../common/buffer.c, line: 189
+# File: ../common/buffer.c, line: 224
msgid "buffer_consume_end: trying to get more bytes than in buffer"
msgstr ""
#
@@ -289,97 +290,123 @@ msgstr ""
msgid "get_sock_port: getnameinfo NI_NUMERICSERV failed"
msgstr ""
#
-# File: ../common/channels.c, line: 196
+# File: ../common/channels.c, line: 197
#, c-format
msgid "channel %d: wfd %d is not a tty?"
msgstr ""
#
-# File: ../common/channels.c, line: 247
+# File: ../common/channels.c, line: 248
#, c-format
msgid "channel_new: internal error: channels_alloc %d too big."
msgstr ""
#
-# File: ../common/channels.c, line: 467
+# File: ../common/channels.c, line: 468
msgid "cannot happen: SSH_CHANNEL_LARVAL"
msgstr ""
#
-# File: ../common/channels.c, line: 476
-# File: ../common/channels.c, line: 516
+# File: ../common/channels.c, line: 477
+# File: ../common/channels.c, line: 517
msgid "cannot happen: OUT_DRAIN"
msgstr ""
#
-# File: ../common/channels.c, line: 479
+# File: ../common/channels.c, line: 480
#, c-format
msgid "channel_still_open: bad channel type %d"
msgstr ""
#
-# File: ../common/channels.c, line: 519
+# File: ../common/channels.c, line: 520
#, c-format
msgid "channel_find_open: bad channel type %d"
msgstr ""
#
-# File: ../common/channels.c, line: 574
+# File: ../common/channels.c, line: 575
#, c-format
msgid "channel_open_message: bad channel type %d"
msgstr ""
#
-# File: ../common/channels.c, line: 669
+# File: ../common/channels.c, line: 670
#, c-format
msgid "channel_activate for non-larval channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 685
+# File: ../common/channels.c, line: 686
#, c-format
msgid "channel_set_wait_for_exit for non-open channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 835
+# File: ../common/channels.c, line: 836
#, c-format
msgid "X11 fake_data_len %d != saved_data_len %d"
msgstr ""
#
-# File: ../common/channels.c, line: 947
+# File: ../common/channels.c, line: 948
#, c-format
msgid "channel %d: decode socks4: len %d > have %d"
msgstr ""
#
+# File: ../common/channels.c, line: 1013
+#, c-format
+msgid "channel %d: socks5 authentication methods not implemented"
+msgstr ""
+#
+# File: ../common/channels.c, line: 1015
+#, c-format
+msgid ""
+"channel %d: forwarding failed: SSH_SOCKS5_NOAUTH method not found"
+msgstr ""
+#
# File: ../common/channels.c, line: 1034
-# File: ../common/channels.c, line: 1158
+#, c-format
+msgid "channel %d: forwarding failed: only socks5 connect is supported"
+msgstr ""
+#
+# File: ../common/channels.c, line: 1052
+#, c-format
+msgid "channel %d: forwarding failed: bad socks5 atyp %d"
+msgstr ""
+#
+# File: ../common/channels.c, line: 1117
+#, c-format
+msgid "channel %d: forwarding failed: unknown socks version 0x%02X"
+msgstr ""
+#
+# File: ../common/channels.c, line: 1156
+# File: ../common/channels.c, line: 1280
# File: sshd.c, line: 1489
#, c-format
msgid "accept: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 1202
+# File: ../common/channels.c, line: 1324
#, c-format
msgid "accept from auth socket: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 1233
+# File: ../common/channels.c, line: 1355
msgid "getsockopt SO_ERROR failed"
msgstr ""
#
-# File: ../common/channels.c, line: 1685
+# File: ../common/channels.c, line: 1807
msgid "cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"
msgstr ""
#
-# File: ../common/channels.c, line: 1738
+# File: ../common/channels.c, line: 1860
#, c-format
msgid "Received data for nonexistent channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1765
-# File: ../common/channels.c, line: 1803
-# File: ../common/channels.c, line: 1823
-# File: ../common/channels.c, line: 1846
-# File: ../common/channels.c, line: 1886
-# File: ../common/channels.c, line: 1898
-# File: ../common/channels.c, line: 1936
-# File: ../common/channels.c, line: 1981
-# File: ../common/channels.c, line: 2006
-# File: ../common/channels.c, line: 2028
-# File: ../common/channels.c, line: 2634
-# File: ../common/channels.c, line: 2777
+# File: ../common/channels.c, line: 1887
+# File: ../common/channels.c, line: 1925
+# File: ../common/channels.c, line: 1945
+# File: ../common/channels.c, line: 1968
+# File: ../common/channels.c, line: 2008
+# File: ../common/channels.c, line: 2020
+# File: ../common/channels.c, line: 2058
+# File: ../common/channels.c, line: 2103
+# File: ../common/channels.c, line: 2128
+# File: ../common/channels.c, line: 2150
+# File: ../common/channels.c, line: 2756
+# File: ../common/channels.c, line: 2895
# File: ../common/kex.c, line: 175
# File: ../common/kex.c, line: 248
# File: ../common/kexdhc.c, line: 88
@@ -389,37 +416,15 @@ msgstr ""
# File: ../common/kexgexs.c, line: 81
# File: ../common/kexgexs.c, line: 111
# File: ../common/packet.c, line: 807
-# File: ssh.c, line: 993
-# File: ssh.c, line: 1041
-# File: sshconnect1.c, line: 122
-# File: sshconnect1.c, line: 260
-# File: sshconnect1.c, line: 377
-# File: sshconnect1.c, line: 437
-# File: sshconnect1.c, line: 560
-# File: sshconnect2.c, line: 326
-# File: sshconnect2.c, line: 439
-# File: sshconnect2.c, line: 473
-# File: sshconnect2.c, line: 646
-# File: sshconnect2.c, line: 698
-# File: sshconnect2.c, line: 781
-# File: sshconnect2.c, line: 806
-# File: sshconnect2.c, line: 1372
-# File: clientloop.c, line: 1147
-# File: clientloop.c, line: 1157
-# File: clientloop.c, line: 1166
-# File: clientloop.c, line: 1193
-# File: clientloop.c, line: 1233
-# File: clientloop.c, line: 1348
-# File: sshd.c, line: 2043
# File: altprivsep.c, line: 568
# File: altprivsep.c, line: 655
+# File: auth-rsa.c, line: 146
# File: auth1.c, line: 139
# File: auth1.c, line: 170
# File: auth1.c, line: 188
# File: auth1.c, line: 207
# File: auth1.c, line: 240
# File: auth1.c, line: 331
-# File: auth2.c, line: 139
# File: auth2-chall.c, line: 280
# File: auth2-gss.c, line: 87
# File: auth2-gss.c, line: 137
@@ -429,11 +434,17 @@ msgstr ""
# File: auth2-gss.c, line: 353
# File: auth2-kbdint.c, line: 53
# File: auth2-none.c, line: 107
-# File: auth2-passwd.c, line: 58
# File: auth2-pam.c, line: 378
+# File: auth2-passwd.c, line: 58
# File: auth2-pubkey.c, line: 130
# File: auth2-pubkey.c, line: 163
-# File: auth-rsa.c, line: 146
+# File: auth2.c, line: 139
+# File: clientloop.c, line: 1294
+# File: clientloop.c, line: 1304
+# File: clientloop.c, line: 1313
+# File: clientloop.c, line: 1340
+# File: clientloop.c, line: 1380
+# File: clientloop.c, line: 1495
# File: serverloop.c, line: 1024
# File: serverloop.c, line: 1040
# File: serverloop.c, line: 1053
@@ -449,218 +460,234 @@ msgstr ""
# File: session.c, line: 1717
# File: session.c, line: 1727
# File: session.c, line: 1737
+# File: ssh.c, line: 929
+# File: ssh.c, line: 977
+# File: sshconnect1.c, line: 122
+# File: sshconnect1.c, line: 260
+# File: sshconnect1.c, line: 377
+# File: sshconnect1.c, line: 437
+# File: sshconnect1.c, line: 560
+# File: sshconnect2.c, line: 327
+# File: sshconnect2.c, line: 449
+# File: sshconnect2.c, line: 483
+# File: sshconnect2.c, line: 656
+# File: sshconnect2.c, line: 708
+# File: sshconnect2.c, line: 791
+# File: sshconnect2.c, line: 816
+# File: sshconnect2.c, line: 1382
+# File: sshd.c, line: 2043
msgid "Packet integrity error."
msgstr ""
#
-# File: ../common/channels.c, line: 1783
+# File: ../common/channels.c, line: 1905
#, c-format
msgid "Received extended_data for bad channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1792
+# File: ../common/channels.c, line: 1914
#, c-format
msgid "Received extended_data after EOF on channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1826
+# File: ../common/channels.c, line: 1948
#, c-format
msgid "Received ieof for nonexistent channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1849
+# File: ../common/channels.c, line: 1971
#, c-format
msgid "Received close for nonexistent channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1888
+# File: ../common/channels.c, line: 2010
#, c-format
msgid "Received oclose for nonexistent channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1900
+# File: ../common/channels.c, line: 2022
#, c-format
msgid "Received close confirmation for out-of-range channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1903
+# File: ../common/channels.c, line: 2025
#, c-format
msgid "Received close confirmation for non-closed channel %d (type %d)."
msgstr ""
#
-# File: ../common/channels.c, line: 1918
+# File: ../common/channels.c, line: 2040
#, c-format
msgid "Received open confirmation for non-opening channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 1966
+# File: ../common/channels.c, line: 2088
#, c-format
msgid "Received open failure for non-opening channel %d."
msgstr ""
#
-# File: ../common/channels.c, line: 2068
+# File: ../common/channels.c, line: 2190
msgid "No forward host name."
msgstr ""
#
-# File: ../common/channels.c, line: 2072
+# File: ../common/channels.c, line: 2194
msgid "Forward host name too long."
msgstr ""
#
-# File: ../common/channels.c, line: 2087
+# File: ../common/channels.c, line: 2209
msgid "getaddrinfo: fatal error"
msgstr ""
#
-# File: ../common/channels.c, line: 2094
+# File: ../common/channels.c, line: 2216
msgid "channel_setup_fwd_listener: getnameinfo failed"
msgstr ""
#
-# File: ../common/channels.c, line: 2101
-# File: ../common/channels.c, line: 2327
-# File: ../common/channels.c, line: 2427
-# File: ../common/channels.c, line: 2502
+# File: ../common/channels.c, line: 2223
+# File: ../common/channels.c, line: 2449
+# File: ../common/channels.c, line: 2549
+# File: ../common/channels.c, line: 2624
+# File: session.c, line: 203
# File: sshconnect.c, line: 206
# File: sshd.c, line: 1343
-# File: session.c, line: 203
#, c-format
msgid "socket: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2111
+# File: ../common/channels.c, line: 2233
# File: sshd.c, line: 1358
#, c-format
msgid "setsockopt SO_REUSEADDR: %s"
msgstr ""
#
-# File: ../common/channels.c, line: 2119
-# File: ../common/channels.c, line: 2121
+# File: ../common/channels.c, line: 2241
+# File: ../common/channels.c, line: 2243
# File: session.c, line: 211
#, c-format
msgid "bind: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2128
-# File: ../common/channels.c, line: 2473
-# File: sshd.c, line: 1376
+# File: ../common/channels.c, line: 2250
+# File: ../common/channels.c, line: 2595
# File: session.c, line: 218
+# File: sshd.c, line: 1376
#, c-format
msgid "listen: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2142
+# File: ../common/channels.c, line: 2264
#, c-format
msgid "channel_setup_fwd_listener: cannot listen to port: %d"
msgstr ""
#
-# File: ../common/channels.c, line: 2180
-# File: ../common/channels.c, line: 2277
+# File: ../common/channels.c, line: 2302
+# File: ../common/channels.c, line: 2399
msgid "channel_request_remote_forwarding: too many forwards"
msgstr ""
#
-# File: ../common/channels.c, line: 2213
+# File: ../common/channels.c, line: 2335
#, c-format
msgid "Protocol error for port forward request:received packet type %d."
msgstr ""
#
-# File: ../common/channels.c, line: 2250
+# File: ../common/channels.c, line: 2372
#, c-format
msgid "Requested forwarding of port %d but user is not root."
msgstr ""
#
-# File: ../common/channels.c, line: 2313
+# File: ../common/channels.c, line: 2435
#, c-format
msgid "connect_to %.100s: unknown host (%s)"
msgstr ""
#
-# File: ../common/channels.c, line: 2322
+# File: ../common/channels.c, line: 2444
msgid "connect_to: getnameinfo failed"
msgstr ""
#
-# File: ../common/channels.c, line: 2331
+# File: ../common/channels.c, line: 2453
#, c-format
msgid "connect_to: F_SETFL: %s"
msgstr ""
#
-# File: ../common/channels.c, line: 2334
+# File: ../common/channels.c, line: 2456
#, c-format
msgid "connect_to %.100s port %s: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2344
+# File: ../common/channels.c, line: 2466
#, c-format
msgid "connect_to %.100s port %d: failed."
msgstr ""
#
-# File: ../common/channels.c, line: 2362
+# File: ../common/channels.c, line: 2484
#, c-format
msgid "WARNING: Server requests forwarding for unknown listen_port %d"
msgstr ""
#
-# File: ../common/channels.c, line: 2418
+# File: ../common/channels.c, line: 2540
#, c-format
msgid "getaddrinfo: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2439
+# File: ../common/channels.c, line: 2561
#, c-format
msgid "setsockopt IPV6_V6ONLY: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2466
+# File: ../common/channels.c, line: 2588
msgid "Failed to allocate internet-domain X11 display socket."
msgstr ""
#
-# File: ../common/channels.c, line: 2509
+# File: ../common/channels.c, line: 2631
#, c-format
msgid "connect %.100s: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2526
+# File: ../common/channels.c, line: 2648
msgid "DISPLAY not set."
msgstr ""
#
-# File: ../common/channels.c, line: 2544
-# File: ../common/channels.c, line: 2570
+# File: ../common/channels.c, line: 2666
+# File: ../common/channels.c, line: 2692
#, c-format
msgid "Could not parse display number from DISPLAY: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2564
+# File: ../common/channels.c, line: 2686
#, c-format
msgid "Could not find ':' in DISPLAY: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2581
+# File: ../common/channels.c, line: 2703
#, c-format
msgid "%.100s: unknown host. (%s)"
msgstr ""
#
-# File: ../common/channels.c, line: 2603
+# File: ../common/channels.c, line: 2725
#, c-format
msgid "connect %.100s port %d: %.100s"
msgstr ""
#
-# File: ../common/channels.c, line: 2667
-# File: clientloop.c, line: 1256
+# File: ../common/channels.c, line: 2789
+# File: clientloop.c, line: 1403
msgid "Warning: ssh server tried agent forwarding."
msgstr ""
#
-# File: ../common/channels.c, line: 2670
-# File: clientloop.c, line: 1222
+# File: ../common/channels.c, line: 2792
+# File: clientloop.c, line: 1369
msgid "Warning: ssh server tried X11 forwarding."
msgstr ""
#
-# File: ../common/channels.c, line: 2673
+# File: ../common/channels.c, line: 2795
#, c-format
msgid "deny_input_open: type %d"
msgstr ""
#
-# File: ../common/channels.c, line: 2676
-# File: clientloop.c, line: 1223
-# File: clientloop.c, line: 1257
+# File: ../common/channels.c, line: 2798
+# File: clientloop.c, line: 1370
+# File: clientloop.c, line: 1404
msgid ""
"Warning: this is probably a break in attempt by a malicious server."
msgstr ""
#
-# File: ../common/channels.c, line: 2721
+# File: ../common/channels.c, line: 2843
#, c-format
msgid "x11_request_forwarding: bad authentication data: %.100s"
msgstr ""
@@ -1338,6 +1365,29 @@ msgstr ""
msgid "setsockopt TCP_NODELAY: %.100s"
msgstr ""
#
+# File: ../common/misc.c, line: 365
+msgid "replacearg: argument too long"
+msgstr ""
+#
+# File: ../common/misc.c, line: 368
+#, c-format
+msgid "replacearg: tried to replace invalid arg %d >= %d"
+msgstr ""
+#
+# File: ../common/misc.c, line: 549
+# File: ../common/readconf.c, line: 466
+# File: ../common/readconf.c, line: 487
+# File: ../common/readconf.c, line: 547
+# File: ../common/readconf.c, line: 567
+# File: ../common/readconf.c, line: 579
+# File: ../common/readconf.c, line: 590
+# File: ../common/readconf.c, line: 601
+# File: ../common/readconf.c, line: 613
+# File: ../common/readconf.c, line: 695
+#, c-format
+msgid "%.200s line %d: Missing argument."
+msgstr ""
+#
# File: ../common/nchan.c, line: 90
#, c-format
msgid "chan_set_istate: bad state %d -> %d"
@@ -1866,10 +1916,10 @@ msgid "%s: struct passwd size mismatch"
msgstr ""
#
# File: ../common/monitor_wrap.c, line: 310
-# File: sshconnect2.c, line: 966
-# File: sshconnect2.c, line: 1342
-# File: sshconnect2.c, line: 1344
# File: auth.c, line: 542
+# File: sshconnect2.c, line: 976
+# File: sshconnect2.c, line: 1352
+# File: sshconnect2.c, line: 1354
#, c-format
msgid "%s"
msgstr ""
@@ -1952,165 +2002,197 @@ msgstr ""
msgid "%s: no fd"
msgstr ""
#
-# File: ../common/readconf.c, line: 208
+# File: ../common/readconf.c, line: 214
msgid "Privileged ports can only be forwarded by root."
msgstr ""
#
-# File: ../common/readconf.c, line: 211
+# File: ../common/readconf.c, line: 217
#, c-format
msgid "Too many local forwards (max %d)."
msgstr ""
#
-# File: ../common/readconf.c, line: 230
+# File: ../common/readconf.c, line: 236
#, c-format
msgid "Too many remote forwards (max %d)."
msgstr ""
#
-# File: ../common/readconf.c, line: 265
+# File: ../common/readconf.c, line: 271
# File: servconf.c, line: 482
#, c-format
msgid "%s: line %d: Bad configuration option: %s"
msgstr ""
#
-# File: ../common/readconf.c, line: 307
+# File: ../common/readconf.c, line: 313
# File: servconf.c, line: 587
#, c-format
msgid "%s line %d: missing time value."
msgstr ""
#
-# File: ../common/readconf.c, line: 310
+# File: ../common/readconf.c, line: 316
# File: servconf.c, line: 590
#, c-format
msgid "%s line %d: invalid time value."
msgstr ""
#
-# File: ../common/readconf.c, line: 321
+# File: ../common/readconf.c, line: 327
#, c-format
msgid "%.200s line %d: Missing yes/no argument."
msgstr ""
#
-# File: ../common/readconf.c, line: 328
+# File: ../common/readconf.c, line: 334
#, c-format
msgid "%.200s line %d: Bad yes/no argument."
msgstr ""
#
-# File: ../common/readconf.c, line: 418
+# File: ../common/readconf.c, line: 428
#, c-format
msgid "%.200s line %d: Missing yes/no/ask argument."
msgstr ""
#
-# File: ../common/readconf.c, line: 428
+# File: ../common/readconf.c, line: 438
#, c-format
msgid "%.200s line %d: Bad yes/no/ask argument."
msgstr ""
#
-# File: ../common/readconf.c, line: 456
-# File: ../common/readconf.c, line: 477
-# File: ../common/readconf.c, line: 537
-# File: ../common/readconf.c, line: 557
-# File: ../common/readconf.c, line: 569
-# File: ../common/readconf.c, line: 580
-# File: ../common/readconf.c, line: 591
-# File: ../common/readconf.c, line: 603
-# File: ../common/readconf.c, line: 685
-#, c-format
-msgid "%.200s line %d: Missing argument."
-msgstr ""
-#
-# File: ../common/readconf.c, line: 460
+# File: ../common/readconf.c, line: 470
#, c-format
msgid "%.200s line %d: Too many identity files specified (max %d)."
msgstr ""
#
-# File: ../common/readconf.c, line: 539
-# File: ../common/readconf.c, line: 544
+# File: ../common/readconf.c, line: 549
+# File: ../common/readconf.c, line: 554
#, c-format
msgid "%.200s line %d: Bad number."
msgstr ""
#
-# File: ../common/readconf.c, line: 560
+# File: ../common/readconf.c, line: 570
#, c-format
msgid "%.200s line %d: Bad cipher '%s'."
msgstr ""
#
-# File: ../common/readconf.c, line: 571
+# File: ../common/readconf.c, line: 581
#, c-format
msgid "%.200s line %d: Bad SSH2 cipher spec '%s'."
msgstr ""
#
-# File: ../common/readconf.c, line: 582
+# File: ../common/readconf.c, line: 592
#, c-format
msgid "%.200s line %d: Bad SSH2 Mac spec '%s'."
msgstr ""
#
-# File: ../common/readconf.c, line: 593
+# File: ../common/readconf.c, line: 603
#, c-format
msgid "%.200s line %d: Bad protocol 2 host key algorithms '%s'."
msgstr ""
#
-# File: ../common/readconf.c, line: 606
+# File: ../common/readconf.c, line: 616
#, c-format
msgid "%.200s line %d: Bad protocol spec '%s'."
msgstr ""
#
-# File: ../common/readconf.c, line: 617
+# File: ../common/readconf.c, line: 627
# File: servconf.c, line: 826
#, c-format
msgid "%.200s line %d: unsupported log level '%s'"
msgstr ""
#
-# File: ../common/readconf.c, line: 627
-# File: ../common/readconf.c, line: 656
+# File: ../common/readconf.c, line: 637
+# File: ../common/readconf.c, line: 666
#, c-format
msgid "%.200s line %d: Missing port argument."
msgstr ""
#
-# File: ../common/readconf.c, line: 630
+# File: ../common/readconf.c, line: 640
#, c-format
msgid "%.200s line %d: Bad listen port."
msgstr ""
#
-# File: ../common/readconf.c, line: 634
+# File: ../common/readconf.c, line: 644
#, c-format
msgid "%.200s line %d: Missing second argument."
msgstr ""
#
-# File: ../common/readconf.c, line: 638
+# File: ../common/readconf.c, line: 648
#, c-format
msgid "%.200s line %d: Bad forwarding specification."
msgstr ""
#
-# File: ../common/readconf.c, line: 641
+# File: ../common/readconf.c, line: 651
#, c-format
msgid "%.200s line %d: Bad forwarding port."
msgstr ""
#
-# File: ../common/readconf.c, line: 660
+# File: ../common/readconf.c, line: 670
#, c-format
msgid "%.200s line %d: Badly formatted port number."
msgstr ""
#
-# File: ../common/readconf.c, line: 694
+# File: ../common/readconf.c, line: 704
#, c-format
msgid "%.200s line %d: Bad escape character."
msgstr ""
#
-# File: ../common/readconf.c, line: 709
+# File: ../common/readconf.c, line: 730
+#, c-format
+msgid "%.200s line %d: Bad yes/no/in-exec-mode argument."
+msgstr ""
+#
+# File: ../common/readconf.c, line: 740
#, c-format
msgid "process_config_line: Unimplemented opcode %d"
msgstr ""
#
-# File: ../common/readconf.c, line: 714
+# File: ../common/readconf.c, line: 745
#, c-format
msgid "%.200s line %d: garbage at end of line; \"%.200s\"."
msgstr ""
#
-# File: ../common/readconf.c, line: 758
+# File: ../common/readconf.c, line: 789
# File: servconf.c, line: 1035
#, c-format
msgid "%s: terminating, %d bad configuration options"
msgstr ""
#
+# File: ../common/sftp-common.c, line: 164
+msgid "No error"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 166
+msgid "End of file"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 168
+msgid "No such file or directory"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 170
+msgid "Permission denied"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 172
+msgid "Failure"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 174
+msgid "Bad message"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 176
+msgid "No connection"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 178
+msgid "Connection lost"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 180
+msgid "Operation unsupported"
+msgstr ""
+#
+# File: ../common/sftp-common.c, line: 182
+msgid "Unknown status"
+msgstr ""
+#
# File: ssh.c, line: 164
#, c-format
msgid ""
@@ -2123,8 +2205,8 @@ msgid ""
" -a Disable authentication agent forwarding (default).\n"
" -X Enable X11 connection forwarding.\n"
" -x Disable X11 connection forwarding (default).\n"
-" -i file Identity for public key authentication (default: ~/.ssh/"
-"identity)\n"
+" -i file Identity for public key authentication (default: "
+"~/.ssh/identity)\n"
" -t Tty; allocate a tty even if command is given.\n"
" -T Do not allocate a tty.\n"
" -v Verbose; display verbose debugging messages.\n"
@@ -2141,8 +2223,8 @@ msgid ""
" -R listen-port:host:port Forward remote port to local address\n"
" These cause %s to listen for connections on a port, "
"and\n"
-" forward them to the other side by connecting to host:"
-"port.\n"
+" forward them to the other side by connecting to "
+"host:port.\n"
" -D port Enable dynamic application-level port forwarding.\n"
" -C Enable compression.\n"
" -N Do not execute a shell or command.\n"
@@ -2167,7 +2249,6 @@ msgid "You don't exist, go away!"
msgstr ""
#
# File: ssh.c, line: 329
-#, c-format
msgid "Warning: Option -P has been deprecated\n"
msgstr ""
#
@@ -2181,8 +2262,8 @@ msgstr ""
msgid "Too many identity files specified (max %d)"
msgstr ""
#
-# File: ssh.c, line: 372
# File: ssh-keyscan.c, line: 725
+# File: ssh.c, line: 372
msgid "Too high debugging level."
msgstr ""
#
@@ -2206,8 +2287,8 @@ msgstr ""
msgid "Unknown mac type '%s'\n"
msgstr ""
#
-# File: ssh.c, line: 440
# File: ssh-keyscan.c, line: 704
+# File: ssh.c, line: 440
#, c-format
msgid "Bad port '%s'\n"
msgstr ""
@@ -2228,7 +2309,6 @@ msgid "Bad dynamic port '%s'\n"
msgstr ""
#
# File: ssh.c, line: 562
-#, c-format
msgid "You must specify a subsystem to invoke.\n"
msgstr ""
#
@@ -2256,95 +2336,89 @@ msgstr ""
msgid "Could not create directory '%.200s'."
msgstr ""
#
-# File: ssh.c, line: 838
-msgid ""
-"Warning: No xauth data; using fake authentication data for X11 "
-"forwarding."
-msgstr ""
-#
-# File: ssh.c, line: 868
+# File: ssh.c, line: 801
msgid "Could not request local forwarding."
msgstr ""
#
-# File: ssh.c, line: 907
+# File: ssh.c, line: 841
msgid "Compression level must be from 1 (fast) to 9 (slow, best)."
msgstr ""
#
-# File: ssh.c, line: 918
+# File: ssh.c, line: 852
msgid "Warning: Remote host refused compression."
msgstr ""
#
-# File: ssh.c, line: 920
+# File: ssh.c, line: 854
msgid "Protocol error waiting for compression response."
msgstr ""
#
-# File: ssh.c, line: 958
+# File: ssh.c, line: 892
msgid "Warning: Remote host failed or refused to allocate a pseudo tty."
msgstr ""
#
-# File: ssh.c, line: 960
+# File: ssh.c, line: 894
msgid "Protocol error waiting for pty request response."
msgstr ""
#
-# File: ssh.c, line: 976
+# File: ssh.c, line: 912
msgid "Warning: Remote host denied X11 forwarding."
msgstr ""
#
-# File: ssh.c, line: 978
+# File: ssh.c, line: 914
msgid "Protocol error waiting for X11 forwarding"
msgstr ""
#
-# File: ssh.c, line: 993
-# File: ssh.c, line: 1041
+# File: clientloop.c, line: 1294
+# File: clientloop.c, line: 1304
+# File: clientloop.c, line: 1313
+# File: clientloop.c, line: 1340
+# File: clientloop.c, line: 1380
+# File: clientloop.c, line: 1495
+# File: ssh.c, line: 929
+# File: ssh.c, line: 977
# File: sshconnect1.c, line: 122
# File: sshconnect1.c, line: 260
# File: sshconnect1.c, line: 377
# File: sshconnect1.c, line: 437
# File: sshconnect1.c, line: 560
-# File: sshconnect2.c, line: 326
-# File: sshconnect2.c, line: 439
-# File: sshconnect2.c, line: 473
-# File: sshconnect2.c, line: 646
-# File: sshconnect2.c, line: 698
-# File: sshconnect2.c, line: 781
-# File: sshconnect2.c, line: 806
-# File: sshconnect2.c, line: 1372
-# File: clientloop.c, line: 1147
-# File: clientloop.c, line: 1157
-# File: clientloop.c, line: 1166
-# File: clientloop.c, line: 1193
-# File: clientloop.c, line: 1233
-# File: clientloop.c, line: 1348
+# File: sshconnect2.c, line: 327
+# File: sshconnect2.c, line: 449
+# File: sshconnect2.c, line: 483
+# File: sshconnect2.c, line: 656
+# File: sshconnect2.c, line: 708
+# File: sshconnect2.c, line: 791
+# File: sshconnect2.c, line: 816
+# File: sshconnect2.c, line: 1382
#, c-format
msgid "Packet integrity error (%d bytes remaining) at %s:%d"
msgstr ""
#
-# File: ssh.c, line: 995
+# File: ssh.c, line: 931
msgid "Warning: Remote host denied authentication agent forwarding."
msgstr ""
#
-# File: ssh.c, line: 1004
-# File: ssh.c, line: 1226
+# File: ssh.c, line: 940
+# File: ssh.c, line: 1162
# File: sshd.c, line: 1284
#, c-format
msgid "daemon() failed: %.200s"
msgstr ""
#
-# File: ssh.c, line: 1043
+# File: ssh.c, line: 979
#, c-format
msgid "Request for subsystem '%.*s' failed on channel %d"
msgstr ""
#
-# File: ssh.c, line: 1064
+# File: ssh.c, line: 997
#, c-format
msgid "Warning: remote port forwarding failed for listen port %d"
msgstr ""
#
-# File: ssh.c, line: 1182
+# File: ssh.c, line: 1118
msgid "dup() in/out/err failed"
msgstr ""
#
-# File: ssh.c, line: 1262
+# File: ssh.c, line: 1198
msgid "Using rsh. WARNING: Connection will not be encrypted."
msgstr ""
#
@@ -2353,9 +2427,9 @@ msgstr ""
msgid "Could not create pipes to communicate with the proxy: %.100s"
msgstr ""
#
-# File: sshconnect.c, line: 160
# File: session.c, line: 458
# File: session.c, line: 577
+# File: sshconnect.c, line: 160
#, c-format
msgid "fork failed: %.100s"
msgstr ""
@@ -2647,7 +2721,7 @@ msgstr ""
#
# File: sshconnect1.c, line: 442
# File: sshconnect1.c, line: 483
-# File: sshconnect2.c, line: 925
+# File: sshconnect2.c, line: 935
msgid "Permission denied, please try again."
msgstr ""
#
@@ -2676,8 +2750,8 @@ msgstr ""
# File: sshconnect1.c, line: 537
#, c-format
msgid ""
-"Warning: Server lies about size of server public key: actual size is %"
-"d bits vs. announced %d."
+"Warning: Server lies about size of server public key: actual size is "
+"%d bits vs. announced %d."
msgstr ""
#
# File: sshconnect1.c, line: 539
@@ -2693,7 +2767,7 @@ msgid ""
msgstr ""
#
# File: sshconnect1.c, line: 566
-# File: sshconnect2.c, line: 85
+# File: sshconnect2.c, line: 86
msgid "Host key verification failed."
msgstr ""
#
@@ -2740,7 +2814,7 @@ msgid "Protocol error: got %d in response to rhosts auth"
msgstr ""
#
# File: sshconnect1.c, line: 798
-# File: sshconnect2.c, line: 927
+# File: sshconnect2.c, line: 937
#, c-format
msgid "%.30s@%.128s's password: "
msgstr ""
@@ -2749,210 +2823,226 @@ msgstr ""
msgid "Permission denied."
msgstr ""
#
-# File: sshconnect2.c, line: 93
+# File: sshconnect2.c, line: 94
msgid ""
"GSS-API authenticated host key addition to known_hosts file failed"
msgstr ""
#
-# File: sshconnect2.c, line: 115
+# File: sshconnect2.c, line: 116
msgid "No valid ciphers for protocol version 2 given, using defaults."
msgstr ""
#
-# File: sshconnect2.c, line: 318
+# File: sshconnect2.c, line: 319
#, c-format
msgid "Server denied authentication request: %d"
msgstr ""
#
-# File: sshconnect2.c, line: 346
+# File: sshconnect2.c, line: 347
msgid "ssh_userauth2: internal error: cannot send userauth none request"
msgstr ""
#
-# File: sshconnect2.c, line: 379
+# File: sshconnect2.c, line: 380
#, c-format
msgid "Permission denied (%s)."
msgstr ""
#
-# File: sshconnect2.c, line: 394
+# File: sshconnect2.c, line: 395
#, c-format
msgid "input_userauth_error: bad message during authentication: type %d"
msgstr ""
#
-# File: sshconnect2.c, line: 417
+# File: sshconnect2.c, line: 427
msgid "input_userauth_success: no authentication context"
msgstr ""
#
-# File: sshconnect2.c, line: 435
+# File: sshconnect2.c, line: 445
msgid "input_userauth_failure: no authentication context"
msgstr ""
#
-# File: sshconnect2.c, line: 442
+# File: sshconnect2.c, line: 452
msgid "Authenticated with partial success."
msgstr ""
#
-# File: sshconnect2.c, line: 460
+# File: sshconnect2.c, line: 470
msgid "input_userauth_pk_ok: no authentication context"
msgstr ""
#
-# File: sshconnect2.c, line: 493
+# File: sshconnect2.c, line: 503
#, c-format
msgid ""
"input_userauth_pk_ok: type mismatch for decoded key (received %d, "
"expected %d)"
msgstr ""
#
-# File: sshconnect2.c, line: 607
-# File: sshconnect2.c, line: 688
-# File: sshconnect2.c, line: 765
-# File: sshconnect2.c, line: 822
+# File: sshconnect2.c, line: 617
+# File: sshconnect2.c, line: 698
+# File: sshconnect2.c, line: 775
+# File: sshconnect2.c, line: 832
msgid "input_gssapi_response: no authentication context"
msgstr ""
#
-# File: sshconnect2.c, line: 960
+# File: sshconnect2.c, line: 970
msgid "input_userauth_passwd_changereq: no authentication context"
msgstr ""
#
-# File: sshconnect2.c, line: 975
+# File: sshconnect2.c, line: 985
#, c-format
msgid "Enter %.30s@%.128s's old password: "
msgstr ""
#
-# File: sshconnect2.c, line: 984
+# File: sshconnect2.c, line: 994
#, c-format
msgid "Enter %.30s@%.128s's new password: "
msgstr ""
#
-# File: sshconnect2.c, line: 992
+# File: sshconnect2.c, line: 1002
#, c-format
msgid "Retype %.30s@%.128s's new password: "
msgstr ""
#
-# File: sshconnect2.c, line: 998
+# File: sshconnect2.c, line: 1008
msgid "Mismatch; try again, EOF to quit."
msgstr ""
#
-# File: sshconnect2.c, line: 1105
+# File: sshconnect2.c, line: 1115
msgid "userauth_pubkey: internal error"
msgstr ""
#
-# File: sshconnect2.c, line: 1167
+# File: sshconnect2.c, line: 1177
#, c-format
msgid "Enter passphrase for key '%.100s': "
msgstr ""
#
-# File: sshconnect2.c, line: 1334
+# File: sshconnect2.c, line: 1344
msgid "input_userauth_info_req: no authentication context"
msgstr ""
#
-# File: sshconnect2.c, line: 1390
+# File: sshconnect2.c, line: 1400
#, c-format
msgid "ssh_keysign: no installed: %s"
msgstr ""
#
-# File: sshconnect2.c, line: 1394
+# File: sshconnect2.c, line: 1404
#, c-format
msgid "ssh_keysign: fflush: %s"
msgstr ""
#
-# File: sshconnect2.c, line: 1396
-# File: sshconnect2.c, line: 1400
+# File: sshconnect2.c, line: 1406
+# File: sshconnect2.c, line: 1410
#, c-format
msgid "ssh_keysign: pipe: %s"
msgstr ""
#
-# File: sshconnect2.c, line: 1404
+# File: sshconnect2.c, line: 1414
#, c-format
msgid "ssh_keysign: fork: %s"
msgstr ""
#
-# File: sshconnect2.c, line: 1412
-# File: sshconnect2.c, line: 1415
+# File: sshconnect2.c, line: 1422
+# File: sshconnect2.c, line: 1425
#, c-format
msgid "ssh_keysign: dup2: %s"
msgstr ""
#
-# File: sshconnect2.c, line: 1419
+# File: sshconnect2.c, line: 1429
#, c-format
msgid "ssh_keysign: exec(%s): %s"
msgstr ""
#
-# File: sshconnect2.c, line: 1431
+# File: sshconnect2.c, line: 1441
msgid "ssh_keysign: no reply"
msgstr ""
#
-# File: sshconnect2.c, line: 1443
+# File: sshconnect2.c, line: 1453
msgid "ssh_keysign: bad version"
msgstr ""
#
-# File: sshconnect2.c, line: 1488
+# File: sshconnect2.c, line: 1498
msgid "userauth_hostbased: cannot get local ipaddr/name"
msgstr ""
#
-# File: sshconnect2.c, line: 1525
# File: ssh-keysign.c, line: 249
+# File: sshconnect2.c, line: 1535
msgid "key_sign failed"
msgstr ""
#
-# File: clientloop.c, line: 472
+# File: clientloop.c, line: 284
+msgid ""
+"Warning: untrusted X11 forwarding setup failed: xauth key data not "
+"generated"
+msgstr ""
+#
+# File: clientloop.c, line: 309
+msgid ""
+"Warning: No xauth data; using fake authentication data for X11 "
+"forwarding."
+msgstr ""
+#
+# File: clientloop.c, line: 460
+msgid "Timeout, server not responding."
+msgstr ""
+#
+# File: clientloop.c, line: 619
#, c-format
msgid "Connection to %.300s closed by remote host.\r\n"
msgstr ""
#
-# File: clientloop.c, line: 490
+# File: clientloop.c, line: 637
#, c-format
msgid "Read from remote host %.300s: %.100s\r\n"
msgstr ""
#
-# File: clientloop.c, line: 520
-# File: sftp-int.c, line: 695
+# File: clientloop.c, line: 667
+# File: sftp.c, line: 894
msgid "Invalid command."
msgstr ""
#
-# File: clientloop.c, line: 526
+# File: clientloop.c, line: 673
msgid "Not supported for SSH protocol version 1."
msgstr ""
#
-# File: clientloop.c, line: 537
+# File: clientloop.c, line: 684
msgid "Bad forwarding specification."
msgstr ""
#
-# File: clientloop.c, line: 542
+# File: clientloop.c, line: 689
msgid "Bad forwarding port(s)."
msgstr ""
#
-# File: clientloop.c, line: 548
+# File: clientloop.c, line: 695
msgid "Port forwarding failed."
msgstr ""
#
-# File: clientloop.c, line: 554
+# File: clientloop.c, line: 701
msgid "Forwarding port."
msgstr ""
#
-# File: clientloop.c, line: 596
+# File: clientloop.c, line: 743
#, c-format
msgid "%c^Z [suspend ssh]\r\n"
msgstr ""
#
-# File: clientloop.c, line: 609
+# File: clientloop.c, line: 756
#, c-format
msgid "%cB [sent break]\r\n"
msgstr ""
#
-# File: clientloop.c, line: 623
+# File: clientloop.c, line: 770
msgid "Server does not support re-keying"
msgstr ""
#
-# File: clientloop.c, line: 642
+# File: clientloop.c, line: 789
#, c-format
msgid "%c& [backgrounded]\n"
msgstr ""
#
-# File: clientloop.c, line: 649
+# File: clientloop.c, line: 796
# File: sshd.c, line: 1580
#, c-format
msgid "fork: %.100s"
msgstr ""
#
-# File: clientloop.c, line: 682
+# File: clientloop.c, line: 829
#, c-format
msgid ""
"%c?\r\n"
@@ -2969,40 +3059,40 @@ msgid ""
"(Note that escapes are only recognized immediately after newline.)\r\n"
msgstr ""
#
-# File: clientloop.c, line: 874
+# File: clientloop.c, line: 1021
#, c-format
msgid "client_channel_closed: id %d != session_ident %d"
msgstr ""
#
-# File: clientloop.c, line: 1081
+# File: clientloop.c, line: 1228
#, c-format
msgid "Killed by signal %d."
msgstr ""
#
-# File: clientloop.c, line: 1091
+# File: clientloop.c, line: 1238
#, c-format
msgid "Connection to %.64s closed.\r\n"
msgstr ""
#
-# File: clientloop.c, line: 1101
+# File: clientloop.c, line: 1248
msgid "Write failed flushing stdout buffer."
msgstr ""
#
-# File: clientloop.c, line: 1113
+# File: clientloop.c, line: 1260
msgid "Write failed flushing stderr buffer."
msgstr ""
#
-# File: clientloop.c, line: 1337
+# File: clientloop.c, line: 1484
#, c-format
msgid "client_input_channel_req: no channel %d"
msgstr ""
#
-# File: clientloop.c, line: 1339
+# File: clientloop.c, line: 1486
#, c-format
msgid "client_input_channel_req: channel %d: wrong channel: %d"
msgstr ""
#
-# File: clientloop.c, line: 1344
+# File: clientloop.c, line: 1491
#, c-format
msgid "client_input_channel_req: channel %d: unknown channel"
msgstr ""
@@ -3082,32 +3172,26 @@ msgid ""
msgstr ""
#
# File: sshd.c, line: 1039
-#, c-format
msgid "Debug level too high.\n"
msgstr ""
#
# File: sshd.c, line: 1064
-#, c-format
msgid "too many ports.\n"
msgstr ""
#
# File: sshd.c, line: 1069
-#, c-format
msgid "Bad port number.\n"
msgstr ""
#
# File: sshd.c, line: 1076
-#, c-format
msgid "Invalid login grace time.\n"
msgstr ""
#
# File: sshd.c, line: 1083
-#, c-format
msgid "Invalid key regeneration interval.\n"
msgstr ""
#
# File: sshd.c, line: 1091
-#, c-format
msgid "too many host keys.\n"
msgstr ""
#
@@ -3122,7 +3206,6 @@ msgid "Could not load host key: %s"
msgstr ""
#
# File: sshd.c, line: 1209
-#, c-format
msgid "Bad server key size.\n"
msgstr ""
#
@@ -3158,9 +3241,9 @@ msgstr ""
msgid "Cannot bind any address."
msgstr ""
#
-# File: sshd.c, line: 1451
# File: serverloop.c, line: 359
# File: serverloop.c, line: 812
+# File: sshd.c, line: 1451
#, c-format
msgid "select: %.100s"
msgstr ""
@@ -3271,8 +3354,8 @@ msgstr ""
# File: altprivsep.c, line: 888
#, c-format
msgid ""
-"Protocol error in privilege separation; expected packet type %d, got %"
-"d"
+"Protocol error in privilege separation; expected packet type %d, got "
+"%d"
msgstr ""
#
# File: auth.c, line: 198
@@ -3333,11 +3416,11 @@ msgstr ""
msgid "input_userauth_request: no authctxt"
msgstr ""
#
-# File: auth2.c, line: 286
# File: auth2-hostbased.c, line: 70
# File: auth2-none.c, line: 105
# File: auth2-passwd.c, line: 52
# File: auth2-pubkey.c, line: 69
+# File: auth2.c, line: 286
#, c-format
msgid "%s: missing context"
msgstr ""
@@ -3444,8 +3527,8 @@ msgid ""
"%d)"
msgstr ""
#
-# File: auth2-pubkey.c, line: 295
# File: auth-rsa.c, line: 332
+# File: auth2-pubkey.c, line: 295
#, c-format
msgid "Found matching %s key: %s"
msgstr ""
@@ -4115,7 +4198,6 @@ msgid "Could not set ULIMIT to %ld from %s\n"
msgstr ""
#
# File: session.c, line: 1063
-#, c-format
msgid "Environment:\n"
msgstr ""
#
@@ -4337,7 +4419,6 @@ msgid "do_local_cmd: no arguments"
msgstr ""
#
# File: scp.c, line: 168
-#, c-format
msgid "Executing:"
msgstr ""
#
@@ -4367,7 +4448,7 @@ msgid "pipe: %s"
msgstr ""
#
# File: scp.c, line: 256
-# File: sftp.c, line: 71
+# File: sftp.c, line: 1346
#, c-format
msgid "fork: %s"
msgstr ""
@@ -4388,7 +4469,6 @@ msgid "Entering directory: %s"
msgstr ""
#
# File: scp.c, line: 1064
-#, c-format
msgid ""
"Usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
" [-c cipher] [-i identity] [-o option]\n"
@@ -4416,12 +4496,10 @@ msgid "Could not remove identity: %s\n"
msgstr ""
#
# File: ssh-add.c, line: 127
-#, c-format
msgid "All identities removed.\n"
msgstr ""
#
# File: ssh-add.c, line: 129
-#, c-format
msgid "Failed to remove all identities.\n"
msgstr ""
#
@@ -4452,37 +4530,30 @@ msgstr ""
#
# File: ssh-add.c, line: 221
# File: ssh-keygen.c, line: 393
-#, c-format
msgid "key_write failed"
msgstr ""
#
# File: ssh-add.c, line: 229
-#, c-format
msgid "The agent has no identities.\n"
msgstr ""
#
# File: ssh-add.c, line: 247
-#, c-format
msgid "Passwords do not match.\n"
msgstr ""
#
# File: ssh-add.c, line: 255
-#, c-format
msgid "Agent locked.\n"
msgstr ""
#
# File: ssh-add.c, line: 257
-#, c-format
msgid "Agent unlocked.\n"
msgstr ""
#
# File: ssh-add.c, line: 261
-#, c-format
msgid "Failed to lock agent.\n"
msgstr ""
#
# File: ssh-add.c, line: 263
-#, c-format
msgid "Failed to unlock agent.\n"
msgstr ""
#
@@ -4501,12 +4572,10 @@ msgid ""
msgstr ""
#
# File: ssh-add.c, line: 321
-#, c-format
msgid "Could not open a connection to your authentication agent.\n"
msgstr ""
#
# File: ssh-add.c, line: 350
-#, c-format
msgid "Invalid lifetime\n"
msgstr ""
#
@@ -4529,8 +4598,8 @@ msgstr ""
msgid "process_remove_identity: internal error: tab->nentries %d"
msgstr ""
#
+# File: sftp-server.c, line: 1172
# File: ssh-agent.c, line: 630
-# File: sftp-server.c, line: 994
#, c-format
msgid "Unknown message %d"
msgstr ""
@@ -4613,13 +4682,13 @@ msgstr ""
msgid "setrlimit RLIMIT_CORE: %s"
msgstr ""
#
+# File: sftp-server.c, line: 1313
# File: ssh-agent.c, line: 1099
#, c-format
msgid "select: %s"
msgstr ""
#
# File: ssh-keygen.c, line: 111
-#, c-format
msgid "bad key type"
msgstr ""
#
@@ -4639,12 +4708,10 @@ msgstr ""
#
# File: ssh-keygen.c, line: 166
# File: ssh-keygen.c, line: 389
-#, c-format
msgid "load failed\n"
msgstr ""
#
# File: ssh-keygen.c, line: 171
-#, c-format
msgid "key_to_blob failed\n"
msgstr ""
#
@@ -4675,22 +4742,18 @@ msgid ""
msgstr ""
#
# File: ssh-keygen.c, line: 318
-#, c-format
msgid "input line too long.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 349
-#, c-format
msgid "uudecode failed.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 356
-#, c-format
msgid "decode blob failed.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 365
-#, c-format
msgid "key write failed"
msgstr ""
#
@@ -4714,7 +4777,6 @@ msgstr ""
#
# File: ssh-keygen.c, line: 531
# File: ssh-keygen.c, line: 618
-#, c-format
msgid "Bad passphrase.\n"
msgstr ""
#
@@ -4733,7 +4795,6 @@ msgid "Enter same passphrase again: "
msgstr ""
#
# File: ssh-keygen.c, line: 554
-#, c-format
msgid "Pass phrases do not match. Try again.\n"
msgstr ""
#
@@ -4745,12 +4806,10 @@ msgid "Saving the key failed: %s.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 578
-#, c-format
msgid "Your identification has been saved with the new passphrase.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 625
-#, c-format
msgid "Comments are only supported for RSA1 keys.\n"
msgstr ""
#
@@ -4760,7 +4819,6 @@ msgid "Key now has comment '%s'\n"
msgstr ""
#
# File: ssh-keygen.c, line: 635
-#, c-format
msgid "Enter new comment: "
msgstr ""
#
@@ -4778,12 +4836,10 @@ msgstr ""
#
# File: ssh-keygen.c, line: 673
# File: ssh-keygen.c, line: 957
-#, c-format
msgid "write key failed"
msgstr ""
#
# File: ssh-keygen.c, line: 680
-#, c-format
msgid "The comment in your key file has been changed.\n"
msgstr ""
#
@@ -4809,22 +4865,18 @@ msgid ""
msgstr ""
#
# File: ssh-keygen.c, line: 740
-#, c-format
msgid "You don't exist, go away!\n"
msgstr ""
#
# File: ssh-keygen.c, line: 754
-#, c-format
msgid "Bits has bad value.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 816
-#, c-format
msgid "Too many arguments.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 820
-#, c-format
msgid "Can only have one of -p and -c.\n"
msgstr ""
#
@@ -4833,7 +4885,6 @@ msgid "no support for smartcards."
msgstr ""
#
# File: ssh-keygen.c, line: 844
-#, c-format
msgid "You must specify a key type (-t).\n"
msgstr ""
#
@@ -4848,7 +4899,6 @@ msgid "Generating public/private %s key pair.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 858
-#, c-format
msgid "key_generate failed"
msgstr ""
#
@@ -4881,7 +4931,6 @@ msgid "Enter passphrase (empty for no passphrase): "
msgstr ""
#
# File: ssh-keygen.c, line: 909
-#, c-format
msgid "Passphrases do not match. Try again.\n"
msgstr ""
#
@@ -4896,7 +4945,6 @@ msgid "Your public key has been saved in %s.\n"
msgstr ""
#
# File: ssh-keygen.c, line: 965
-#, c-format
msgid "The key fingerprint is:\n"
msgstr ""
#
@@ -5043,527 +5091,601 @@ msgstr ""
msgid "%s: not enough file descriptors"
msgstr ""
#
-# File: sftp-server.c, line: 450
+# File: sftp-server.c, line: 483
+#, c-format
+msgid "received client version %d"
+msgstr ""
+#
+# File: sftp-server.c, line: 562
msgid "process_read: seek failed"
msgstr ""
#
-# File: sftp-server.c, line: 488
+# File: sftp-server.c, line: 601
msgid "process_write: seek failed"
msgstr ""
#
-# File: sftp-server.c, line: 493
+# File: sftp-server.c, line: 606
msgid "process_write: write failed"
msgstr ""
#
-# File: sftp-server.c, line: 924
-msgid "bad message "
+# File: sftp-server.c, line: 632
+#, c-format
+msgid "%sstat name \"%s\""
msgstr ""
#
-# File: sftp-server.c, line: 999
-msgid "iqueue grows"
+# File: sftp-server.c, line: 959
+#, c-format
+msgid "realpath \"%s\""
msgstr ""
#
-# File: sftp-server.c, line: 1002
+# File: sftp-server.c, line: 1038
#, c-format
-msgid "msg_len %d < consumed %d"
+msgid "readlink \"%s\""
+msgstr ""
+#
+# File: sftp-server.c, line: 1101
+#, c-format
+msgid "bad message from %s local user %s"
msgstr ""
#
-# File: sftp-server.c, line: 1065
-msgid "read error"
+# File: sftp-server.c, line: 1177
+msgid "iqueue grew unexpectedly"
msgstr ""
#
-# File: sftp-server.c, line: 1075
-msgid "write error"
+# File: sftp-server.c, line: 1180
+#, c-format
+msgid "msg_len %d < consumed %d"
msgstr ""
#
-# File: sftp.c, line: 65
+# File: sftp-server.c, line: 1241
#, c-format
-msgid "socketpair: %s"
+msgid "Invalid log level \"%s\""
msgstr ""
#
-# File: sftp.c, line: 97
+# File: sftp-server.c, line: 1246
#, c-format
-msgid ""
-"Usage: %s [-vC1] [-b batchfile] [-o option] [-s subsystem|path]\n"
-" [-F config] [-P direct server path] [-S program] [-B "
-"buffer_size]\n"
-" [-R num_requests] [user@]host[:file [file]]\n"
+msgid "Invalid log facility \"%s\""
msgstr ""
#
-# File: sftp.c, line: 162
+# File: sftp-server.c, line: 1259
#, c-format
-msgid "%s (%s)."
+msgid "Malformed SSH_CONNECTION variable: \"%s\""
msgstr ""
#
-# File: sftp.c, line: 164
-msgid "Filename already specified."
+# File: sftp-server.c, line: 1266
+#, c-format
+msgid "No user found for uid %lu"
msgstr ""
#
-# File: sftp.c, line: 172
+# File: sftp-server.c, line: 1324
#, c-format
-msgid "Invalid buffer size \"%s\""
+msgid "read: %s"
msgstr ""
#
-# File: sftp.c, line: 177
+# File: sftp-server.c, line: 1334
#, c-format
-msgid "Invalid number of requests \"%s\""
+msgid "write: %s"
+msgstr ""
+#
+# File: sftp.c, line: 172
+msgid ""
+"Available commands:\n"
+"cd path Change remote directory to 'path'\n"
+"lcd path Change local directory to 'path'\n"
+"chgrp grp path Change group of file 'path' to 'grp'\n"
+"chmod mode path Change permissions of file 'path' to "
+"'mode'\n"
+"chown own path Change owner of file 'path' to 'own'\n"
+"help Display this help text\n"
+"get remote-path [local-path] Download file\n"
+"lls [ls-options [path]] Display local directory listing\n"
+"ln oldpath newpath Symlink remote file\n"
+"lmkdir path Create local directory\n"
+"lpwd Print local working directory\n"
+"ls [path] Display remote directory listing\n"
+"lumask umask Set local umask to 'umask'\n"
+"mkdir path Create remote directory\n"
+"progress Toggle display of progress meter\n"
+"put local-path [remote-path] Upload file\n"
+"pwd Display remote working directory\n"
+"exit Quit sftp\n"
+"quit Quit sftp\n"
+"rename oldpath newpath Rename remote file\n"
+"rmdir path Remove remote directory\n"
+"rm path Delete remote file\n"
+"symlink oldpath newpath Symlink remote file\n"
+"version Show SFTP version\n"
+"!command Execute 'command' in local shell\n"
+"! Escape to local shell\n"
+"? Synonym for help\n"
msgstr ""
#
-# File: sftp.c, line: 205
+# File: sftp.c, line: 216
#, c-format
-msgid "Missing username\n"
+msgid "Couldn't fork: %s"
msgstr ""
#
-# File: sftp.c, line: 213
+# File: sftp.c, line: 227
#, c-format
-msgid "Missing hostname\n"
+msgid "Couldn't execute \"%s\": %s\n"
msgstr ""
#
-# File: sftp.c, line: 228
+# File: sftp.c, line: 233
#, c-format
-msgid "Connecting to %s...\n"
+msgid "Couldn't wait for child: %s"
msgstr ""
#
# File: sftp.c, line: 235
-#, c-format
-msgid "Attaching to %s...\n"
+msgid "Shell exited abnormally"
msgstr ""
#
-# File: sftp.c, line: 254
+# File: sftp.c, line: 237
#, c-format
-msgid "Couldn't wait for ssh process: %s"
+msgid "Shell exited with status %d"
msgstr ""
#
-# File: sftp-client.c, line: 78
+# File: sftp.c, line: 316
+msgid "Invalid path"
+msgstr ""
+#
+# File: sftp.c, line: 337
+# File: sftp.c, line: 389
#, c-format
-msgid "Couldn't send packet: %s"
+msgid "Invalid flag -%c"
msgstr ""
#
-# File: sftp-client.c, line: 91
-# File: sftp-client.c, line: 102
-msgid "Connection closed"
+# File: sftp.c, line: 427
+msgid "Unterminated quote"
msgstr ""
#
-# File: sftp-client.c, line: 93
-# File: sftp-client.c, line: 104
+# File: sftp.c, line: 434
#, c-format
-msgid "Couldn't read packet: %s"
+msgid "Bad escaped character '\\%c'"
msgstr ""
#
-# File: sftp-client.c, line: 97
+# File: sftp.c, line: 443
+msgid "Empty quotes"
+msgstr ""
+#
+# File: sftp.c, line: 483
#, c-format
-msgid "Received message too long %u"
+msgid "stat %s: %s"
msgstr ""
#
-# File: sftp-client.c, line: 154
-# File: sftp-client.c, line: 180
-# File: sftp-client.c, line: 211
-# File: sftp-client.c, line: 367
-# File: sftp-client.c, line: 577
+# File: sftp.c, line: 517
+# File: sftp.c, line: 585
#, c-format
-msgid "ID mismatch (%u != %u)"
+msgid "File \"%s\" not found."
msgstr ""
#
-# File: sftp-client.c, line: 156
+# File: sftp.c, line: 524
+# File: sftp.c, line: 592
#, c-format
-msgid "Expected SSH2_FXP_STATUS(%u) packet, got %u"
+msgid "Multiple files match, but \"%s\" is not a directory"
msgstr ""
#
-# File: sftp-client.c, line: 184
+# File: sftp.c, line: 554
#, c-format
-msgid "Couldn't get handle: %s"
+msgid "Fetching %s to %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 187
+# File: sftp.c, line: 600
#, c-format
-msgid "Expected SSH2_FXP_HANDLE(%u) packet, got %u"
+msgid "skipping non-regular file %s"
msgstr ""
#
-# File: sftp-client.c, line: 218
+# File: sftp.c, line: 627
#, c-format
-msgid "Couldn't stat remote file: %s"
+msgid "Uploading %s to %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 221
+# File: sftp.c, line: 656
+msgid "Unknown ls sort type"
+msgstr ""
+#
+# File: sftp.c, line: 761
#, c-format
-msgid "Expected SSH2_FXP_ATTRS(%u) packet, got %u"
+msgid "Can't ls: \"%s\" not found"
msgstr ""
#
-# File: sftp-client.c, line: 249
+# File: sftp.c, line: 910
#, c-format
-msgid "Invalid packet back from SSH2_FXP_INIT (type %u)"
+msgid "You must specify at least one path after a %s command."
msgstr ""
#
-# File: sftp-client.c, line: 308
+# File: sftp.c, line: 925
#, c-format
-msgid "Couldn't close file: %s"
+msgid "You must specify two paths after a %s command."
msgstr ""
#
-# File: sftp-client.c, line: 377
+# File: sftp.c, line: 940
+# File: sftp.c, line: 988
#, c-format
-msgid "Couldn't read directory: %s"
+msgid "You must specify a path after a %s command."
msgstr ""
#
-# File: sftp-client.c, line: 383
-# File: sftp-client.c, line: 585
+# File: sftp.c, line: 969
+# File: sftp.c, line: 978
#, c-format
-msgid "Expected SSH2_FXP_NAME(%u) packet, got %u"
+msgid "You must supply a numeric argument to the %s command."
+msgstr ""
+#
+# File: sftp.c, line: 1001
+msgid "Command not implemented"
msgstr ""
#
-# File: sftp-client.c, line: 453
+# File: sftp.c, line: 1057
#, c-format
-msgid "Couldn't delete file: %s"
+msgid "Removing %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 468
+# File: sftp.c, line: 1086
+msgid "Can't change directory: Can't check target"
+msgstr ""
+#
+# File: sftp.c, line: 1092
#, c-format
-msgid "Couldn't create directory: %s"
+msgid "Can't change directory: \"%s\" is not a directory"
msgstr ""
#
-# File: sftp-client.c, line: 484
+# File: sftp.c, line: 1117
#, c-format
-msgid "Couldn't remove directory: %s"
+msgid "Couldn't change local directory to \"%s\": %s"
msgstr ""
#
-# File: sftp-client.c, line: 536
+# File: sftp.c, line: 1124
#, c-format
-msgid "Couldn't setstat on \"%s\": %s"
+msgid "Couldn't create local directory \"%s\": %s"
msgstr ""
#
-# File: sftp-client.c, line: 554
+# File: sftp.c, line: 1137
#, c-format
-msgid "Couldn't fsetstat: %s"
+msgid "Local umask: %03lo\n"
msgstr ""
#
-# File: sftp-client.c, line: 582
+# File: sftp.c, line: 1146
#, c-format
-msgid "Couldn't canonicalise: %s"
+msgid "Changing mode on %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 590
+# File: sftp.c, line: 1164
#, c-format
-msgid "Got multiple names (%d) from SSH_FXP_REALPATH"
+msgid "Can't get current ownership of remote file \"%s\""
msgstr ""
#
-# File: sftp-client.c, line: 626
-# File: sftp-client.c, line: 658
+# File: sftp.c, line: 1173
#, c-format
-msgid "Couldn't rename file \"%s\" to \"%s\": %s"
+msgid "Changing owner on %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 639
-msgid "This server does not support the symlink operation"
+# File: sftp.c, line: 1176
+#, c-format
+msgid "Changing group on %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 717
+# File: sftp.c, line: 1185
#, c-format
-msgid "Cannot download a directory: %s"
+msgid "Remote working directory: %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 748
+# File: sftp.c, line: 1189
#, c-format
-msgid "Couldn't open local file \"%s\" for writing: %s"
+msgid "Couldn't get local cwd: %s"
msgstr ""
#
-# File: sftp-client.c, line: 791
+# File: sftp.c, line: 1193
#, c-format
-msgid "Unexpected reply %u"
+msgid "Local working directory: %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 809
+# File: sftp.c, line: 1202
#, c-format
-msgid "Received more data than asked for %u > %u"
+msgid "SFTP protocol version %u\n"
msgstr ""
#
-# File: sftp-client.c, line: 856
+# File: sftp.c, line: 1212
#, c-format
-msgid "Expected SSH2_FXP_DATA(%u) packet, got %u"
+msgid "%d is not implemented"
msgstr ""
#
-# File: sftp-client.c, line: 863
-msgid "Transfer complete, but requests still in queue"
+# File: sftp.c, line: 1246
+msgid "Couldn't initialise connection to server"
+msgstr ""
+#
+# File: sftp.c, line: 1250
+msgid "Need cwd"
msgstr ""
#
-# File: sftp-client.c, line: 866
+# File: sftp.c, line: 1257
#, c-format
-msgid "Couldn't read from remote file \"%s\" : %s"
+msgid "Changing to: %s\n"
msgstr ""
#
-# File: sftp-client.c, line: 870
+# File: sftp.c, line: 1340
#, c-format
-msgid "Couldn't write to \"%s\": %s"
+msgid "socketpair: %s"
msgstr ""
#
-# File: sftp-client.c, line: 881
+# File: sftp.c, line: 1382
#, c-format
-msgid "Couldn't set mode on \"%s\": %s"
+msgid ""
+"Usage: %s [-1Cv] [-b batchfile] [-B buffer_size]\n"
+" [-F ssh_config] [-o ssh_option] [-P sftp_server_path]\n"
+" [-R num_requests] [-s subsystem | sftp_server]\n"
+" [-S program] [user@]host[:dir[/] | :file [file]]\n"
msgstr ""
#
-# File: sftp-client.c, line: 889
+# File: sftp.c, line: 1450
+msgid "Batch file already specified."
+msgstr ""
+#
+# File: sftp.c, line: 1455
#, c-format
-msgid "Can't set times on \"%s\": %s"
+msgid "%s (%s)."
msgstr ""
#
-# File: sftp-client.c, line: 925
+# File: sftp.c, line: 1466
#, c-format
-msgid "Couldn't open local file \"%s\" for reading: %s"
+msgid "Invalid buffer size \"%s\""
msgstr ""
#
-# File: sftp-client.c, line: 930
+# File: sftp.c, line: 1471
#, c-format
-msgid "Couldn't fstat local file \"%s\": %s"
+msgid "Invalid number of requests \"%s\""
+msgstr ""
+#
+# File: sftp.c, line: 1497
+msgid "Missing username\n"
msgstr ""
#
-# File: sftp-client.c, line: 982
+# File: sftp.c, line: 1510
+msgid "Missing hostname\n"
+msgstr ""
+#
+# File: sftp.c, line: 1525
#, c-format
-msgid "Couldn't read from \"%s\": %s"
+msgid "Connecting to %s...\n"
msgstr ""
#
-# File: sftp-client.c, line: 1005
+# File: sftp.c, line: 1532
#, c-format
-msgid "Unexpected ACK %u"
+msgid "Attaching to %s...\n"
msgstr ""
#
-# File: sftp-client.c, line: 1017
+# File: sftp.c, line: 1551
#, c-format
-msgid "Expected SSH2_FXP_STATUS(%d) packet, got %d"
+msgid "Couldn't wait for ssh process: %s"
msgstr ""
#
-# File: sftp-client.c, line: 1029
+# File: sftp-client.c, line: 81
#, c-format
-msgid "Can't find request for ID %u"
+msgid "Outbound message too long %u"
msgstr ""
#
-# File: sftp-client.c, line: 1033
+# File: sftp-client.c, line: 91
#, c-format
-msgid "Couldn't write to remote file \"%s\": %s"
+msgid "Couldn't send packet: %s"
msgstr ""
#
-# File: sftp-client.c, line: 1049
+# File: sftp-client.c, line: 104
+# File: sftp-client.c, line: 116
+msgid "Connection closed"
+msgstr ""
+#
+# File: sftp-client.c, line: 106
#, c-format
-msgid "Couldn't close local file \"%s\": %s"
+msgid "Couldn't read packet: %s"
msgstr ""
#
-# File: sftp-int.c, line: 105
+# File: sftp-client.c, line: 111
#, c-format
-msgid ""
-"Available commands:\n"
-"cd path Change remote directory to 'path'\n"
-"lcd path Change local directory to 'path'\n"
-"chgrp grp path Change group of file 'path' to 'grp'\n"
-"chmod mode path Change permissions of file 'path' to "
-"'mode'\n"
-"chown own path Change owner of file 'path' to 'own'\n"
-"help Display this help text\n"
-"get remote-path [local-path] Download file\n"
-"lls [ls-options [path]] Display local directory listing\n"
-"ln oldpath newpath Symlink remote file\n"
-"lmkdir path Create local directory\n"
-"lpwd Print local working directory\n"
-"ls [path] Display remote directory listing\n"
-"lumask umask Set local umask to 'umask'\n"
-"mkdir path Create remote directory\n"
-"put local-path [remote-path] Upload file\n"
-"pwd Display remote working directory\n"
-"exit Quit sftp\n"
-"quit Quit sftp\n"
-"rename oldpath newpath Rename remote file\n"
-"rmdir path Remove remote directory\n"
-"rm path Delete remote file\n"
-"symlink oldpath newpath Symlink remote file\n"
-"version Show SFTP version\n"
-"!command Execute 'command' in local shell\n"
-"! Escape to local shell\n"
-"? Synonym for help\n"
+msgid "Received message too long %u"
msgstr ""
#
-# File: sftp-int.c, line: 151
+# File: sftp-client.c, line: 118
#, c-format
-msgid "Couldn't fork: %s"
+msgid "Read packet: %s"
msgstr ""
#
-# File: sftp-int.c, line: 162
+# File: sftp-client.c, line: 165
+# File: sftp-client.c, line: 191
+# File: sftp-client.c, line: 223
+# File: sftp-client.c, line: 378
+# File: sftp-client.c, line: 598
#, c-format
-msgid "Couldn't execute \"%s\": %s\n"
+msgid "ID mismatch (%u != %u)"
msgstr ""
#
-# File: sftp-int.c, line: 168
+# File: sftp-client.c, line: 167
#, c-format
-msgid "Couldn't wait for child: %s"
+msgid "Expected SSH2_FXP_STATUS(%u) packet, got %u"
msgstr ""
#
-# File: sftp-int.c, line: 170
-msgid "Shell exited abnormally"
+# File: sftp-client.c, line: 195
+#, c-format
+msgid "Couldn't get handle: %s"
msgstr ""
#
-# File: sftp-int.c, line: 172
+# File: sftp-client.c, line: 199
#, c-format
-msgid "Shell exited with status %d"
+msgid "Expected SSH2_FXP_HANDLE(%u) packet, got %u"
msgstr ""
#
-# File: sftp-int.c, line: 251
-msgid "Invalid path"
+# File: sftp-client.c, line: 230
+#, c-format
+msgid "Couldn't stat remote file: %s"
msgstr ""
#
-# File: sftp-int.c, line: 272
-# File: sftp-int.c, line: 295
+# File: sftp-client.c, line: 234
#, c-format
-msgid "Invalid flag -%c"
+msgid "Expected SSH2_FXP_ATTRS(%u) packet, got %u"
msgstr ""
#
-# File: sftp-int.c, line: 325
-msgid "Unterminated quote"
+# File: sftp-client.c, line: 262
+#, c-format
+msgid "Invalid packet back from SSH2_FXP_INIT (type %u)"
msgstr ""
#
-# File: sftp-int.c, line: 329
-msgid "Empty quotes"
+# File: sftp-client.c, line: 321
+#, c-format
+msgid "Couldn't close file: %s"
msgstr ""
#
-# File: sftp-int.c, line: 394
-# File: sftp-int.c, line: 473
+# File: sftp-client.c, line: 388
#, c-format
-msgid "File \"%s\" not found."
+msgid "Couldn't read directory: %s"
msgstr ""
#
-# File: sftp-int.c, line: 416
-# File: sftp-int.c, line: 440
+# File: sftp-client.c, line: 395
+# File: sftp-client.c, line: 606
#, c-format
-msgid "Fetching %s to %s\n"
+msgid "Expected SSH2_FXP_NAME(%u) packet, got %u"
msgstr ""
#
-# File: sftp-int.c, line: 423
-# File: sftp-int.c, line: 505
+# File: sftp-client.c, line: 471
#, c-format
-msgid "Multiple files match, but \"%s\" is not a directory"
+msgid "Couldn't delete file: %s"
msgstr ""
#
-# File: sftp-int.c, line: 498
-# File: sftp-int.c, line: 522
+# File: sftp-client.c, line: 486
#, c-format
-msgid "Uploading %s to %s\n"
+msgid "Couldn't create directory: %s"
msgstr ""
#
-# File: sftp-int.c, line: 602
+# File: sftp-client.c, line: 502
#, c-format
-msgid "Can't ls: \"%s\" not found"
+msgid "Couldn't remove directory: %s"
msgstr ""
#
-# File: sftp-int.c, line: 711
+# File: sftp-client.c, line: 555
#, c-format
-msgid "You must specify at least one path after a %s command."
+msgid "Couldn't setstat on \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 726
+# File: sftp-client.c, line: 573
#, c-format
-msgid "You must specify two paths after a %s command."
+msgid "Couldn't fsetstat: %s"
msgstr ""
#
-# File: sftp-int.c, line: 741
-# File: sftp-int.c, line: 788
+# File: sftp-client.c, line: 603
#, c-format
-msgid "You must specify a path after a %s command."
+msgid "Couldn't canonicalise: %s"
msgstr ""
#
-# File: sftp-int.c, line: 769
-# File: sftp-int.c, line: 778
+# File: sftp-client.c, line: 611
#, c-format
-msgid "You must supply a numeric argument to the %s command."
+msgid "Got multiple names (%d) from SSH_FXP_REALPATH"
msgstr ""
#
-# File: sftp-int.c, line: 800
-msgid "Command not implemented"
+# File: sftp-client.c, line: 647
+#, c-format
+msgid "Couldn't rename file \"%s\" to \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 847
+# File: sftp-client.c, line: 660
+msgid "This server does not support the symlink operation"
+msgstr ""
+#
+# File: sftp-client.c, line: 679
#, c-format
-msgid "Removing %s\n"
+msgid "Couldn't symlink file \"%s\" to \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 875
-msgid "Can't change directory: Can't check target"
+# File: sftp-client.c, line: 740
+#, c-format
+msgid "Cannot download non-regular file: %s"
msgstr ""
#
-# File: sftp-int.c, line: 881
+# File: sftp-client.c, line: 772
#, c-format
-msgid "Can't change directory: \"%s\" is not a directory"
+msgid "Couldn't open local file \"%s\" for writing: %s"
msgstr ""
#
-# File: sftp-int.c, line: 907
+# File: sftp-client.c, line: 831
#, c-format
-msgid "Couldn't change local directory to \"%s\": %s"
+msgid "Unexpected reply %u"
msgstr ""
#
-# File: sftp-int.c, line: 914
+# File: sftp-client.c, line: 849
#, c-format
-msgid "Couldn't create local directory \"%s\": %s"
+msgid "Received more data than asked for %u > %u"
msgstr ""
#
-# File: sftp-int.c, line: 927
+# File: sftp-client.c, line: 896
#, c-format
-msgid "Local umask: %03lo\n"
+msgid "Expected SSH2_FXP_DATA(%u) packet, got %u"
msgstr ""
#
-# File: sftp-int.c, line: 936
+# File: sftp-client.c, line: 906
+msgid "Transfer complete, but requests still in queue"
+msgstr ""
+#
+# File: sftp-client.c, line: 909
#, c-format
-msgid "Changing mode on %s\n"
+msgid "Couldn't read from remote file \"%s\" : %s"
msgstr ""
#
-# File: sftp-int.c, line: 947
-# File: sftp-int.c, line: 965
+# File: sftp-client.c, line: 913
#, c-format
-msgid "Can't get current ownership of remote file \"%s\""
+msgid "Couldn't write to \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 951
+# File: sftp-client.c, line: 924
#, c-format
-msgid "Changing owner on %s\n"
+msgid "Couldn't set mode on \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 969
+# File: sftp-client.c, line: 932
#, c-format
-msgid "Changing group on %s\n"
+msgid "Can't set times on \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 977
+# File: sftp-client.c, line: 968
#, c-format
-msgid "Remote working directory: %s\n"
+msgid "Couldn't open local file \"%s\" for reading: %s"
msgstr ""
#
-# File: sftp-int.c, line: 981
+# File: sftp-client.c, line: 973
#, c-format
-msgid "Couldn't get local cwd: %s"
+msgid "Couldn't fstat local file \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 984
+# File: sftp-client.c, line: 979
#, c-format
-msgid "Local working directory: %s\n"
+msgid "%s is not a regular file"
msgstr ""
#
-# File: sftp-int.c, line: 993
+# File: sftp-client.c, line: 1037
#, c-format
-msgid "SFTP protocol version %u\n"
+msgid "Couldn't read from \"%s\": %s"
msgstr ""
#
-# File: sftp-int.c, line: 997
+# File: sftp-client.c, line: 1060
#, c-format
-msgid "%d is not implemented"
+msgid "Unexpected ACK %u"
msgstr ""
#
-# File: sftp-int.c, line: 1024
-msgid "Couldn't initialise connection to server"
+# File: sftp-client.c, line: 1072
+#, c-format
+msgid "Expected SSH2_FXP_STATUS(%d) packet, got %d"
msgstr ""
#
-# File: sftp-int.c, line: 1028
-msgid "Need cwd"
+# File: sftp-client.c, line: 1084
+#, c-format
+msgid "Can't find request for ID %u"
msgstr ""
#
-# File: sftp-int.c, line: 1035
+# File: sftp-client.c, line: 1088
#, c-format
-msgid "Changing to: %s\n"
+msgid "Couldn't write to remote file \"%s\": %s"
msgstr ""
#
-# File: ssh-http-proxy-connect.c, line: 63
+# File: sftp-client.c, line: 1111
#, c-format
+msgid "Couldn't close local file \"%s\": %s"
+msgstr ""
+#
+# File: ssh-http-proxy-connect.c, line: 63
msgid ""
"Usage: ssh-http-proxy-connect [-h http_proxy_host] [-p "
"http_proxy_port]\n"
@@ -5571,14 +5693,12 @@ msgid ""
msgstr ""
#
# File: ssh-http-proxy-connect.c, line: 158
-#, c-format
msgid ""
"ssh-http-proxy: Incorrect url specified for http_proxy environment "
"variable\n"
msgstr ""
#
# File: ssh-http-proxy-connect.c, line: 167
-#, c-format
msgid "ssh-http-proxy: http proxy not specified\n"
msgstr ""
#
@@ -5588,12 +5708,10 @@ msgid "ssh-http-proxy: Unable to connect to %s: %s\n"
msgstr ""
#
# File: ssh-http-proxy-connect.c, line: 230
-#, c-format
msgid "ssh-http-proxy: HTTP reply not understood\n"
msgstr ""
#
# File: ssh-socks5-proxy-connect.c, line: 63
-#, c-format
msgid ""
"Usage: ssh-socks5-proxy-connect [-h socks5_proxy_host] [-p "
"socks5_proxy_port] \n"
@@ -5606,7 +5724,6 @@ msgid "Unsupported SOCKS version: %x\n"
msgstr ""
#
# File: ssh-socks5-proxy-connect.c, line: 209
-#, c-format
msgid "ssh-socks5-proxy: SOCKS Server reply not understood\n"
msgstr ""
#
@@ -5616,11 +5733,9 @@ msgid "ssh-socks5-proxy: Address type not supported: %u\n"
msgstr ""
#
# File: ssh-socks5-proxy-connect.c, line: 289
-#, c-format
msgid "ssh-socks5-proxy: SOCKS5 SERVER not specified\n"
msgstr ""
#
# File: ssh-socks5-proxy-connect.c, line: 327
-#, c-format
msgid "ssh-socks5-proxy: Client and Server versions differ.\n"
msgstr ""