version 1.15, 2001/04/16 02:31:44 |
version 1.15.2.2, 2002/03/09 00:20:45 |
|
|
/* |
/* |
* Copyright (c) 2001 Damien Miller. All rights reserved. |
* Copyright (c) 2001,2002 Damien Miller. All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* modification, are permitted provided that the following conditions |
|
|
|
|
RCSID("$OpenBSD$"); |
RCSID("$OpenBSD$"); |
|
|
/* XXX: commandline mode */ |
|
/* XXX: short-form remote directory listings (like 'ls -C') */ |
/* XXX: short-form remote directory listings (like 'ls -C') */ |
|
|
#include "buffer.h" |
#include "buffer.h" |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "log.h" |
#include "log.h" |
#include "pathnames.h" |
#include "pathnames.h" |
|
#include "misc.h" |
|
|
#include "sftp.h" |
#include "sftp.h" |
#include "sftp-common.h" |
#include "sftp-common.h" |
#include "sftp-client.h" |
#include "sftp-client.h" |
#include "sftp-int.h" |
#include "sftp-int.h" |
|
|
#include "scp-common.h" |
|
|
|
int use_ssh1 = 0; |
|
char *ssh_program = _PATH_SSH_PROGRAM; |
|
char *sftp_server = NULL; |
|
FILE* infile; |
FILE* infile; |
|
size_t copy_buffer_len = 32768; |
|
size_t num_requests = 16; |
|
|
void |
static void |
connect_to_server(char **args, int *in, int *out, pid_t *sshpid) |
connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid) |
{ |
{ |
int c_in, c_out; |
int c_in, c_out; |
#ifdef USE_PIPES |
#ifdef USE_PIPES |
|
|
close(*out); |
close(*out); |
close(c_in); |
close(c_in); |
close(c_out); |
close(c_out); |
execv(ssh_program, args); |
execv(path, args); |
fprintf(stderr, "exec: %s: %s\n", ssh_program, strerror(errno)); |
fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
close(c_out); |
close(c_out); |
} |
} |
|
|
char ** |
static void |
make_ssh_args(char *add_arg) |
|
{ |
|
static char **args = NULL; |
|
static int nargs = 0; |
|
char debug_buf[4096]; |
|
int i; |
|
|
|
/* Init args array */ |
|
if (args == NULL) { |
|
nargs = 2; |
|
i = 0; |
|
args = xmalloc(sizeof(*args) * nargs); |
|
args[i++] = "ssh"; |
|
args[i++] = NULL; |
|
} |
|
|
|
/* If asked to add args, then do so and return */ |
|
if (add_arg) { |
|
i = nargs++ - 1; |
|
args = xrealloc(args, sizeof(*args) * nargs); |
|
args[i++] = add_arg; |
|
args[i++] = NULL; |
|
return(NULL); |
|
} |
|
|
|
/* no subsystem if the server-spec contains a '/' */ |
|
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) |
|
make_ssh_args("-s"); |
|
make_ssh_args("-oForwardX11=no"); |
|
make_ssh_args("-oForwardAgent=no"); |
|
make_ssh_args(use_ssh1 ? "-oProtocol=1" : "-oProtocol=2"); |
|
|
|
/* Otherwise finish up and return the arg array */ |
|
if (sftp_server != NULL) |
|
make_ssh_args(sftp_server); |
|
else |
|
make_ssh_args("sftp"); |
|
|
|
/* XXX: overflow - doesn't grow debug_buf */ |
|
debug_buf[0] = '\0'; |
|
for(i = 0; args[i]; i++) { |
|
if (i) |
|
strlcat(debug_buf, " ", sizeof(debug_buf)); |
|
|
|
strlcat(debug_buf, args[i], sizeof(debug_buf)); |
|
} |
|
debug("SSH args \"%s\"", debug_buf); |
|
|
|
return(args); |
|
} |
|
|
|
void |
|
usage(void) |
usage(void) |
{ |
{ |
fprintf(stderr, "usage: sftp [-1vC] [-b batchfile] [-osshopt=value] [user@]host[:file [file]]\n"); |
extern char *__progname; |
|
|
|
fprintf(stderr, |
|
"usage: %s [-vC1] [-b batchfile] [-o option] [-s subsystem|path] [-B buffer_size]\n" |
|
" [-F config] [-P direct server path] [-S program]\n" |
|
" [user@]host[:file [file]]\n", __progname); |
exit(1); |
exit(1); |
} |
} |
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
int in, out, ch, debug_level, compress_flag; |
int in, out, ch; |
pid_t sshpid; |
pid_t sshpid; |
char *file1 = NULL; |
|
char *host, *userhost, *cp, *file2; |
char *host, *userhost, *cp, *file2; |
LogLevel ll; |
int debug_level = 0, sshver = 2; |
|
char *file1 = NULL, *sftp_server = NULL; |
|
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; |
|
LogLevel ll = SYSLOG_LEVEL_INFO; |
|
arglist args; |
extern int optind; |
extern int optind; |
extern char *optarg; |
extern char *optarg; |
|
|
|
args.list = NULL; |
|
addargs(&args, "ssh"); /* overwritten with ssh_program */ |
|
addargs(&args, "-oFallBackToRsh no"); |
|
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; /* Read from STDIN unless changed by -b */ |
debug_level = compress_flag = 0; |
|
|
|
while ((ch = getopt(argc, argv, "1hvCo:s:S:b:")) != -1) { |
while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { |
switch (ch) { |
switch (ch) { |
case 'C': |
case 'C': |
compress_flag = 1; |
addargs(&args, "-C"); |
break; |
break; |
case 'v': |
case 'v': |
debug_level = MIN(3, debug_level + 1); |
if (debug_level < 3) { |
|
addargs(&args, "-v"); |
|
ll = SYSLOG_LEVEL_DEBUG1 + debug_level; |
|
} |
|
debug_level++; |
break; |
break; |
|
case 'F': |
case 'o': |
case 'o': |
make_ssh_args("-o"); |
addargs(&args, "-%c%s", ch, optarg); |
make_ssh_args(optarg); |
|
break; |
break; |
case '1': |
case '1': |
use_ssh1 = 1; |
sshver = 1; |
if (sftp_server == NULL) |
if (sftp_server == NULL) |
sftp_server = _PATH_SFTP_SERVER; |
sftp_server = _PATH_SFTP_SERVER; |
break; |
break; |
|
|
} else |
} else |
fatal("Filename already specified."); |
fatal("Filename already specified."); |
break; |
break; |
|
case 'P': |
|
sftp_direct = optarg; |
|
break; |
|
case 'B': |
|
copy_buffer_len = strtol(optarg, &cp, 10); |
|
if (copy_buffer_len == 0 || *cp != '\0') |
|
fatal("Invalid buffer size \"%s\"", optarg); |
|
break; |
|
case 'R': |
|
num_requests = strtol(optarg, &cp, 10); |
|
if (num_requests == 0 || *cp != '\0') |
|
fatal("Invalid number of requests \"%s\"", |
|
optarg); |
|
break; |
case 'h': |
case 'h': |
default: |
default: |
usage(); |
usage(); |
} |
} |
} |
} |
|
|
if (optind == argc || argc > (optind + 2)) |
if (sftp_direct == NULL) { |
usage(); |
if (optind == argc || argc > (optind + 2)) |
|
usage(); |
|
|
userhost = xstrdup(argv[optind]); |
userhost = xstrdup(argv[optind]); |
file2 = argv[optind+1]; |
file2 = argv[optind+1]; |
|
|
if ((cp = colon(userhost)) != NULL) { |
if ((cp = colon(userhost)) != NULL) { |
*cp++ = '\0'; |
*cp++ = '\0'; |
file1 = cp; |
file1 = cp; |
} |
} |
|
|
if ((host = strchr(userhost, '@')) == NULL) |
if ((host = strchr(userhost, '@')) == NULL) |
host = userhost; |
host = userhost; |
else { |
else { |
*host++ = '\0'; |
*host++ = '\0'; |
if (!userhost[0]) { |
if (!userhost[0]) { |
fprintf(stderr, "Missing username\n"); |
fprintf(stderr, "Missing username\n"); |
|
usage(); |
|
} |
|
addargs(&args, "-l%s",userhost); |
|
} |
|
|
|
host = cleanhostname(host); |
|
if (!*host) { |
|
fprintf(stderr, "Missing hostname\n"); |
usage(); |
usage(); |
} |
} |
make_ssh_args("-l"); |
|
make_ssh_args(userhost); |
|
} |
|
|
|
host = cleanhostname(host); |
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); |
if (!*host) { |
addargs(&args, "-oProtocol %d", sshver); |
fprintf(stderr, "Missing hostname\n"); |
|
usage(); |
|
} |
|
|
|
/* Set up logging and debug '-d' arguments to ssh */ |
/* no subsystem if the server-spec contains a '/' */ |
ll = SYSLOG_LEVEL_INFO; |
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) |
switch (debug_level) { |
addargs(&args, "-s"); |
case 1: |
|
ll = SYSLOG_LEVEL_DEBUG1; |
|
make_ssh_args("-v"); |
|
break; |
|
case 2: |
|
ll = SYSLOG_LEVEL_DEBUG2; |
|
make_ssh_args("-v"); |
|
make_ssh_args("-v"); |
|
break; |
|
case 3: |
|
ll = SYSLOG_LEVEL_DEBUG3; |
|
make_ssh_args("-v"); |
|
make_ssh_args("-v"); |
|
make_ssh_args("-v"); |
|
break; |
|
} |
|
|
|
if (compress_flag) |
addargs(&args, "%s", host); |
make_ssh_args("-C"); |
addargs(&args, "%s", (sftp_server != NULL ? |
|
sftp_server : "sftp")); |
|
args.list[0] = ssh_program; |
|
|
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); |
fprintf(stderr, "Connecting to %s...\n", host); |
|
connect_to_server(ssh_program, args.list, &in, &out, |
|
&sshpid); |
|
} else { |
|
args.list = NULL; |
|
addargs(&args, "sftp-server"); |
|
|
make_ssh_args(host); |
fprintf(stderr, "Attaching to %s...\n", sftp_direct); |
|
connect_to_server(sftp_direct, args.list, &in, &out, |
fprintf(stderr, "Connecting to %s...\n", host); |
&sshpid); |
|
} |
connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid); |
|
|
|
interactive_loop(in, out, file1, file2); |
interactive_loop(in, out, file1, file2); |
|
|