version 1.119.2.2, 2006/02/03 02:53:44 |
version 1.120, 2005/03/31 18:39:21 |
|
|
killchild(int signo) |
killchild(int signo) |
{ |
{ |
if (do_cmd_pid > 1) { |
if (do_cmd_pid > 1) { |
kill(do_cmd_pid, signo ? signo : SIGTERM); |
kill(do_cmd_pid, signo); |
waitpid(do_cmd_pid, NULL, 0); |
waitpid(do_cmd_pid, NULL, 0); |
} |
} |
|
|
if (signo) |
_exit(1); |
_exit(1); |
|
exit(1); |
|
} |
} |
|
|
static int |
|
do_local_cmd(arglist *a) |
|
{ |
|
u_int i; |
|
int status; |
|
pid_t pid; |
|
|
|
if (a->num == 0) |
|
fatal("do_local_cmd: no arguments"); |
|
|
|
if (verbose_mode) { |
|
fprintf(stderr, "Executing:"); |
|
for (i = 0; i < a->num; i++) |
|
fprintf(stderr, " %s", a->list[i]); |
|
fprintf(stderr, "\n"); |
|
} |
|
if ((pid = fork()) == -1) |
|
fatal("do_local_cmd: fork: %s", strerror(errno)); |
|
|
|
if (pid == 0) { |
|
execvp(a->list[0], a->list); |
|
perror(a->list[0]); |
|
exit(1); |
|
} |
|
|
|
do_cmd_pid = pid; |
|
signal(SIGTERM, killchild); |
|
signal(SIGINT, killchild); |
|
signal(SIGHUP, killchild); |
|
|
|
while (waitpid(pid, &status, 0) == -1) |
|
if (errno != EINTR) |
|
fatal("do_local_cmd: waitpid: %s", strerror(errno)); |
|
|
|
do_cmd_pid = -1; |
|
|
|
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) |
|
return (-1); |
|
|
|
return (0); |
|
} |
|
|
|
/* |
/* |
* 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(pin[0]); |
close(pin[0]); |
close(pout[1]); |
close(pout[1]); |
|
|
replacearg(&args, 0, "%s", ssh_program); |
args.list[0] = ssh_program; |
if (remuser != NULL) |
if (remuser != NULL) |
addargs(&args, "-l%s", remuser); |
addargs(&args, "-l%s", remuser); |
addargs(&args, "%s", host); |
addargs(&args, "%s", host); |
|
|
} |
} |
|
|
typedef struct { |
typedef struct { |
size_t cnt; |
int cnt; |
char *buf; |
char *buf; |
} BUF; |
} BUF; |
|
|
|
|
extern char *optarg; |
extern char *optarg; |
extern int optind; |
extern int optind; |
|
|
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
|
sanitise_stdfd(); |
|
|
|
memset(&args, '\0', sizeof(args)); |
|
args.list = NULL; |
args.list = NULL; |
addargs(&args, "%s", ssh_program); |
addargs(&args, "ssh"); /* overwritten with ssh_program */ |
addargs(&args, "-x"); |
addargs(&args, "-x"); |
addargs(&args, "-oForwardAgent no"); |
addargs(&args, "-oForwardAgent no"); |
addargs(&args, "-oPermitLocalCommand no"); |
|
addargs(&args, "-oClearAllForwardings yes"); |
addargs(&args, "-oClearAllForwardings yes"); |
|
|
fflag = tflag = 0; |
fflag = tflag = 0; |
|
|
if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ |
if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ |
toremote(targ, argc, argv); |
toremote(targ, argc, argv); |
else { |
else { |
|
tolocal(argc, argv); /* Dest is local host. */ |
if (targetshouldbedirectory) |
if (targetshouldbedirectory) |
verifydir(argv[argc - 1]); |
verifydir(argv[argc - 1]); |
tolocal(argc, argv); /* Dest is local host. */ |
|
} |
} |
/* |
/* |
* Finally check the exit status of the ssh process, if one was forked |
* Finally check the exit status of the ssh process, if one was forked |
|
|
{ |
{ |
int i, len; |
int i, len; |
char *bp, *host, *src, *suser, *thost, *tuser, *arg; |
char *bp, *host, *src, *suser, *thost, *tuser, *arg; |
arglist alist; |
|
|
|
memset(&alist, '\0', sizeof(alist)); |
|
alist.list = NULL; |
|
|
|
*targ++ = 0; |
*targ++ = 0; |
if (*targ == 0) |
if (*targ == 0) |
targ = "."; |
targ = "."; |
|
|
arg = xstrdup(argv[argc - 1]); |
arg = strdup(argv[argc - 1]); |
|
if (!arg) |
|
err(1, "malloc"); |
if ((thost = strrchr(arg, '@'))) { |
if ((thost = strrchr(arg, '@'))) { |
/* user@host */ |
/* user@host */ |
*thost++ = 0; |
*thost++ = 0; |
|
|
tuser = NULL; |
tuser = NULL; |
} |
} |
|
|
if (tuser != NULL && !okname(tuser)) { |
|
xfree(arg); |
|
return; |
|
} |
|
|
|
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 */ |
freeargs(&alist); |
static char *ssh_options = |
addargs(&alist, "%s", ssh_program); |
"-x -o'ClearAllForwardings yes'"; |
if (verbose_mode) |
|
addargs(&alist, "-v"); |
|
addargs(&alist, "-x"); |
|
addargs(&alist, "-oClearAllForwardings yes"); |
|
addargs(&alist, "-n"); |
|
|
|
*src++ = 0; |
*src++ = 0; |
if (*src == 0) |
if (*src == 0) |
src = "."; |
src = "."; |
host = strrchr(argv[i], '@'); |
host = strrchr(argv[i], '@'); |
|
len = strlen(ssh_program) + strlen(argv[i]) + |
|
strlen(src) + (tuser ? strlen(tuser) : 0) + |
|
strlen(thost) + strlen(targ) + |
|
strlen(ssh_options) + CMDNEEDS + 20; |
|
bp = xmalloc(len); |
if (host) { |
if (host) { |
*host++ = 0; |
*host++ = 0; |
host = cleanhostname(host); |
host = cleanhostname(host); |
suser = argv[i]; |
suser = argv[i]; |
if (*suser == '\0') |
if (*suser == '\0') |
suser = pwd->pw_name; |
suser = pwd->pw_name; |
else if (!okname(suser)) |
else if (!okname(suser)) { |
|
xfree(bp); |
continue; |
continue; |
addargs(&alist, "-l"); |
} |
addargs(&alist, "%s", suser); |
if (tuser && !okname(tuser)) { |
|
xfree(bp); |
|
continue; |
|
} |
|
snprintf(bp, len, |
|
"%s%s %s -n " |
|
"-l %s %s %s %s '%s%s%s:%s'", |
|
ssh_program, verbose_mode ? " -v" : "", |
|
ssh_options, suser, host, cmd, src, |
|
tuser ? tuser : "", tuser ? "@" : "", |
|
thost, targ); |
} else { |
} else { |
host = cleanhostname(argv[i]); |
host = cleanhostname(argv[i]); |
|
snprintf(bp, len, |
|
"exec %s%s %s -n %s " |
|
"%s %s '%s%s%s:%s'", |
|
ssh_program, verbose_mode ? " -v" : "", |
|
ssh_options, host, cmd, src, |
|
tuser ? tuser : "", tuser ? "@" : "", |
|
thost, targ); |
} |
} |
addargs(&alist, "%s", host); |
if (verbose_mode) |
addargs(&alist, "%s", cmd); |
fprintf(stderr, "Executing: %s\n", bp); |
addargs(&alist, "%s", src); |
if (system(bp) != 0) |
addargs(&alist, "%s%s%s:%s", |
|
tuser ? tuser : "", tuser ? "@" : "", |
|
thost, targ); |
|
if (do_local_cmd(&alist) != 0) |
|
errs = 1; |
errs = 1; |
|
(void) xfree(bp); |
} else { /* local to remote */ |
} else { /* local to remote */ |
if (remin == -1) { |
if (remin == -1) { |
len = strlen(targ) + CMDNEEDS + 20; |
len = strlen(targ) + CMDNEEDS + 20; |
|
|
{ |
{ |
int i, len; |
int i, len; |
char *bp, *host, *src, *suser; |
char *bp, *host, *src, *suser; |
arglist alist; |
|
|
|
memset(&alist, '\0', sizeof(alist)); |
|
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. */ |
if (!(src = colon(argv[i]))) { /* Local to local. */ |
freeargs(&alist); |
len = strlen(_PATH_CP) + strlen(argv[i]) + |
addargs(&alist, "%s", _PATH_CP); |
strlen(argv[argc - 1]) + 20; |
if (iamrecursive) |
bp = xmalloc(len); |
addargs(&alist, "-r"); |
(void) snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, |
if (pflag) |
iamrecursive ? " -r" : "", pflag ? " -p" : "", |
addargs(&alist, "-p"); |
argv[i], argv[argc - 1]); |
addargs(&alist, "%s", argv[i]); |
if (verbose_mode) |
addargs(&alist, "%s", argv[argc-1]); |
fprintf(stderr, "Executing: %s\n", bp); |
if (do_local_cmd(&alist)) |
if (system(bp)) |
++errs; |
++errs; |
|
(void) xfree(bp); |
continue; |
continue; |
} |
} |
*src++ = 0; |
*src++ = 0; |
|
|
struct stat stb; |
struct stat stb; |
static BUF buffer; |
static BUF buffer; |
BUF *bp; |
BUF *bp; |
off_t i, amt, statbytes; |
off_t i, amt, result, statbytes; |
size_t result; |
int fd, haderr, indx; |
int fd = -1, haderr, indx; |
|
char *last, *name, buf[2048]; |
char *last, *name, buf[2048]; |
int len; |
int len; |
|
|
|
|
if (response() < 0) |
if (response() < 0) |
goto next; |
goto next; |
if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { |
if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { |
next: if (fd != -1) { |
next: (void) close(fd); |
(void) close(fd); |
|
fd = -1; |
|
} |
|
continue; |
continue; |
} |
} |
if (showprogress) |
if (showprogress) |
|
|
if (!haderr) { |
if (!haderr) { |
result = atomicio(read, fd, bp->buf, amt); |
result = atomicio(read, fd, bp->buf, amt); |
if (result != amt) |
if (result != amt) |
haderr = errno; |
haderr = result >= 0 ? EIO : errno; |
} |
} |
if (haderr) |
if (haderr) |
(void) atomicio(vwrite, remout, bp->buf, amt); |
(void) atomicio(vwrite, remout, bp->buf, amt); |
else { |
else { |
result = atomicio(vwrite, remout, bp->buf, amt); |
result = atomicio(vwrite, remout, bp->buf, amt); |
if (result != amt) |
if (result != amt) |
haderr = errno; |
haderr = result >= 0 ? EIO : errno; |
statbytes += result; |
statbytes += result; |
} |
} |
if (limit_rate) |
if (limit_rate) |
|
|
if (showprogress) |
if (showprogress) |
stop_progress_meter(); |
stop_progress_meter(); |
|
|
if (fd != -1) { |
if (close(fd) < 0 && !haderr) |
if (close(fd) < 0 && !haderr) |
haderr = errno; |
haderr = errno; |
|
fd = -1; |
|
} |
|
if (!haderr) |
if (!haderr) |
(void) atomicio(vwrite, remout, "", 1); |
(void) atomicio(vwrite, remout, "", 1); |
else |
else |
|
|
YES, NO, DISPLAYED |
YES, NO, DISPLAYED |
} wrerr; |
} wrerr; |
BUF *bp; |
BUF *bp; |
off_t i; |
off_t i, j; |
size_t j, count; |
int amt, count, exists, first, mask, mode, ofd, omode; |
int amt, exists, first, mask, mode, ofd, omode; |
|
off_t size, statbytes; |
off_t size, statbytes; |
int setimes, targisdir, wrerrno = 0; |
int setimes, targisdir, wrerrno = 0; |
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; |
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; |
|
|
targisdir = 1; |
targisdir = 1; |
for (first = 1;; first = 0) { |
for (first = 1;; first = 0) { |
cp = buf; |
cp = buf; |
if (atomicio(read, remin, cp, 1) != 1) |
if (atomicio(read, remin, cp, 1) <= 0) |
return; |
return; |
if (*cp++ == '\n') |
if (*cp++ == '\n') |
SCREWUP("unexpected <newline>"); |
SCREWUP("unexpected <newline>"); |
|
|
} |
} |
if (targisdir) { |
if (targisdir) { |
static char *namebuf; |
static char *namebuf; |
static size_t cursize; |
static int cursize; |
size_t need; |
size_t need; |
|
|
need = strlen(targ) + strlen(cp) + 250; |
need = strlen(targ) + strlen(cp) + 250; |
|
|
count += amt; |
count += amt; |
do { |
do { |
j = atomicio(read, remin, cp, amt); |
j = atomicio(read, remin, cp, amt); |
if (j == 0) { |
if (j <= 0) { |
run_err("%s", j ? strerror(errno) : |
run_err("%s", j ? strerror(errno) : |
"dropped connection"); |
"dropped connection"); |
exit(1); |
exit(1); |
|
|
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) { |
if (atomicio(vwrite, ofd, bp->buf, |
j = atomicio(vwrite, ofd, bp->buf, count); |
count) != count) { |
if (j != count) { |
wrerr = YES; |
wrerr = YES; |
wrerrno = errno; |
wrerrno = j >= 0 ? EIO : errno; |
} |
} |
} |
} |
count = 0; |
count = 0; |
|
|
if (showprogress) |
if (showprogress) |
stop_progress_meter(); |
stop_progress_meter(); |
if (count != 0 && wrerr == NO && |
if (count != 0 && wrerr == NO && |
atomicio(vwrite, ofd, bp->buf, count) != count) { |
(j = atomicio(vwrite, ofd, bp->buf, count)) != count) { |
wrerr = YES; |
wrerr = YES; |
wrerrno = errno; |
wrerrno = j >= 0 ? EIO : errno; |
} |
} |
if (wrerr == NO && ftruncate(ofd, size) != 0) { |
if (wrerr == NO && ftruncate(ofd, size) != 0) { |
run_err("%s: truncate: %s", np, strerror(errno)); |
run_err("%s: truncate: %s", np, strerror(errno)); |
|
|
errno = ENOTDIR; |
errno = ENOTDIR; |
} |
} |
run_err("%s: %s", cp, strerror(errno)); |
run_err("%s: %s", cp, strerror(errno)); |
killchild(0); |
exit(1); |
} |
} |
|
|
int |
int |