version 1.68, 2001/04/22 12:34:05 |
version 1.68.2.2, 2001/11/15 00:15:19 |
|
|
#include "atomicio.h" |
#include "atomicio.h" |
#include "pathnames.h" |
#include "pathnames.h" |
#include "log.h" |
#include "log.h" |
#include "scp-common.h" |
#include "misc.h" |
|
|
/* For progressmeter() -- number of seconds before xfer considered "stalled" */ |
/* For progressmeter() -- number of seconds before xfer considered "stalled" */ |
#define STALLTIME 5 |
#define STALLTIME 5 |
|
/* alarm() interval for updating progress meter */ |
|
#define PROGRESSTIME 1 |
|
|
/* Visual statistics about files as they are transferred. */ |
/* Visual statistics about files as they are transferred. */ |
void progressmeter(int); |
void progressmeter(int); |
|
|
int getttywidth(void); |
int getttywidth(void); |
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); |
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); |
|
|
/* setup arguments for the call to ssh */ |
/* Struct for addargs */ |
void addargs(char *fmt, ...) __attribute__((format(printf, 1, 2))); |
arglist args; |
|
|
/* Time a transfer started. */ |
/* Time a transfer started. */ |
static struct timeval start; |
static struct timeval start; |
|
|
/* 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; |
|
|
/* This is the list of arguments that scp passes to ssh */ |
|
struct { |
|
char **list; |
|
int num; |
|
int nalloc; |
|
} args; |
|
|
|
/* |
/* |
* This function executes the given command as the specified user on the |
* This function executes the given command as the specified user on the |
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This |
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This |
|
|
int pin[2], pout[2], reserved[2]; |
int pin[2], pout[2], reserved[2]; |
|
|
if (verbose_mode) |
if (verbose_mode) |
fprintf(stderr, "Executing: program %s host %s, user %s, command %s\n", |
fprintf(stderr, |
ssh_program, host, remuser ? remuser : "(unspecified)", cmd); |
"Executing: program %s host %s, user %s, command %s\n", |
|
ssh_program, host, |
|
remuser ? remuser : "(unspecified)", cmd); |
|
|
/* |
/* |
* Reserve two descriptors so that the real pipes won't get |
* Reserve two descriptors so that the real pipes won't get |
|
|
|
|
args.list[0] = ssh_program; |
args.list[0] = ssh_program; |
if (remuser != NULL) |
if (remuser != NULL) |
addargs("-l%s", remuser); |
addargs(&args, "-l%s", remuser); |
addargs("%s", host); |
addargs(&args, "%s", host); |
addargs("%s", cmd); |
addargs(&args, "%s", cmd); |
|
|
execvp(ssh_program, args.list); |
execvp(ssh_program, args.list); |
perror(ssh_program); |
perror(ssh_program); |
|
|
extern int optind; |
extern int optind; |
|
|
args.list = NULL; |
args.list = NULL; |
addargs("ssh"); /* overwritten with ssh_program */ |
addargs(&args, "ssh"); /* overwritten with ssh_program */ |
addargs("-x"); |
addargs(&args, "-x"); |
addargs("-oFallBackToRsh no"); |
addargs(&args, "-oForwardAgent no"); |
|
addargs(&args, "-oFallBackToRsh no"); |
|
addargs(&args, "-oClearAllForwardings yes"); |
|
|
fflag = tflag = 0; |
fflag = tflag = 0; |
while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:")) != -1) |
while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) |
switch (ch) { |
switch (ch) { |
/* User-visible flags. */ |
/* User-visible flags. */ |
case '4': |
case '4': |
case '6': |
case '6': |
case 'C': |
case 'C': |
addargs("-%c", ch); |
addargs(&args, "-%c", ch); |
break; |
break; |
case 'o': |
case 'o': |
case 'c': |
case 'c': |
case 'i': |
case 'i': |
addargs("-%c%s", ch, optarg); |
case 'F': |
|
addargs(&args, "-%c%s", ch, optarg); |
break; |
break; |
case 'P': |
case 'P': |
addargs("-p%s", optarg); |
addargs(&args, "-p%s", optarg); |
break; |
break; |
case 'B': |
case 'B': |
addargs("-oBatchmode yes"); |
addargs(&args, "-oBatchmode yes"); |
break; |
break; |
case 'p': |
case 'p': |
pflag = 1; |
pflag = 1; |
|
|
ssh_program = xstrdup(optarg); |
ssh_program = xstrdup(optarg); |
break; |
break; |
case 'v': |
case 'v': |
|
addargs(&args, "-v"); |
verbose_mode = 1; |
verbose_mode = 1; |
break; |
break; |
case 'q': |
case 'q': |
|
|
for (i = 0; i < argc - 1; i++) { |
for (i = 0; i < argc - 1; i++) { |
src = colon(argv[i]); |
src = colon(argv[i]); |
if (src) { /* remote to remote */ |
if (src) { /* remote to remote */ |
|
static char *ssh_options = |
|
"-x -o'FallBackToRsh no' " |
|
"-o'ClearAllForwardings yes'"; |
*src++ = 0; |
*src++ = 0; |
if (*src == 0) |
if (*src == 0) |
src = "."; |
src = "."; |
host = strchr(argv[i], '@'); |
host = strchr(argv[i], '@'); |
len = strlen(ssh_program) + strlen(argv[i]) + |
len = strlen(ssh_program) + strlen(argv[i]) + |
strlen(src) + (tuser ? strlen(tuser) : 0) + |
strlen(src) + (tuser ? strlen(tuser) : 0) + |
strlen(thost) + strlen(targ) + CMDNEEDS + 32; |
strlen(thost) + strlen(targ) + |
|
strlen(ssh_options) + CMDNEEDS + 20; |
bp = xmalloc(len); |
bp = xmalloc(len); |
if (host) { |
if (host) { |
*host++ = 0; |
*host++ = 0; |
|
|
else if (!okname(suser)) |
else if (!okname(suser)) |
continue; |
continue; |
snprintf(bp, len, |
snprintf(bp, len, |
"%s%s -x -o'FallBackToRsh no' -n " |
"%s%s %s -n " |
"-l %s %s %s %s '%s%s%s:%s'", |
"-l %s %s %s %s '%s%s%s:%s'", |
ssh_program, verbose_mode ? " -v" : "", |
ssh_program, verbose_mode ? " -v" : "", |
suser, host, cmd, src, |
ssh_options, suser, host, cmd, src, |
tuser ? tuser : "", tuser ? "@" : "", |
tuser ? tuser : "", tuser ? "@" : "", |
thost, targ); |
thost, targ); |
} else { |
} else { |
host = cleanhostname(argv[i]); |
host = cleanhostname(argv[i]); |
snprintf(bp, len, |
snprintf(bp, len, |
"exec %s%s -x -o'FallBackToRsh no' -n %s " |
"exec %s%s %s -n %s " |
"%s %s '%s%s%s:%s'", |
"%s %s '%s%s%s:%s'", |
ssh_program, verbose_mode ? " -v" : "", |
ssh_program, verbose_mode ? " -v" : "", |
host, cmd, src, |
ssh_options, host, cmd, src, |
tuser ? tuser : "", tuser ? "@" : "", |
tuser ? tuser : "", tuser ? "@" : "", |
thost, targ); |
thost, targ); |
} |
} |
|
|
len = strlen(name); |
len = strlen(name); |
while (len > 1 && name[len-1] == '/') |
while (len > 1 && name[len-1] == '/') |
name[--len] = '\0'; |
name[--len] = '\0'; |
|
if (strchr(name, '\n') != NULL) { |
|
run_err("%s: skipping, filename contains a newline", |
|
name); |
|
goto next; |
|
} |
if ((fd = open(name, O_RDONLY, 0)) < 0) |
if ((fd = open(name, O_RDONLY, 0)) < 0) |
goto syserr; |
goto syserr; |
if (fstat(fd, &stb) < 0) { |
if (fstat(fd, &stb) < 0) { |
|
|
|
|
#define atime tv[0] |
#define atime tv[0] |
#define mtime tv[1] |
#define mtime tv[1] |
#define SCREWUP(str) { why = str; goto screwup; } |
#define SCREWUP(str) do { why = str; goto screwup; } while (0) |
|
|
setimes = targisdir = 0; |
setimes = targisdir = 0; |
mask = umask(0); |
mask = umask(0); |
|
|
} |
} |
omode = mode; |
omode = mode; |
mode |= S_IWRITE; |
mode |= S_IWRITE; |
if ((ofd = open(np, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0) { |
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { |
bad: run_err("%s: %s", np, strerror(errno)); |
bad: run_err("%s: %s", np, strerror(errno)); |
continue; |
continue; |
} |
} |
|
|
count += amt; |
count += amt; |
do { |
do { |
j = read(remin, cp, amt); |
j = read(remin, cp, amt); |
if (j == -1 && (errno == EINTR || errno == EAGAIN)) { |
if (j == -1 && (errno == EINTR || |
|
errno == EAGAIN)) { |
continue; |
continue; |
} else if (j <= 0) { |
} else if (j <= 0) { |
run_err("%s", j ? strerror(errno) : |
run_err("%s", j ? strerror(errno) : |
|
|
wrerr = YES; |
wrerr = YES; |
wrerrno = j >= 0 ? EIO : errno; |
wrerrno = j >= 0 ? EIO : errno; |
} |
} |
#if 0 |
|
if (ftruncate(ofd, size)) { |
if (ftruncate(ofd, size)) { |
run_err("%s: truncate: %s", np, strerror(errno)); |
run_err("%s: truncate: %s", np, strerror(errno)); |
wrerr = DISPLAYED; |
wrerr = DISPLAYED; |
} |
} |
#endif |
|
if (pflag) { |
if (pflag) { |
if (exists || omode != mode) |
if (exists || omode != mode) |
if (fchmod(ofd, omode)) |
if (fchmod(ofd, omode)) |
|
|
void |
void |
usage() |
usage() |
{ |
{ |
(void) fprintf(stderr, "usage: scp " |
(void) fprintf(stderr, |
"[-pqrvBC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2\n" |
"usage: scp [-pqrvBC46] [-F config] [-S ssh] [-P port] [-c cipher] [-i identity]\n" |
|
" [-o option] f1 f2\n" |
" or: scp [options] f1 ... fn directory\n"); |
" or: scp [options] f1 ... fn directory\n"); |
exit(1); |
exit(1); |
} |
} |
|
|
{ |
{ |
static FILE *fp; |
static FILE *fp; |
va_list ap; |
va_list ap; |
va_start(ap, fmt); |
|
|
|
++errs; |
++errs; |
if (fp == NULL && !(fp = fdopen(remout, "w"))) |
if (fp == NULL && !(fp = fdopen(remout, "w"))) |
return; |
return; |
(void) fprintf(fp, "%c", 0x01); |
(void) fprintf(fp, "%c", 0x01); |
(void) fprintf(fp, "scp: "); |
(void) fprintf(fp, "scp: "); |
|
va_start(ap, fmt); |
(void) vfprintf(fp, fmt, ap); |
(void) vfprintf(fp, fmt, ap); |
|
va_end(ap); |
(void) fprintf(fp, "\n"); |
(void) fprintf(fp, "\n"); |
(void) fflush(fp); |
(void) fflush(fp); |
|
|
if (!iamremote) { |
if (!iamremote) { |
|
va_start(ap, fmt); |
vfprintf(stderr, fmt, ap); |
vfprintf(stderr, fmt, ap); |
|
va_end(ap); |
fprintf(stderr, "\n"); |
fprintf(stderr, "\n"); |
} |
} |
va_end(ap); |
|
} |
} |
|
|
void |
void |
|
|
|
|
cp = cp0; |
cp = cp0; |
do { |
do { |
c = *cp; |
c = (int)*cp; |
if (c & 0200) |
if (c & 0200) |
goto bad; |
goto bad; |
if (!isalpha(c) && !isdigit(c) && |
if (!isalpha(c) && !isdigit(c) && |
|
|
bp->buf = xmalloc(size); |
bp->buf = xmalloc(size); |
else |
else |
bp->buf = xrealloc(bp->buf, size); |
bp->buf = xrealloc(bp->buf, size); |
|
memset(bp->buf, 0, size); |
bp->cnt = size; |
bp->cnt = size; |
return (bp); |
return (bp); |
} |
} |
|
|
int signo; |
int signo; |
{ |
{ |
if (!iamremote) |
if (!iamremote) |
fprintf(stderr, "lost connection\n"); |
write(STDERR_FILENO, "lost connection\n", 16); |
exit(1); |
if (signo) |
|
_exit(1); |
|
else |
|
exit(1); |
} |
} |
|
|
|
static void |
void |
|
alarmtimer(int wait) |
|
{ |
|
struct itimerval itv; |
|
|
|
itv.it_value.tv_sec = wait; |
|
itv.it_value.tv_usec = 0; |
|
itv.it_interval = itv.it_value; |
|
setitimer(ITIMER_REAL, &itv, NULL); |
|
} |
|
|
|
void |
|
updateprogressmeter(int ignore) |
updateprogressmeter(int ignore) |
{ |
{ |
int save_errno = errno; |
int save_errno = errno; |
|
|
progressmeter(0); |
progressmeter(0); |
|
signal(SIGALRM, updateprogressmeter); |
|
alarm(PROGRESSTIME); |
errno = save_errno; |
errno = save_errno; |
} |
} |
|
|
int |
static int |
foregroundproc(void) |
foregroundproc(void) |
{ |
{ |
static pid_t pgrp = -1; |
static pid_t pgrp = -1; |
|
|
i = barlength * ratio / 100; |
i = barlength * ratio / 100; |
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
"|%.*s%*s|", i, |
"|%.*s%*s|", i, |
"*****************************************************************************" |
"***************************************" |
"*****************************************************************************", |
"***************************************" |
|
"***************************************" |
|
"***************************************", |
barlength - i, ""); |
barlength - i, ""); |
} |
} |
i = 0; |
i = 0; |
|
|
|
|
if (flag == -1) { |
if (flag == -1) { |
signal(SIGALRM, updateprogressmeter); |
signal(SIGALRM, updateprogressmeter); |
alarmtimer(1); |
alarm(PROGRESSTIME); |
} else if (flag == 1) { |
} else if (flag == 1) { |
alarmtimer(0); |
alarm(0); |
atomicio(write, fileno(stdout), "\n", 1); |
atomicio(write, fileno(stdout), "\n", 1); |
statbytes = 0; |
statbytes = 0; |
} |
} |
|
|
return (winsize.ws_col ? winsize.ws_col : 80); |
return (winsize.ws_col ? winsize.ws_col : 80); |
else |
else |
return (80); |
return (80); |
} |
|
|
|
void |
|
addargs(char *fmt, ...) |
|
{ |
|
va_list ap; |
|
char buf[1024]; |
|
|
|
va_start(ap, fmt); |
|
vsnprintf(buf, sizeof(buf), fmt, ap); |
|
va_end(ap); |
|
|
|
if (args.list == NULL) { |
|
args.nalloc = 32; |
|
args.num = 0; |
|
args.list = xmalloc(args.nalloc * sizeof(char *)); |
|
} else if (args.num+2 >= args.nalloc) { |
|
args.nalloc *= 2; |
|
args.list = xrealloc(args.list, args.nalloc * sizeof(char *)); |
|
} |
|
args.list[args.num++] = xstrdup(buf); |
|
args.list[args.num] = NULL; |
|
} |
} |