version 1.102.2.2, 2004/03/04 18:18:16 |
version 1.103, 2003/06/03 02:56:16 |
|
|
arglist args; |
arglist args; |
|
|
/* Bandwidth limit */ |
/* Bandwidth limit */ |
off_t limit_rate = 0; |
off_t limit = 0; |
|
|
/* Name of current file being transferred. */ |
/* Name of current file being transferred. */ |
char *curfile; |
char *curfile; |
|
|
char *ssh_program = _PATH_SSH_PROGRAM; |
char *ssh_program = _PATH_SSH_PROGRAM; |
|
|
/* This is used to store the pid of ssh_program */ |
/* This is used to store the pid of ssh_program */ |
pid_t do_cmd_pid = -1; |
pid_t do_cmd_pid; |
|
|
static void |
|
killchild(int signo) |
|
{ |
|
if (do_cmd_pid > 1) |
|
kill(do_cmd_pid, signo); |
|
|
|
_exit(1); |
|
} |
|
|
|
/* |
/* |
* 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 |
|
|
close(reserved[0]); |
close(reserved[0]); |
close(reserved[1]); |
close(reserved[1]); |
|
|
/* Fork a child to execute the command on the remote host using ssh. */ |
/* For a child to execute the command on the remote host using ssh. */ |
do_cmd_pid = fork(); |
do_cmd_pid = fork(); |
if (do_cmd_pid == 0) { |
if (do_cmd_pid == 0) { |
/* Child. */ |
/* Child. */ |
|
|
*fdout = pin[1]; |
*fdout = pin[1]; |
close(pout[1]); |
close(pout[1]); |
*fdin = pout[0]; |
*fdin = pout[0]; |
signal(SIGTERM, killchild); |
|
signal(SIGINT, killchild); |
|
signal(SIGHUP, killchild); |
|
return 0; |
return 0; |
} |
} |
|
|
|
|
void usage(void); |
void usage(void); |
|
|
int |
int |
main(int argc, char **argv) |
main(argc, argv) |
|
int argc; |
|
char *argv[]; |
{ |
{ |
int ch, fflag, tflag, status; |
int ch, fflag, tflag, status; |
double speed; |
double speed; |
|
|
speed = strtod(optarg, &endp); |
speed = strtod(optarg, &endp); |
if (speed <= 0 || *endp != '\0') |
if (speed <= 0 || *endp != '\0') |
usage(); |
usage(); |
limit_rate = speed * 1024; |
limit = speed * 1024; |
break; |
break; |
case 'p': |
case 'p': |
pflag = 1; |
pflag = 1; |
|
|
verbose_mode = 1; |
verbose_mode = 1; |
break; |
break; |
case 'q': |
case 'q': |
addargs(&args, "-q"); |
|
showprogress = 0; |
showprogress = 0; |
break; |
break; |
|
|
|
|
argv += optind; |
argv += optind; |
|
|
if ((pwd = getpwuid(userid = getuid())) == NULL) |
if ((pwd = getpwuid(userid = getuid())) == NULL) |
fatal("unknown user %u", (u_int) userid); |
fatal("unknown user %d", (int) userid); |
|
|
if (!isatty(STDERR_FILENO)) |
if (!isatty(STDERR_FILENO)) |
showprogress = 0; |
showprogress = 0; |
|
|
} |
} |
|
|
void |
void |
toremote(char *targ, int argc, char **argv) |
toremote(targ, argc, argv) |
|
char *targ, *argv[]; |
|
int argc; |
{ |
{ |
int i, len; |
int i, len; |
char *bp, *host, *src, *suser, *thost, *tuser; |
char *bp, *host, *src, *suser, *thost, *tuser; |
|
|
} |
} |
if (verbose_mode) |
if (verbose_mode) |
fprintf(stderr, "Executing: %s\n", bp); |
fprintf(stderr, "Executing: %s\n", bp); |
if (system(bp) != 0) |
(void) system(bp); |
errs = 1; |
|
(void) xfree(bp); |
(void) xfree(bp); |
} else { /* local to remote */ |
} else { /* local to remote */ |
if (remin == -1) { |
if (remin == -1) { |
|
|
} |
} |
|
|
void |
void |
tolocal(int argc, char **argv) |
tolocal(argc, argv) |
|
int argc; |
|
char *argv[]; |
{ |
{ |
int i, len; |
int i, len; |
char *bp, *host, *src, *suser; |
char *bp, *host, *src, *suser; |
|
|
} |
} |
|
|
void |
void |
source(int argc, char **argv) |
source(argc, argv) |
|
int argc; |
|
char *argv[]; |
{ |
{ |
struct stat stb; |
struct stat stb; |
static BUF buffer; |
static BUF buffer; |
|
|
(void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n", |
(void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n", |
(u_long) stb.st_mtime, |
(u_long) stb.st_mtime, |
(u_long) stb.st_atime); |
(u_long) stb.st_atime); |
(void) atomicio(vwrite, remout, buf, strlen(buf)); |
(void) atomicio(write, remout, buf, strlen(buf)); |
if (response() < 0) |
if (response() < 0) |
goto next; |
goto next; |
} |
} |
|
|
if (verbose_mode) { |
if (verbose_mode) { |
fprintf(stderr, "Sending file modes: %s", buf); |
fprintf(stderr, "Sending file modes: %s", buf); |
} |
} |
(void) atomicio(vwrite, remout, buf, strlen(buf)); |
(void) atomicio(write, remout, buf, strlen(buf)); |
if (response() < 0) |
if (response() < 0) |
goto next; |
goto next; |
if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { |
if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { |
|
|
haderr = result >= 0 ? EIO : errno; |
haderr = result >= 0 ? EIO : errno; |
} |
} |
if (haderr) |
if (haderr) |
(void) atomicio(vwrite, remout, bp->buf, amt); |
(void) atomicio(write, remout, bp->buf, amt); |
else { |
else { |
result = atomicio(vwrite, remout, bp->buf, amt); |
result = atomicio(write, remout, bp->buf, amt); |
if (result != amt) |
if (result != amt) |
haderr = result >= 0 ? EIO : errno; |
haderr = result >= 0 ? EIO : errno; |
statbytes += result; |
statbytes += result; |
} |
} |
if (limit_rate) |
if (limit) |
bwlimit(amt); |
bwlimit(amt); |
} |
} |
if (showprogress) |
if (showprogress) |
|
|
if (close(fd) < 0 && !haderr) |
if (close(fd) < 0 && !haderr) |
haderr = errno; |
haderr = errno; |
if (!haderr) |
if (!haderr) |
(void) atomicio(vwrite, remout, "", 1); |
(void) atomicio(write, remout, "", 1); |
else |
else |
run_err("%s: %s", name, strerror(haderr)); |
run_err("%s: %s", name, strerror(haderr)); |
(void) response(); |
(void) response(); |
|
|
} |
} |
|
|
void |
void |
rsource(char *name, struct stat *statp) |
rsource(name, statp) |
|
char *name; |
|
struct stat *statp; |
{ |
{ |
DIR *dirp; |
DIR *dirp; |
struct dirent *dp; |
struct dirent *dp; |
|
|
(void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n", |
(void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n", |
(u_long) statp->st_mtime, |
(u_long) statp->st_mtime, |
(u_long) statp->st_atime); |
(u_long) statp->st_atime); |
(void) atomicio(vwrite, remout, path, strlen(path)); |
(void) atomicio(write, remout, path, strlen(path)); |
if (response() < 0) { |
if (response() < 0) { |
closedir(dirp); |
closedir(dirp); |
return; |
return; |
|
|
(u_int) (statp->st_mode & FILEMODEMASK), 0, last); |
(u_int) (statp->st_mode & FILEMODEMASK), 0, last); |
if (verbose_mode) |
if (verbose_mode) |
fprintf(stderr, "Entering directory: %s", path); |
fprintf(stderr, "Entering directory: %s", path); |
(void) atomicio(vwrite, remout, path, strlen(path)); |
(void) atomicio(write, remout, path, strlen(path)); |
if (response() < 0) { |
if (response() < 0) { |
closedir(dirp); |
closedir(dirp); |
return; |
return; |
|
|
source(1, vect); |
source(1, vect); |
} |
} |
(void) closedir(dirp); |
(void) closedir(dirp); |
(void) atomicio(vwrite, remout, "E\n", 2); |
(void) atomicio(write, remout, "E\n", 2); |
(void) response(); |
(void) response(); |
} |
} |
|
|
|
|
return; |
return; |
|
|
lamt *= 8; |
lamt *= 8; |
wait = (double)1000000L * lamt / limit_rate; |
wait = (double)1000000L * lamt / limit; |
|
|
bwstart.tv_sec = wait / 1000000L; |
bwstart.tv_sec = wait / 1000000L; |
bwstart.tv_usec = wait % 1000000L; |
bwstart.tv_usec = wait % 1000000L; |
|
|
} |
} |
|
|
void |
void |
sink(int argc, char **argv) |
sink(argc, argv) |
|
int argc; |
|
char *argv[]; |
{ |
{ |
static BUF buffer; |
static BUF buffer; |
struct stat stb; |
struct stat stb; |
|
|
if (targetshouldbedirectory) |
if (targetshouldbedirectory) |
verifydir(targ); |
verifydir(targ); |
|
|
(void) atomicio(vwrite, remout, "", 1); |
(void) atomicio(write, remout, "", 1); |
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) |
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) |
targisdir = 1; |
targisdir = 1; |
for (first = 1;; first = 0) { |
for (first = 1;; first = 0) { |
|
|
|
|
if (buf[0] == '\01' || buf[0] == '\02') { |
if (buf[0] == '\01' || buf[0] == '\02') { |
if (iamremote == 0) |
if (iamremote == 0) |
(void) atomicio(vwrite, STDERR_FILENO, |
(void) atomicio(write, STDERR_FILENO, |
buf + 1, strlen(buf + 1)); |
buf + 1, strlen(buf + 1)); |
if (buf[0] == '\02') |
if (buf[0] == '\02') |
exit(1); |
exit(1); |
|
|
continue; |
continue; |
} |
} |
if (buf[0] == 'E') { |
if (buf[0] == 'E') { |
(void) atomicio(vwrite, remout, "", 1); |
(void) atomicio(write, remout, "", 1); |
return; |
return; |
} |
} |
if (ch == '\n') |
if (ch == '\n') |
|
|
atime.tv_usec = strtol(cp, &cp, 10); |
atime.tv_usec = strtol(cp, &cp, 10); |
if (!cp || *cp++ != '\0') |
if (!cp || *cp++ != '\0') |
SCREWUP("atime.usec not delimited"); |
SCREWUP("atime.usec not delimited"); |
(void) atomicio(vwrite, remout, "", 1); |
(void) atomicio(write, remout, "", 1); |
continue; |
continue; |
} |
} |
if (*cp != 'C' && *cp != 'D') { |
if (*cp != 'C' && *cp != 'D') { |
|
|
bad: run_err("%s: %s", np, strerror(errno)); |
bad: run_err("%s: %s", np, strerror(errno)); |
continue; |
continue; |
} |
} |
(void) atomicio(vwrite, remout, "", 1); |
(void) atomicio(write, remout, "", 1); |
if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { |
if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { |
(void) close(ofd); |
(void) close(ofd); |
continue; |
continue; |
|
|
cp += j; |
cp += j; |
statbytes += j; |
statbytes += j; |
} while (amt > 0); |
} while (amt > 0); |
|
|
if (limit_rate) |
if (limit) |
bwlimit(4096); |
bwlimit(4096); |
|
|
if (count == bp->cnt) { |
if (count == bp->cnt) { |
/* Keep reading so we stay sync'd up. */ |
/* Keep reading so we stay sync'd up. */ |
if (wrerr == NO) { |
if (wrerr == NO) { |
j = atomicio(vwrite, ofd, bp->buf, count); |
j = atomicio(write, ofd, bp->buf, count); |
if (j != count) { |
if (j != count) { |
wrerr = YES; |
wrerr = YES; |
wrerrno = j >= 0 ? EIO : errno; |
wrerrno = j >= 0 ? EIO : errno; |
|
|
if (showprogress) |
if (showprogress) |
stop_progress_meter(); |
stop_progress_meter(); |
if (count != 0 && wrerr == NO && |
if (count != 0 && wrerr == NO && |
(j = atomicio(vwrite, ofd, bp->buf, count)) != count) { |
(j = atomicio(write, ofd, bp->buf, count)) != count) { |
wrerr = YES; |
wrerr = YES; |
wrerrno = j >= 0 ? EIO : errno; |
wrerrno = j >= 0 ? EIO : errno; |
} |
} |
|
|
run_err("%s: %s", np, strerror(wrerrno)); |
run_err("%s: %s", np, strerror(wrerrno)); |
break; |
break; |
case NO: |
case NO: |
(void) atomicio(vwrite, remout, "", 1); |
(void) atomicio(write, remout, "", 1); |
break; |
break; |
case DISPLAYED: |
case DISPLAYED: |
break; |
break; |
|
|
} while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); |
} while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); |
|
|
if (!iamremote) |
if (!iamremote) |
(void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf); |
(void) atomicio(write, STDERR_FILENO, rbuf, cp - rbuf); |
++errs; |
++errs; |
if (resp == 1) |
if (resp == 1) |
return (-1); |
return (-1); |
|
|
usage(void) |
usage(void) |
{ |
{ |
(void) fprintf(stderr, |
(void) fprintf(stderr, |
"usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" |
"usage: scp [-pqrvBC1246] [-F config] [-S program] [-P port]\n" |
" [-l limit] [-o ssh_option] [-P port] [-S program]\n" |
" [-c cipher] [-i identity] [-l limit] [-o option]\n" |
" [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); |
" [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); |
exit(1); |
exit(1); |
} |
} |
|
|
} |
} |
|
|
void |
void |
verifydir(char *cp) |
verifydir(cp) |
|
char *cp; |
{ |
{ |
struct stat stb; |
struct stat stb; |
|
|
|
|
} |
} |
|
|
int |
int |
okname(char *cp0) |
okname(cp0) |
|
char *cp0; |
{ |
{ |
int c; |
int c; |
char *cp; |
char *cp; |
|
|
} |
} |
|
|
BUF * |
BUF * |
allocbuf(BUF *bp, int fd, int blksize) |
allocbuf(bp, fd, blksize) |
|
BUF *bp; |
|
int fd, blksize; |
{ |
{ |
size_t size; |
size_t size; |
struct stat stb; |
struct stat stb; |
|
|
} |
} |
|
|
void |
void |
lostconn(int signo) |
lostconn(signo) |
|
int signo; |
{ |
{ |
if (!iamremote) |
if (!iamremote) |
write(STDERR_FILENO, "lost connection\n", 16); |
write(STDERR_FILENO, "lost connection\n", 16); |