X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/47b535189e432cd21707d9ad9acfffd80e921389..06617857197c00b4fdd0e1456bf25c82c796f4cf:/scp.c diff --git a/scp.c b/scp.c index 0c4400f6..1fab4838 100644 --- a/scp.c +++ b/scp.c @@ -75,7 +75,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.67 2001/04/16 02:31:43 mouring Exp $"); +RCSID("$OpenBSD: scp.c,v 1.88 2002/04/06 18:24:09 mouring Exp $"); #include "xmalloc.h" #include "atomicio.h" @@ -91,14 +91,8 @@ char *__progname; /* For progressmeter() -- number of seconds before xfer considered "stalled" */ #define STALLTIME 5 - -/* Progress meter bar */ -#define BAR \ - "************************************************************"\ - "************************************************************"\ - "************************************************************"\ - "************************************************************" -#define MAX_BARLENGTH (sizeof(BAR) - 1) +/* alarm() interval for updating progress meter */ +#define PROGRESSTIME 1 /* Visual statistics about files as they are transferred. */ void progressmeter(int); @@ -107,14 +101,14 @@ void progressmeter(int); int getttywidth(void); int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); -/* setup arguments for the call to ssh */ -void addargs(char *fmt, ...) __attribute__((format(printf, 1, 2))); +/* Struct for addargs */ +arglist args; /* Time a transfer started. */ static struct timeval start; /* Number of bytes of current file transferred so far. */ -volatile u_long statbytes; +volatile off_t statbytes; /* Total size of current file. */ off_t totalbytes = 0; @@ -131,13 +125,6 @@ int showprogress = 1; /* This is the program to execute for the secured connection. ("ssh" or -S) */ 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 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This @@ -150,8 +137,10 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) int pin[2], pout[2], reserved[2]; if (verbose_mode) - fprintf(stderr, "Executing: program %s host %s, user %s, command %s\n", - ssh_program, host, remuser ? remuser : "(unspecified)", cmd); + fprintf(stderr, + "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 @@ -181,9 +170,9 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) args.list[0] = ssh_program; if (remuser != NULL) - addargs("-l%s", remuser); - addargs("%s", host); - addargs("%s", cmd); + addargs(&args, "-l%s", remuser); + addargs(&args, "%s", host); + addargs(&args, "%s", cmd); execvp(ssh_program, args.list); perror(ssh_program); @@ -238,29 +227,32 @@ main(argc, argv) __progname = get_progname(argv[0]); args.list = NULL; - addargs("ssh"); /* overwritten with ssh_program */ - addargs("-x"); - addargs("-oFallBackToRsh no"); + 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:")) != -1) + while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) switch (ch) { /* User-visible flags. */ case '4': case '6': case 'C': - addargs("-%c", ch); + addargs(&args, "-%c", ch); break; case 'o': case 'c': case 'i': - addargs("-%c%s", ch, optarg); + case 'F': + addargs(&args, "-%c%s", ch, optarg); break; case 'P': - addargs("-p%s", optarg); + addargs(&args, "-p%s", optarg); break; case 'B': - addargs("-oBatchmode yes"); + addargs(&args, "-oBatchmode yes"); break; case 'p': pflag = 1; @@ -272,6 +264,7 @@ main(argc, argv) ssh_program = xstrdup(optarg); break; case 'v': + addargs(&args, "-v"); verbose_mode = 1; break; case 'q': @@ -371,13 +364,17 @@ 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'FallBackToRsh no' " + "-o'ClearAllForwardings yes'"; *src++ = 0; if (*src == 0) src = "."; host = strchr(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 +385,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); } @@ -487,8 +484,8 @@ source(argc, argv) struct stat stb; static BUF buffer; BUF *bp; - off_t i; - int amt, fd, haderr, indx, result; + off_t i, amt, result; + int fd, haderr, indx; char *last, *name, buf[2048]; int len; @@ -498,6 +495,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,14 +540,13 @@ 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); @@ -668,7 +669,7 @@ sink(argc, argv) #define atime tv[0] #define mtime tv[1] -#define SCREWUP(str) { why = str; goto screwup; } +#define SCREWUP(str) do { why = str; goto screwup; } while (0) setimes = targisdir = 0; mask = umask(0); @@ -773,7 +774,7 @@ sink(argc, argv) cursize = need; } (void) snprintf(namebuf, need, "%s%s%s", targ, - *targ ? "/" : "", cp); + strcmp(targ, "/") ? "/" : "", cp); np = namebuf; } else np = targ; @@ -811,7 +812,7 @@ sink(argc, argv) } omode = mode; 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)); continue; } @@ -835,7 +836,8 @@ bad: run_err("%s: %s", np, strerror(errno)); count += amt; do { j = read(remin, cp, amt); - if (j == -1 && (errno == EINTR || errno == EAGAIN)) { + if (j == -1 && (errno == EINTR || + errno == EAGAIN)) { continue; } else if (j <= 0) { run_err("%s", j ? strerror(errno) : @@ -866,12 +868,10 @@ bad: run_err("%s: %s", np, strerror(errno)); wrerr = YES; wrerrno = j >= 0 ? EIO : errno; } -#if 0 if (ftruncate(ofd, size)) { run_err("%s: truncate: %s", np, strerror(errno)); wrerr = DISPLAYED; } -#endif if (pflag) { if (exists || omode != mode) #ifdef HAVE_FCHMOD @@ -921,7 +921,7 @@ screwup: } int -response() +response(void) { char ch, *cp, resp, rbuf[2048]; @@ -954,10 +954,11 @@ response() } void -usage() +usage(void) { - (void) fprintf(stderr, "usage: scp " - "[-pqrvBC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2\n" + (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"); exit(1); } @@ -1011,7 +1012,7 @@ okname(cp0) cp = cp0; do { - c = *cp; + c = (int)*cp; if (c & 0200) goto bad; if (!isalpha(c) && !isdigit(c) && @@ -1030,7 +1031,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,15 +1043,16 @@ 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) bp->buf = xmalloc(size); else bp->buf = xrealloc(bp->buf, size); + memset(bp->buf, 0, size); bp->cnt = size; return (bp); } @@ -1060,32 +1062,25 @@ lostconn(signo) int signo; { if (!iamremote) - fprintf(stderr, "lost connection\n"); - exit(1); -} - - -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); + write(STDERR_FILENO, "lost connection\n", 16); + if (signo) + _exit(1); + else + exit(1); } -void +static void updateprogressmeter(int ignore) { int save_errno = errno; progressmeter(0); + signal(SIGALRM, updateprogressmeter); + alarm(PROGRESSTIME); errno = save_errno; } -int +static int foregroundproc(void) { static pid_t pgrp = -1; @@ -1113,7 +1108,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); @@ -1135,11 +1130,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; @@ -1194,9 +1196,9 @@ progressmeter(int flag) if (flag == -1) { mysignal(SIGALRM, updateprogressmeter); - alarmtimer(1); + alarm(PROGRESSTIME); } else if (flag == 1) { - alarmtimer(0); + alarm(0); atomicio(write, fileno(stdout), "\n", 1); statbytes = 0; } @@ -1212,25 +1214,3 @@ getttywidth(void) else 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; -}