version 1.21, 2001/09/19 19:24:19 |
version 1.21.2.1, 2002/03/07 17:37:47 |
|
|
/* |
/* |
* 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 "sftp-client.h" |
#include "sftp-client.h" |
#include "sftp-int.h" |
#include "sftp-int.h" |
|
|
char *ssh_program = _PATH_SSH_PROGRAM; |
|
FILE* infile; |
FILE* infile; |
|
size_t copy_buffer_len = 32768; |
|
size_t num_requests = 16; |
|
|
static 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); |
} |
} |
|
|
|
|
static void |
static void |
usage(void) |
usage(void) |
{ |
{ |
|
extern char *__progname; |
|
|
fprintf(stderr, |
fprintf(stderr, |
"usage: sftp [-1Cv] [-b batchfile] [-F config] [-o option] [-s subsystem|path]\n" |
"usage: %s [-vC1] [-b batchfile] [-o option] [-s subsystem|path] [-B buffer_size]\n" |
" [-S program] [user@]host[:file [file]]\n"); |
" [-F config] [-P direct server path] [-S program]\n" |
|
" [user@]host[:file [file]]\n", __progname); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
char *host, *userhost, *cp, *file2; |
char *host, *userhost, *cp, *file2; |
int debug_level = 0, sshver = 2; |
int debug_level = 0, sshver = 2; |
char *file1 = NULL, *sftp_server = NULL; |
char *file1 = NULL, *sftp_server = NULL; |
|
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; |
LogLevel ll = SYSLOG_LEVEL_INFO; |
LogLevel ll = SYSLOG_LEVEL_INFO; |
arglist args; |
arglist args; |
extern int optind; |
extern int optind; |
extern char *optarg; |
extern char *optarg; |
|
|
args.list = NULL; |
args.list = NULL; |
addargs(&args, "ssh"); /* overwritten with ssh_program */ |
addargs(&args, "ssh"); /* overwritten with ssh_program */ |
addargs(&args, "-oFallBackToRsh no"); |
addargs(&args, "-oFallBackToRsh no"); |
addargs(&args, "-oForwardX11 no"); |
addargs(&args, "-oForwardX11 no"); |
addargs(&args, "-oForwardAgent no"); |
addargs(&args, "-oForwardAgent no"); |
|
|
ll = SYSLOG_LEVEL_INFO; |
ll = SYSLOG_LEVEL_INFO; |
infile = stdin; /* Read from STDIN unless changed by -b */ |
infile = stdin; /* Read from STDIN unless changed by -b */ |
|
|
while ((ch = getopt(argc, argv, "1hvCo:s:S:b:F:")) != -1) { |
while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { |
switch (ch) { |
switch (ch) { |
case 'C': |
case 'C': |
addargs(&args, "-C"); |
addargs(&args, "-C"); |
|
|
} 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(); |
} |
} |
addargs(&args, "-l%s",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(); |
|
} |
|
|
|
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); |
/* no subsystem if the server-spec contains a '/' */ |
addargs(&args, "-oProtocol %d", sshver); |
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) |
|
addargs(&args, "-s"); |
|
|
/* no subsystem if the server-spec contains a '/' */ |
addargs(&args, "%s", host); |
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) |
addargs(&args, "%s", (sftp_server != NULL ? |
addargs(&args, "-s"); |
sftp_server : "sftp")); |
|
args.list[0] = ssh_program; |
|
|
addargs(&args, "%s", host); |
fprintf(stderr, "Connecting to %s...\n", host); |
addargs(&args, "%s", (sftp_server != NULL ? sftp_server : "sftp")); |
connect_to_server(ssh_program, args.list, &in, &out, |
args.list[0] = ssh_program; |
&sshpid); |
|
} else { |
|
args.list = NULL; |
|
addargs(&args, "sftp-server"); |
|
|
fprintf(stderr, "Connecting to %s...\n", host); |
fprintf(stderr, "Attaching to %s...\n", sftp_direct); |
|
connect_to_server(sftp_direct, args.list, &in, &out, |
connect_to_server(args.list, &in, &out, &sshpid); |
&sshpid); |
|
} |
|
|
interactive_loop(in, out, file1, file2); |
interactive_loop(in, out, file1, file2); |
|
|