*/
#include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.83 2001/09/17 17:57:56 stevesk Exp $");
+RCSID("$OpenBSD: scp.c,v 1.94 2002/11/27 17:53:35 markus Exp $");
#include "xmalloc.h"
#include "atomicio.h"
/* alarm() interval for updating progress meter */
#define PROGRESSTIME 1
-/* Progress meter bar */
-#define BAR \
- "************************************************************"\
- "************************************************************"\
- "************************************************************"\
- "************************************************************"
-#define MAX_BARLENGTH (sizeof(BAR) - 1)
-
/* Visual statistics about files as they are transferred. */
void progressmeter(int);
/* This is the program to execute for the secured connection. ("ssh" or -S) */
char *ssh_program = _PATH_SSH_PROGRAM;
+/* This is used to store the pid of ssh_program */
+pid_t do_cmd_pid;
+
/*
* This function executes the given command as the specified user on the
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
close(reserved[1]);
/* For a child to execute the command on the remote host using ssh. */
- if (fork() == 0) {
+ do_cmd_pid = fork();
+ if (do_cmd_pid == 0) {
/* Child. */
close(pin[1]);
close(pout[0]);
execvp(ssh_program, args.list);
perror(ssh_program);
exit(1);
+ } else if (do_cmd_pid == -1) {
+ fatal("fork: %s", strerror(errno));
}
/* Parent. Close the other side, and return the local side. */
close(pin[0]);
int argc;
char *argv[];
{
- int ch, fflag, tflag;
+ int ch, fflag, tflag, status;
char *targ;
extern char *optarg;
extern int optind;
__progname = get_progname(argv[0]);
args.list = NULL;
- addargs(&args, "ssh"); /* overwritten with ssh_program */
+ addargs(&args, "ssh"); /* overwritten with ssh_program */
addargs(&args, "-x");
addargs(&args, "-oForwardAgent no");
- addargs(&args, "-oFallBackToRsh no");
+ addargs(&args, "-oClearAllForwardings yes");
fflag = tflag = 0;
while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1)
targetshouldbedirectory = 1;
remin = remout = -1;
+ do_cmd_pid = -1;
/* Command to be executed on remote system using "ssh". */
(void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
verbose_mode ? " -v" : "",
if (targetshouldbedirectory)
verifydir(argv[argc - 1]);
}
+ /*
+ * Finally check the exit status of the ssh process, if one was forked
+ * and no error has occured yet
+ */
+ if (do_cmd_pid != -1 && errs == 0) {
+ if (remin != -1)
+ (void) close(remin);
+ if (remout != -1)
+ (void) close(remout);
+ if (waitpid(do_cmd_pid, &status, 0) == -1)
+ errs = 1;
+ else {
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ errs = 1;
+ }
+ }
exit(errs != 0);
}
if (*targ == 0)
targ = ".";
- if ((thost = strchr(argv[argc - 1], '@'))) {
+ if ((thost = strrchr(argv[argc - 1], '@'))) {
/* user@host */
*thost++ = 0;
tuser = argv[argc - 1];
for (i = 0; i < argc - 1; i++) {
src = colon(argv[i]);
if (src) { /* remote to remote */
+ static char *ssh_options =
+ "-x -o'ClearAllForwardings yes'";
*src++ = 0;
if (*src == 0)
src = ".";
- host = strchr(argv[i], '@');
+ host = strrchr(argv[i], '@');
len = strlen(ssh_program) + strlen(argv[i]) +
strlen(src) + (tuser ? strlen(tuser) : 0) +
- strlen(thost) + strlen(targ) + CMDNEEDS + 32;
+ strlen(thost) + strlen(targ) +
+ strlen(ssh_options) + CMDNEEDS + 20;
bp = xmalloc(len);
if (host) {
*host++ = 0;
else if (!okname(suser))
continue;
snprintf(bp, len,
- "%s%s -x -o'FallBackToRsh no' -n "
+ "%s%s %s -n "
"-l %s %s %s %s '%s%s%s:%s'",
ssh_program, verbose_mode ? " -v" : "",
- suser, host, cmd, src,
+ ssh_options, suser, host, cmd, src,
tuser ? tuser : "", tuser ? "@" : "",
thost, targ);
} else {
host = cleanhostname(argv[i]);
snprintf(bp, len,
- "exec %s%s -x -o'FallBackToRsh no' -n %s "
+ "exec %s%s %s -n %s "
"%s %s '%s%s%s:%s'",
ssh_program, verbose_mode ? " -v" : "",
- host, cmd, src,
+ ssh_options, host, cmd, src,
tuser ? tuser : "", tuser ? "@" : "",
thost, targ);
}
*src++ = 0;
if (*src == 0)
src = ".";
- if ((host = strchr(argv[i], '@')) == NULL) {
+ if ((host = strrchr(argv[i], '@')) == NULL) {
host = argv[i];
suser = NULL;
} else {
len = strlen(name);
while (len > 1 && name[len-1] == '/')
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)
goto syserr;
if (fstat(fd, &stb) < 0) {
#ifdef HAVE_LONG_LONG_INT
snprintf(buf, sizeof buf, "C%04o %lld %s\n",
(u_int) (stb.st_mode & FILEMODEMASK),
- (long long) stb.st_size, last);
+ (long long)stb.st_size, last);
#else
/* XXX: Handle integer overflow? */
snprintf(buf, sizeof buf, "C%04o %lu %s\n",
(u_int) (stb.st_mode & FILEMODEMASK),
(u_long) stb.st_size, last);
#endif
-
if (verbose_mode) {
fprintf(stderr, "Sending file modes: %s", buf);
- fflush(stderr);
}
(void) atomicio(write, remout, buf, strlen(buf));
if (response() < 0)
cursize = need;
}
(void) snprintf(namebuf, need, "%s%s%s", targ,
- *targ ? "/" : "", cp);
+ strcmp(targ, "/") ? "/" : "", cp);
np = namebuf;
} else
np = targ;
}
int
-response()
+response(void)
{
char ch, *cp, resp, rbuf[2048];
}
void
-usage()
+usage(void)
{
(void) fprintf(stderr,
- "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");
+ "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
+ " [-c cipher] [-i identity] [-o option]\n"
+ " [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
exit(1);
}
if (c & 0200)
goto bad;
if (!isalpha(c) && !isdigit(c) &&
- c != '_' && c != '-' && c != '.' && c != '+')
+ c != '@' && c != '_' && c != '-' && c != '.' && c != '+')
goto bad;
} while (*++cp);
return (1);
int fd, blksize;
{
size_t size;
-#ifdef HAVE_ST_BLKSIZE
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
struct stat stb;
if (fstat(fd, &stb) < 0) {
else
size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
stb.st_blksize;
-#else /* HAVE_ST_BLKSIZE */
+#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
size = blksize;
-#endif /* HAVE_ST_BLKSIZE */
+#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
if (bp->cnt >= size)
return (bp);
if (bp->buf == NULL)
off_t cursize, abbrevsize;
double elapsed;
int ratio, barlength, i, remaining;
- char buf[256];
+ char buf[512];
if (flag == -1) {
(void) gettimeofday(&start, (struct timezone *) 0);
snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio);
barlength = getttywidth() - 51;
- barlength = (barlength <= MAX_BARLENGTH)?barlength:MAX_BARLENGTH;
if (barlength > 0) {
i = barlength * ratio / 100;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "|%.*s%*s|", i, BAR, barlength - i, "");
+ "|%.*s%*s|", i,
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************"
+ "*******************************************************",
+ barlength - i, "");
}
i = 0;
abbrevsize = cursize;