]> andersk Git - openssh.git/blobdiff - scp.c
- markus@cvs.openbsd.org 2002/11/27 17:53:35
[openssh.git] / scp.c
diff --git a/scp.c b/scp.c
index 512dfa67a3c9ca850e87ffe25cb9fb8f5ba25c6e..4214e0c53dc61c28a44ed855da1ce19eb2c1dff0 100644 (file)
--- 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;
This page took 0.311131 seconds and 4 git commands to generate.