aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssh/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/sftp.c')
-rw-r--r--crypto/openssh/sftp.c304
1 files changed, 160 insertions, 144 deletions
diff --git a/crypto/openssh/sftp.c b/crypto/openssh/sftp.c
index 7db86c2d3cf0..69f84cdcf1a4 100644
--- a/crypto/openssh/sftp.c
+++ b/crypto/openssh/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.186 2018/09/07 04:26:56 dtucker Exp $ */
+/* $OpenBSD: sftp.c,v 1.211 2021/08/12 09:59:00 schwarze Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -53,7 +53,6 @@ typedef void EditLine;
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <stdarg.h>
#ifdef HAVE_UTIL_H
# include <util.h>
@@ -71,9 +70,6 @@ typedef void EditLine;
#include "sftp-common.h"
#include "sftp-client.h"
-#define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */
-#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */
-
/* File to read commands from */
FILE* infile;
@@ -83,7 +79,7 @@ int batchmode = 0;
/* PID of ssh transport process */
static volatile pid_t sshpid = -1;
-/* Suppress diagnositic messages */
+/* Suppress diagnostic messages */
int quiet = 0;
/* This is set to 0 if the progressmeter is not desired. */
@@ -221,9 +217,12 @@ static const struct CMD cmds[] = {
static void
killchild(int signo)
{
- if (sshpid > 1) {
- kill(sshpid, SIGTERM);
- waitpid(sshpid, NULL, 0);
+ pid_t pid;
+
+ pid = sshpid;
+ if (pid > 1) {
+ kill(pid, SIGTERM);
+ waitpid(pid, NULL, 0);
}
_exit(1);
@@ -253,6 +252,13 @@ cmd_interrupt(int signo)
errno = olderrno;
}
+/* ARGSUSED */
+static void
+read_interrupt(int signo)
+{
+ interrupted = 1;
+}
+
/*ARGSUSED*/
static void
sigchld_handler(int sig)
@@ -278,15 +284,13 @@ help(void)
printf("Available commands:\n"
"bye Quit sftp\n"
"cd path Change remote 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"
+ "chgrp [-h] grp path Change group of file 'path' to 'grp'\n"
+ "chmod [-h] mode path Change permissions of file 'path' to 'mode'\n"
+ "chown [-h] own path Change owner of file 'path' to 'own'\n"
"df [-hi] [path] Display statistics for current directory or\n"
" filesystem containing 'path'\n"
"exit Quit sftp\n"
- "get [-afPpRr] remote [local] Download file\n"
- "reget [-fPpRr] remote [local] Resume download file\n"
- "reput [-fPpRr] [local] remote Resume upload file\n"
+ "get [-afpR] remote [local] Download file\n"
"help Display this help text\n"
"lcd path Change local directory to 'path'\n"
"lls [ls-options [path]] Display local directory listing\n"
@@ -297,10 +301,12 @@ help(void)
"lumask umask Set local umask to 'umask'\n"
"mkdir path Create remote directory\n"
"progress Toggle display of progress meter\n"
- "put [-afPpRr] local [remote] Upload file\n"
+ "put [-afpR] local [remote] Upload file\n"
"pwd Display remote working directory\n"
"quit Quit sftp\n"
+ "reget [-fpR] remote [local] Resume download file\n"
"rename oldpath newpath Rename remote file\n"
+ "reput [-fpR] local [remote] Resume upload file\n"
"rm path Delete remote file\n"
"rmdir path Remove remote directory\n"
"symlink oldpath newpath Symlink remote file\n"
@@ -383,20 +389,6 @@ path_strip(const char *path, const char *strip)
return (xstrdup(path));
}
-static char *
-make_absolute(char *p, const char *pwd)
-{
- char *abs_str;
-
- /* Derelativise */
- if (p && p[0] != '/') {
- abs_str = path_append(pwd, p);
- free(p);
- return(abs_str);
- } else
- return(p);
-}
-
static int
parse_getput_flags(const char *cmd, char **argv, int argc,
int *aflag, int *fflag, int *pflag, int *rflag)
@@ -562,7 +554,7 @@ parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
}
static int
-parse_no_flags(const char *cmd, char **argv, int argc)
+parse_ch_flags(const char *cmd, char **argv, int argc, int *hflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
@@ -570,8 +562,12 @@ parse_no_flags(const char *cmd, char **argv, int argc)
optind = optreset = 1;
opterr = 0;
- while ((ch = getopt(argc, argv, "")) != -1) {
+ *hflag = 0;
+ while ((ch = getopt(argc, argv, "h")) != -1) {
switch (ch) {
+ case 'h':
+ *hflag = 1;
+ break;
default:
error("%s: Invalid flag -%c", cmd, optopt);
return -1;
@@ -582,37 +578,23 @@ parse_no_flags(const char *cmd, char **argv, int argc)
}
static int
-is_dir(const char *path)
+parse_no_flags(const char *cmd, char **argv, int argc)
{
- struct stat sb;
-
- /* XXX: report errors? */
- if (stat(path, &sb) == -1)
- return(0);
-
- return(S_ISDIR(sb.st_mode));
-}
+ extern int opterr, optind, optopt, optreset;
+ int ch;
-static int
-remote_is_dir(struct sftp_conn *conn, const 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));
-}
+ optind = optreset = 1;
+ opterr = 0;
-/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
-static int
-pathname_is_dir(const char *pathname)
-{
- size_t l = strlen(pathname);
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ error("%s: Invalid flag -%c", cmd, optopt);
+ return -1;
+ }
+ }
- return l > 0 && pathname[l - 1] == '/';
+ return optind;
}
static int
@@ -644,7 +626,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
* If multiple matches then dst must be a directory or
* unspecified.
*/
- if (g.gl_matchc > 1 && dst != NULL && !is_dir(dst)) {
+ if (g.gl_matchc > 1 && dst != NULL && !local_is_dir(dst)) {
error("Multiple source paths, but destination "
"\"%s\" is not a directory", dst);
err = -1;
@@ -661,7 +643,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
}
if (g.gl_matchc == 1 && dst) {
- if (is_dir(dst)) {
+ if (local_is_dir(dst)) {
abs_dst = path_append(dst, filename);
} else {
abs_dst = xstrdup(dst);
@@ -680,10 +662,11 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
else if (!quiet && !resume)
mprintf("Fetching %s to %s\n",
g.gl_pathv[i], abs_dst);
- if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
+ /* XXX follow link flag */
+ if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
pflag || global_pflag, 1, resume,
- fflag || global_fflag) == -1)
+ fflag || global_fflag, 0) == -1)
err = -1;
} else {
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
@@ -766,17 +749,18 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
}
free(tmp);
- resume |= global_aflag;
+ resume |= global_aflag;
if (!quiet && resume)
mprintf("Resuming upload of %s to %s\n",
g.gl_pathv[i], abs_dst);
else if (!quiet && !resume)
mprintf("Uploading %s to %s\n",
g.gl_pathv[i], abs_dst);
- if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
+ /* XXX follow_link_flag */
+ if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, 1, resume,
- fflag || global_fflag) == -1)
+ fflag || global_fflag, 0) == -1)
err = -1;
} else {
if (do_upload(conn, g.gl_pathv[i], abs_dst,
@@ -913,7 +897,10 @@ sglob_comp(const void *aa, const void *bb)
return (rmul * strcmp(ap, bp));
else if (sort_flag & LS_TIME_SORT) {
#if defined(HAVE_STRUCT_STAT_ST_MTIM)
- return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <));
+ if (timespeccmp(&as->st_mtim, &bs->st_mtim, ==))
+ return 0;
+ return timespeccmp(&as->st_mtim, &bs->st_mtim, <) ?
+ rmul : -rmul;
#elif defined(HAVE_STRUCT_STAT_ST_MTIME)
return (rmul * NCMP(as->st_mtime, bs->st_mtime));
#else
@@ -1146,7 +1133,7 @@ undo_glob_escape(char *s)
* last argument's quote has been properly terminated or 0 otherwise.
* This parameter is only of use if "sloppy" is set.
*/
-#define MAXARGS 128
+#define MAXARGS 128
#define MAXARGLEN 8192
static char **
makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
@@ -1296,7 +1283,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
}
static int
-parse_args(const char **cpp, int *ignore_errors, int *aflag,
+parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag,
int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
int *rflag, int *sflag,
unsigned long *n_arg, char **path1, char **path2)
@@ -1304,19 +1291,29 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag,
const char *cmd, *cp = *cpp;
char *cp2, **argv;
int base = 0;
- long l;
+ long long ll;
int path1_mandatory = 0, i, cmdnum, optidx, argc;
/* Skip leading whitespace */
cp = cp + strspn(cp, WHITESPACE);
- /* Check for leading '-' (disable error processing) */
+ /*
+ * Check for leading '-' (disable error processing) and '@' (suppress
+ * command echo)
+ */
*ignore_errors = 0;
- if (*cp == '-') {
- *ignore_errors = 1;
- cp++;
- cp = cp + strspn(cp, WHITESPACE);
+ *disable_echo = 0;
+ for (;*cp != '\0'; cp++) {
+ if (*cp == '-') {
+ *ignore_errors = 1;
+ } else if (*cp == '@') {
+ *disable_echo = 1;
+ } else {
+ /* all other characters terminate prefix processing */
+ break;
+ }
}
+ cp = cp + strspn(cp, WHITESPACE);
/* Ignore blank lines and lines which begin with comment '#' char */
if (*cp == '\0' || *cp == '#')
@@ -1446,22 +1443,22 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag,
/* FALLTHROUGH */
case I_CHOWN:
case I_CHGRP:
- if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
+ if ((optidx = parse_ch_flags(cmd, argv, argc, hflag)) == -1)
return -1;
/* Get numeric arg (mandatory) */
if (argc - optidx < 1)
goto need_num_arg;
errno = 0;
- l = strtol(argv[optidx], &cp2, base);
+ ll = strtoll(argv[optidx], &cp2, base);
if (cp2 == argv[optidx] || *cp2 != '\0' ||
- ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
- l < 0) {
+ ((ll == LLONG_MIN || ll == LLONG_MAX) && errno == ERANGE) ||
+ ll < 0 || ll > UINT32_MAX) {
need_num_arg:
error("You must supply a numeric argument "
"to the %s command.", cmd);
return -1;
}
- *n_arg = l;
+ *n_arg = ll;
if (cmdnum == I_LUMASK)
break;
/* Get pathname (mandatory) */
@@ -1491,11 +1488,12 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag,
static int
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
- const char *startdir, int err_abort)
+ const char *startdir, int err_abort, int echo_command)
{
+ const char *ocmd = cmd;
char *path1, *path2, *tmp;
- int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0,
- iflag = 0;
+ int ignore_errors = 0, disable_echo = 1;
+ int aflag = 0, fflag = 0, hflag = 0, iflag = 0;
int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
int cmdnum, i;
unsigned long n_arg = 0;
@@ -1505,11 +1503,15 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
glob_t g;
path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
- &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2);
+ cmdnum = parse_args(&cmd, &ignore_errors, &disable_echo, &aflag, &fflag,
+ &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg,
+ &path1, &path2);
if (ignore_errors != 0)
err_abort = 0;
+ if (echo_command && !disable_echo)
+ mprintf("sftp> %s\n", ocmd);
+
memset(&g, 0, sizeof(g));
/* Perform command */
@@ -1608,7 +1610,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
/* Strip pwd off beginning of non-absolute paths */
tmp = NULL;
- if (*path1 != '/')
+ if (!path_absolute(path1))
tmp = *pwd;
path1 = make_absolute(path1, *pwd);
@@ -1660,7 +1662,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
if (!quiet)
mprintf("Changing mode on %s\n",
g.gl_pathv[i]);
- err = do_setstat(conn, g.gl_pathv[i], &a);
+ err = (hflag ? do_lsetstat : do_setstat)(conn,
+ g.gl_pathv[i], &a);
if (err != 0 && err_abort)
break;
}
@@ -1670,7 +1673,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
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 (!(aa = (hflag ? do_lstat : do_stat)(conn,
+ g.gl_pathv[i], 0))) {
if (err_abort) {
err = -1;
break;
@@ -1698,7 +1702,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
g.gl_pathv[i]);
aa->gid = n_arg;
}
- err = do_setstat(conn, g.gl_pathv[i], aa);
+ err = (hflag ? do_lsetstat : do_setstat)(conn,
+ g.gl_pathv[i], aa);
if (err != 0 && err_abort)
break;
}
@@ -1936,7 +1941,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
xasprintf(&tmp, "%s*", file);
/* Check if the path is absolute. */
- isabs = tmp[0] == '/';
+ isabs = path_absolute(tmp);
memset(&g, 0, sizeof(g));
if (remote != LOCAL) {
@@ -2057,7 +2062,7 @@ complete(EditLine *el, int ch)
lf = el_line(el);
if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0)
- fatal("%s: el_get failed", __func__);
+ fatal_f("el_get failed");
/* Figure out which argument the cursor points to */
cursor = lf->cursor - lf->buffer;
@@ -2147,7 +2152,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
/* enable ctrl-left-arrow and ctrl-right-arrow */
el_set(el, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
- el_set(el, EL_BIND, "\\e[5C", "em-next-word", NULL);
+ el_set(el, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
el_set(el, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
/* make ^w match ksh behaviour */
@@ -2169,7 +2174,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
mprintf("Changing to: %s\n", dir);
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
if (parse_dispatch_command(conn, cmd,
- &remote_path, startdir, 1) != 0) {
+ &remote_path, startdir, 1, 0) != 0) {
free(dir);
free(startdir);
free(remote_path);
@@ -2183,7 +2188,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
file2 == NULL ? "" : " ",
file2 == NULL ? "" : file2);
err = parse_dispatch_command(conn, cmd,
- &remote_path, startdir, 1);
+ &remote_path, startdir, 1, 0);
free(dir);
free(startdir);
free(remote_path);
@@ -2199,10 +2204,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
interactive = !batchmode && isatty(STDIN_FILENO);
err = 0;
for (;;) {
- char *cp;
-
- signal(SIGINT, SIG_IGN);
-
if (el == NULL) {
if (interactive)
printf("sftp> ");
@@ -2211,21 +2212,26 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
printf("\n");
break;
}
- if (!interactive) { /* Echo command */
- mprintf("sftp> %s", cmd);
- if (strlen(cmd) > 0 &&
- cmd[strlen(cmd) - 1] != '\n')
- printf("\n");
- }
} else {
#ifdef USE_LIBEDIT
const char *line;
int count = 0;
-
+ struct sigaction sa;
+
+ interrupted = 0;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = read_interrupt;
+ if (sigaction(SIGINT, &sa, NULL) == -1) {
+ debug3("sigaction(%s): %s",
+ strsignal(SIGINT), strerror(errno));
+ break;
+ }
if ((line = el_gets(el, &count)) == NULL ||
count <= 0) {
printf("\n");
- break;
+ if (interrupted)
+ continue;
+ break;
}
history(hl, &hev, H_ENTER, line);
if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {
@@ -2235,20 +2241,18 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
#endif /* USE_LIBEDIT */
}
- cp = strrchr(cmd, '\n');
- if (cp)
- *cp = '\0';
+ cmd[strcspn(cmd, "\n")] = '\0';
/* Handle user interrupts gracefully during commands */
interrupted = 0;
- signal(SIGINT, cmd_interrupt);
+ ssh_signal(SIGINT, cmd_interrupt);
err = parse_dispatch_command(conn, cmd, &remote_path,
- startdir, batchmode);
+ startdir, batchmode, !interactive && el == NULL);
if (err != 0)
break;
}
- signal(SIGCHLD, SIG_DFL);
+ ssh_signal(SIGCHLD, SIG_DFL);
free(remote_path);
free(startdir);
free(conn);
@@ -2305,20 +2309,20 @@ connect_to_server(char *path, char **args, int *in, int *out)
* kill it too. Contrawise, since sftp sends SIGTERMs to the
* underlying ssh, it must *not* ignore that signal.
*/
- signal(SIGINT, SIG_IGN);
- signal(SIGTERM, SIG_DFL);
+ ssh_signal(SIGINT, SIG_IGN);
+ ssh_signal(SIGTERM, SIG_DFL);
execvp(path, args);
fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
_exit(1);
}
- signal(SIGTERM, killchild);
- signal(SIGINT, killchild);
- signal(SIGHUP, killchild);
- signal(SIGTSTP, suspchild);
- signal(SIGTTIN, suspchild);
- signal(SIGTTOU, suspchild);
- signal(SIGCHLD, sigchld_handler);
+ ssh_signal(SIGTERM, killchild);
+ ssh_signal(SIGINT, killchild);
+ ssh_signal(SIGHUP, killchild);
+ ssh_signal(SIGTSTP, suspchild);
+ ssh_signal(SIGTTIN, suspchild);
+ ssh_signal(SIGTTOU, suspchild);
+ ssh_signal(SIGCHLD, sigchld_handler);
close(c_in);
close(c_out);
}
@@ -2329,12 +2333,11 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
- " [-D sftp_server_path] [-F ssh_config] "
- "[-i identity_file] [-l limit]\n"
- " [-o ssh_option] [-P port] [-R num_requests] "
- "[-S program]\n"
- " [-s subsystem | sftp_server] destination\n",
+ "usage: %s [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
+ " [-D sftp_server_path] [-F ssh_config] [-i identity_file]\n"
+ " [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
+ " [-R num_requests] [-S program] [-s subsystem | sftp_server]\n"
+ " destination\n",
__progname);
exit(1);
}
@@ -2342,9 +2345,9 @@ usage(void)
int
main(int argc, char **argv)
{
- int in, out, ch, err, tmp, port = -1;
+ int in, out, ch, err, tmp, port = -1, noisy = 0;
char *host = NULL, *user, *cp, *file2 = NULL;
- int debug_level = 0, sshver = 2;
+ int debug_level = 0;
char *file1 = NULL, *sftp_server = NULL;
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
const char *errstr;
@@ -2353,21 +2356,21 @@ main(int argc, char **argv)
extern int optind;
extern char *optarg;
struct sftp_conn *conn;
- size_t copy_buffer_len = DEFAULT_COPY_BUFLEN;
- size_t num_requests = DEFAULT_NUM_REQUESTS;
+ size_t copy_buffer_len = 0;
+ size_t num_requests = 0;
long long limit_kbps = 0;
- ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
msetlocale();
+ seed_rng();
+
__progname = ssh_get_progname(argv[0]);
memset(&args, '\0', sizeof(args));
args.list = NULL;
addargs(&args, "%s", ssh_program);
addargs(&args, "-oForwardX11 no");
- addargs(&args, "-oForwardAgent no");
addargs(&args, "-oPermitLocalCommand no");
addargs(&args, "-oClearAllForwardings yes");
@@ -2375,9 +2378,10 @@ main(int argc, char **argv)
infile = stdin;
while ((ch = getopt(argc, argv,
- "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
+ "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
+ case 'A':
case '4':
case '6':
case 'C':
@@ -2385,6 +2389,7 @@ main(int argc, char **argv)
break;
/* Passed through to ssh(1) with argument */
case 'F':
+ case 'J':
case 'c':
case 'i':
case 'o':
@@ -2410,12 +2415,10 @@ main(int argc, char **argv)
debug_level++;
break;
case '1':
- sshver = 1;
- if (sftp_server == NULL)
- sftp_server = _PATH_SFTP_SERVER;
+ fatal("SSH protocol v.1 is no longer supported");
break;
case '2':
- sshver = 2;
+ /* accept silently */
break;
case 'a':
global_aflag = 1;
@@ -2440,6 +2443,9 @@ main(int argc, char **argv)
case 'f':
global_fflag = 1;
break;
+ case 'N':
+ noisy = 1; /* Used to clear quiet mode after getopt */
+ break;
case 'p':
global_pflag = 1;
break;
@@ -2475,9 +2481,15 @@ main(int argc, char **argv)
}
}
+ /* Do this last because we want the user to be able to override it */
+ addargs(&args, "-oForwardAgent no");
+
if (!isatty(STDERR_FILENO))
showprogress = 0;
+ if (noisy)
+ quiet = 0;
+
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
if (sftp_direct == NULL) {
@@ -2494,12 +2506,17 @@ main(int argc, char **argv)
port = tmp;
break;
default:
+ /* Try with user, host and path. */
if (parse_user_host_path(*argv, &user, &host,
- &file1) == -1) {
- /* Treat as a plain hostname. */
- host = xstrdup(*argv);
- host = cleanhostname(host);
- }
+ &file1) == 0)
+ break;
+ /* Try with user and host. */
+ if (parse_user_host_port(*argv, &user, &host, NULL)
+ == 0)
+ break;
+ /* Treat as a plain hostname. */
+ host = xstrdup(*argv);
+ host = cleanhostname(host);
break;
}
file2 = *(argv + 1);
@@ -2515,7 +2532,6 @@ main(int argc, char **argv)
addargs(&args, "-l");
addargs(&args, "%s", user);
}
- addargs(&args, "-oProtocol %d", sshver);
/* no subsystem if the server-spec contains a '/' */
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)