version 1.192, 2017/05/31 09:15:42 |
version 1.193, 2017/10/21 23:06:24 |
|
|
#include <vis.h> |
#include <vis.h> |
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
|
#include "ssh.h" |
#include "atomicio.h" |
#include "atomicio.h" |
#include "pathnames.h" |
#include "pathnames.h" |
#include "log.h" |
#include "log.h" |
|
|
|
|
#define COPY_BUFLEN 16384 |
#define COPY_BUFLEN 16384 |
|
|
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); |
int do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout); |
int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout); |
int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout); |
|
|
/* Struct for addargs */ |
/* Struct for addargs */ |
arglist args; |
arglist args; |
|
|
*/ |
*/ |
int throughlocal = 0; |
int throughlocal = 0; |
|
|
|
/* Non-standard port to use for the ssh connection or -1. */ |
|
int sshport = -1; |
|
|
/* This is the program to execute for the secured connection. ("ssh" or -S) */ |
/* This is the program to execute for the secured connection. ("ssh" or -S) */ |
char *ssh_program = _PATH_SSH_PROGRAM; |
char *ssh_program = _PATH_SSH_PROGRAM; |
|
|
|
|
*/ |
*/ |
|
|
int |
int |
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) |
do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout) |
{ |
{ |
int pin[2], pout[2], reserved[2]; |
int pin[2], pout[2], reserved[2]; |
|
|
|
|
ssh_program, host, |
ssh_program, host, |
remuser ? remuser : "(unspecified)", cmd); |
remuser ? remuser : "(unspecified)", cmd); |
|
|
|
if (port == -1) |
|
port = sshport; |
|
|
/* |
/* |
* Reserve two descriptors so that the real pipes won't get |
* Reserve two descriptors so that the real pipes won't get |
* descriptors 0 and 1 because that will screw up dup2 below. |
* descriptors 0 and 1 because that will screw up dup2 below. |
|
|
close(pout[1]); |
close(pout[1]); |
|
|
replacearg(&args, 0, "%s", ssh_program); |
replacearg(&args, 0, "%s", ssh_program); |
|
if (port != -1) { |
|
addargs(&args, "-p"); |
|
addargs(&args, "%d", port); |
|
} |
if (remuser != NULL) { |
if (remuser != NULL) { |
addargs(&args, "-l"); |
addargs(&args, "-l"); |
addargs(&args, "%s", remuser); |
addargs(&args, "%s", remuser); |
|
|
* This way the input and output of two commands can be connected. |
* This way the input and output of two commands can be connected. |
*/ |
*/ |
int |
int |
do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout) |
do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout) |
{ |
{ |
pid_t pid; |
pid_t pid; |
int status; |
int status; |
|
|
ssh_program, host, |
ssh_program, host, |
remuser ? remuser : "(unspecified)", cmd); |
remuser ? remuser : "(unspecified)", cmd); |
|
|
|
if (port == -1) |
|
port = sshport; |
|
|
/* Fork a child to execute the command on the remote host using ssh. */ |
/* Fork a child to execute the command on the remote host using ssh. */ |
pid = fork(); |
pid = fork(); |
if (pid == 0) { |
if (pid == 0) { |
|
|
dup2(fdout, 1); |
dup2(fdout, 1); |
|
|
replacearg(&args, 0, "%s", ssh_program); |
replacearg(&args, 0, "%s", ssh_program); |
|
if (port != -1) { |
|
addargs(&args, "-p"); |
|
addargs(&args, "%d", port); |
|
} |
if (remuser != NULL) { |
if (remuser != NULL) { |
addargs(&args, "-l"); |
addargs(&args, "-l"); |
addargs(&args, "%s", remuser); |
addargs(&args, "%s", remuser); |
|
|
void sink(int, char *[]); |
void sink(int, char *[]); |
void source(int, char *[]); |
void source(int, char *[]); |
void tolocal(int, char *[]); |
void tolocal(int, char *[]); |
void toremote(char *, int, char *[]); |
void toremote(int, char *[]); |
void usage(void); |
void usage(void); |
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
int ch, fflag, tflag, status, n; |
int ch, fflag, tflag, status, n; |
char *targ, **newargv; |
char **newargv; |
const char *errstr; |
const char *errstr; |
extern char *optarg; |
extern char *optarg; |
extern int optind; |
extern int optind; |
|
|
addargs(&args, "%s", optarg); |
addargs(&args, "%s", optarg); |
break; |
break; |
case 'P': |
case 'P': |
addargs(&remote_remote_args, "-p"); |
sshport = a2port(optarg); |
addargs(&remote_remote_args, "%s", optarg); |
if (sshport <= 0) |
addargs(&args, "-p"); |
fatal("bad port \"%s\"\n", optarg); |
addargs(&args, "%s", optarg); |
|
break; |
break; |
case 'B': |
case 'B': |
addargs(&remote_remote_args, "-oBatchmode=yes"); |
addargs(&remote_remote_args, "-oBatchmode=yes"); |
|
|
|
|
(void) signal(SIGPIPE, lostconn); |
(void) signal(SIGPIPE, lostconn); |
|
|
if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ |
if (colon(argv[argc - 1])) /* Dest is remote host. */ |
toremote(targ, argc, argv); |
toremote(argc, argv); |
else { |
else { |
if (targetshouldbedirectory) |
if (targetshouldbedirectory) |
verifydir(argv[argc - 1]); |
verifydir(argv[argc - 1]); |
|
|
} |
} |
|
|
void |
void |
toremote(char *targ, int argc, char **argv) |
toremote(int argc, char **argv) |
{ |
{ |
char *bp, *host, *src, *suser, *thost, *tuser, *arg; |
char *suser = NULL, *host = NULL, *src = NULL; |
|
char *bp, *tuser, *thost, *targ; |
|
int sport = -1, tport = -1; |
arglist alist; |
arglist alist; |
int i; |
int i, r; |
u_int j; |
u_int j; |
|
|
memset(&alist, '\0', sizeof(alist)); |
memset(&alist, '\0', sizeof(alist)); |
alist.list = NULL; |
alist.list = NULL; |
|
|
*targ++ = 0; |
/* Parse target */ |
if (*targ == 0) |
r = parse_uri("scp", argv[argc - 1], &tuser, &thost, &tport, &targ); |
targ = "."; |
if (r == -1) |
|
goto out; /* invalid URI */ |
arg = xstrdup(argv[argc - 1]); |
if (r != 0) { |
if ((thost = strrchr(arg, '@'))) { |
if (parse_user_host_path(argv[argc - 1], &tuser, &thost, |
/* user@host */ |
&targ) == -1) |
*thost++ = 0; |
goto out; |
tuser = arg; |
|
if (*tuser == '\0') |
|
tuser = NULL; |
|
} else { |
|
thost = arg; |
|
tuser = NULL; |
|
} |
} |
|
if (tuser != NULL && !okname(tuser)) |
|
goto out; |
|
|
if (tuser != NULL && !okname(tuser)) { |
/* Parse source files */ |
free(arg); |
|
return; |
|
} |
|
|
|
for (i = 0; i < argc - 1; i++) { |
for (i = 0; i < argc - 1; i++) { |
src = colon(argv[i]); |
free(suser); |
if (src && throughlocal) { /* extended remote to remote */ |
free(host); |
*src++ = 0; |
free(src); |
if (*src == 0) |
r = parse_uri("scp", argv[i], &suser, &host, &sport, &src); |
src = "."; |
if (r == -1) |
host = strrchr(argv[i], '@'); |
continue; /* invalid URI */ |
if (host) { |
if (r != 0) |
*host++ = 0; |
parse_user_host_path(argv[i], &suser, &host, &src); |
host = cleanhostname(host); |
if (suser != NULL && !okname(suser)) { |
suser = argv[i]; |
++errs; |
if (*suser == '\0') |
continue; |
suser = pwd->pw_name; |
} |
else if (!okname(suser)) |
if (host && throughlocal) { /* extended remote to remote */ |
continue; |
|
} else { |
|
host = cleanhostname(argv[i]); |
|
suser = NULL; |
|
} |
|
xasprintf(&bp, "%s -f %s%s", cmd, |
xasprintf(&bp, "%s -f %s%s", cmd, |
*src == '-' ? "-- " : "", src); |
*src == '-' ? "-- " : "", src); |
if (do_cmd(host, suser, bp, &remin, &remout) < 0) |
if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) |
exit(1); |
exit(1); |
free(bp); |
free(bp); |
host = cleanhostname(thost); |
|
xasprintf(&bp, "%s -t %s%s", cmd, |
xasprintf(&bp, "%s -t %s%s", cmd, |
*targ == '-' ? "-- " : "", targ); |
*targ == '-' ? "-- " : "", targ); |
if (do_cmd2(host, tuser, bp, remin, remout) < 0) |
if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0) |
exit(1); |
exit(1); |
free(bp); |
free(bp); |
(void) close(remin); |
(void) close(remin); |
(void) close(remout); |
(void) close(remout); |
remin = remout = -1; |
remin = remout = -1; |
} else if (src) { /* standard remote to remote */ |
} else if (host) { /* standard remote to remote */ |
|
if (tport != -1 && tport != SSH_DEFAULT_PORT) { |
|
/* This would require the remote support URIs */ |
|
fatal("target port not supported with two " |
|
"remote hosts without the -3 option"); |
|
} |
|
|
freeargs(&alist); |
freeargs(&alist); |
addargs(&alist, "%s", ssh_program); |
addargs(&alist, "%s", ssh_program); |
addargs(&alist, "-x"); |
addargs(&alist, "-x"); |
|
|
addargs(&alist, "%s", |
addargs(&alist, "%s", |
remote_remote_args.list[j]); |
remote_remote_args.list[j]); |
} |
} |
*src++ = 0; |
|
if (*src == 0) |
|
src = "."; |
|
host = strrchr(argv[i], '@'); |
|
|
|
if (host) { |
if (sport != -1) { |
*host++ = 0; |
addargs(&alist, "-p"); |
host = cleanhostname(host); |
addargs(&alist, "%d", sport); |
suser = argv[i]; |
} |
if (*suser == '\0') |
if (suser) { |
suser = pwd->pw_name; |
|
else if (!okname(suser)) |
|
continue; |
|
addargs(&alist, "-l"); |
addargs(&alist, "-l"); |
addargs(&alist, "%s", suser); |
addargs(&alist, "%s", suser); |
} else { |
|
host = cleanhostname(argv[i]); |
|
} |
} |
addargs(&alist, "--"); |
addargs(&alist, "--"); |
addargs(&alist, "%s", host); |
addargs(&alist, "%s", host); |
|
|
if (remin == -1) { |
if (remin == -1) { |
xasprintf(&bp, "%s -t %s%s", cmd, |
xasprintf(&bp, "%s -t %s%s", cmd, |
*targ == '-' ? "-- " : "", targ); |
*targ == '-' ? "-- " : "", targ); |
host = cleanhostname(thost); |
if (do_cmd(thost, tuser, tport, bp, &remin, |
if (do_cmd(host, tuser, bp, &remin, |
|
&remout) < 0) |
&remout) < 0) |
exit(1); |
exit(1); |
if (response() < 0) |
if (response() < 0) |
|
|
source(1, argv + i); |
source(1, argv + i); |
} |
} |
} |
} |
free(arg); |
out: |
|
free(tuser); |
|
free(thost); |
|
free(targ); |
|
free(suser); |
|
free(host); |
|
free(src); |
} |
} |
|
|
void |
void |
tolocal(int argc, char **argv) |
tolocal(int argc, char **argv) |
{ |
{ |
char *bp, *host, *src, *suser; |
char *bp, *host = NULL, *src = NULL, *suser = NULL; |
arglist alist; |
arglist alist; |
int i; |
int i, r, sport = -1; |
|
|
memset(&alist, '\0', sizeof(alist)); |
memset(&alist, '\0', sizeof(alist)); |
alist.list = NULL; |
alist.list = NULL; |
|
|
for (i = 0; i < argc - 1; i++) { |
for (i = 0; i < argc - 1; i++) { |
if (!(src = colon(argv[i]))) { /* Local to local. */ |
free(suser); |
|
free(host); |
|
free(src); |
|
r = parse_uri("scp", argv[i], &suser, &host, &sport, &src); |
|
if (r == -1) { |
|
++errs; |
|
continue; |
|
} |
|
if (r != 0) |
|
parse_user_host_path(argv[i], &suser, &host, &src); |
|
if (suser != NULL && !okname(suser)) { |
|
++errs; |
|
continue; |
|
} |
|
if (!host) { /* Local to local. */ |
freeargs(&alist); |
freeargs(&alist); |
addargs(&alist, "%s", _PATH_CP); |
addargs(&alist, "%s", _PATH_CP); |
if (iamrecursive) |
if (iamrecursive) |
|
|
++errs; |
++errs; |
continue; |
continue; |
} |
} |
*src++ = 0; |
/* Remote to local. */ |
if (*src == 0) |
|
src = "."; |
|
if ((host = strrchr(argv[i], '@')) == NULL) { |
|
host = argv[i]; |
|
suser = NULL; |
|
} else { |
|
*host++ = 0; |
|
suser = argv[i]; |
|
if (*suser == '\0') |
|
suser = pwd->pw_name; |
|
} |
|
host = cleanhostname(host); |
|
xasprintf(&bp, "%s -f %s%s", |
xasprintf(&bp, "%s -f %s%s", |
cmd, *src == '-' ? "-- " : "", src); |
cmd, *src == '-' ? "-- " : "", src); |
if (do_cmd(host, suser, bp, &remin, &remout) < 0) { |
if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) { |
free(bp); |
free(bp); |
++errs; |
++errs; |
continue; |
continue; |
|
|
(void) close(remin); |
(void) close(remin); |
remin = remout = -1; |
remin = remout = -1; |
} |
} |
|
free(suser); |
|
free(host); |
|
free(src); |
} |
} |
|
|
void |
void |
|
|
{ |
{ |
(void) fprintf(stderr, |
(void) fprintf(stderr, |
"usage: scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" |
"usage: scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" |
" [-l limit] [-o ssh_option] [-P port] [-S program]\n" |
" [-l limit] [-o ssh_option] [-P port] [-S program] source ... target\n"); |
" [[user@]host1:]file1 ... [[user@]host2:]file2\n"); |
|
exit(1); |
exit(1); |
} |
} |
|
|