X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/f1278af7334a140e7d29024dbfd280f1cff6a090..15748b4d32dd9418e63e3f0f391aef554fd78141:/scp.c diff --git a/scp.c b/scp.c index 512dfa67..4214e0c5 100644 --- a/scp.c +++ b/scp.c @@ -75,7 +75,7 @@ */ #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" @@ -94,14 +94,6 @@ char *__progname; /* 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); @@ -133,6 +125,9 @@ int showprogress = 1; /* 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 @@ -167,7 +162,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) 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]); @@ -185,6 +181,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) 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]); @@ -227,7 +225,7 @@ main(argc, argv) int argc; char *argv[]; { - int ch, fflag, tflag; + int ch, fflag, tflag, status; char *targ; extern char *optarg; extern int optind; @@ -235,10 +233,10 @@ main(argc, argv) __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) @@ -325,6 +323,7 @@ main(argc, argv) 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" : "", @@ -340,6 +339,22 @@ main(argc, argv) 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); } @@ -355,7 +370,7 @@ toremote(targ, argc, argv) if (*targ == 0) targ = "."; - if ((thost = strchr(argv[argc - 1], '@'))) { + if ((thost = strrchr(argv[argc - 1], '@'))) { /* user@host */ *thost++ = 0; tuser = argv[argc - 1]; @@ -371,13 +386,16 @@ toremote(targ, argc, argv) 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; @@ -388,19 +406,19 @@ toremote(targ, argc, argv) 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); } @@ -452,7 +470,7 @@ tolocal(argc, argv) *src++ = 0; if (*src == 0) src = "."; - if ((host = strchr(argv[i], '@')) == NULL) { + if ((host = strrchr(argv[i], '@')) == NULL) { host = argv[i]; suser = NULL; } else { @@ -498,6 +516,11 @@ source(argc, argv) 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) { @@ -538,17 +561,15 @@ syserr: run_err("%s: %s", name, strerror(errno)); #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) @@ -773,7 +794,7 @@ sink(argc, argv) cursize = need; } (void) snprintf(namebuf, need, "%s%s%s", targ, - *targ ? "/" : "", cp); + strcmp(targ, "/") ? "/" : "", cp); np = namebuf; } else np = targ; @@ -920,7 +941,7 @@ screwup: } int -response() +response(void) { char ch, *cp, resp, rbuf[2048]; @@ -953,12 +974,12 @@ response() } 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); } @@ -1015,7 +1036,7 @@ okname(cp0) 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); @@ -1030,7 +1051,7 @@ allocbuf(bp, fd, blksize) int fd, blksize; { size_t size; -#ifdef HAVE_ST_BLKSIZE +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE struct stat stb; if (fstat(fd, &stb) < 0) { @@ -1042,9 +1063,9 @@ allocbuf(bp, fd, blksize) 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) @@ -1107,7 +1128,7 @@ progressmeter(int flag) 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); @@ -1129,11 +1150,18 @@ progressmeter(int flag) 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;