diff options
Diffstat (limited to 'scp.c')
-rw-r--r-- | scp.c | 55 |
1 files changed, 33 insertions, 22 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: scp.c,v 1.184 2015/11/27 00:49:31 deraadt Exp $ */ | 1 | /* $OpenBSD: scp.c,v 1.186 2016/05/25 23:48:45 schwarze Exp $ */ |
2 | /* | 2 | /* |
3 | * scp - secure remote copy. This is basically patched BSD rcp which | 3 | * scp - secure remote copy. This is basically patched BSD rcp which |
4 | * uses ssh to do the data transfer (instead of using rcmd). | 4 | * uses ssh to do the data transfer (instead of using rcmd). |
@@ -96,6 +96,7 @@ | |||
96 | #include <errno.h> | 96 | #include <errno.h> |
97 | #include <fcntl.h> | 97 | #include <fcntl.h> |
98 | #include <limits.h> | 98 | #include <limits.h> |
99 | #include <locale.h> | ||
99 | #include <pwd.h> | 100 | #include <pwd.h> |
100 | #include <signal.h> | 101 | #include <signal.h> |
101 | #include <stdarg.h> | 102 | #include <stdarg.h> |
@@ -114,6 +115,7 @@ | |||
114 | #include "log.h" | 115 | #include "log.h" |
115 | #include "misc.h" | 116 | #include "misc.h" |
116 | #include "progressmeter.h" | 117 | #include "progressmeter.h" |
118 | #include "utf8.h" | ||
117 | 119 | ||
118 | extern char *__progname; | 120 | extern char *__progname; |
119 | 121 | ||
@@ -192,13 +194,13 @@ do_local_cmd(arglist *a) | |||
192 | fprintf(stderr, "Executing:"); | 194 | fprintf(stderr, "Executing:"); |
193 | for (i = 0; i < a->num; i++) { | 195 | for (i = 0; i < a->num; i++) { |
194 | if (i == 0) | 196 | if (i == 0) |
195 | fprintf(stderr, " %s", a->list[i]); | 197 | fmprintf(stderr, " %s", a->list[i]); |
196 | else | 198 | else |
197 | /* | 199 | /* |
198 | * TODO: misbehaves if a->list[i] contains a | 200 | * TODO: misbehaves if a->list[i] contains a |
199 | * single quote | 201 | * single quote |
200 | */ | 202 | */ |
201 | fprintf(stderr, " '%s'", a->list[i]); | 203 | fmprintf(stderr, " '%s'", a->list[i]); |
202 | } | 204 | } |
203 | fprintf(stderr, "\n"); | 205 | fprintf(stderr, "\n"); |
204 | } | 206 | } |
@@ -240,7 +242,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
240 | int pin[2], pout[2], reserved[2]; | 242 | int pin[2], pout[2], reserved[2]; |
241 | 243 | ||
242 | if (verbose_mode) | 244 | if (verbose_mode) |
243 | fprintf(stderr, | 245 | fmprintf(stderr, |
244 | "Executing: program %s host %s, user %s, command %s\n", | 246 | "Executing: program %s host %s, user %s, command %s\n", |
245 | ssh_program, host, | 247 | ssh_program, host, |
246 | remuser ? remuser : "(unspecified)", cmd); | 248 | remuser ? remuser : "(unspecified)", cmd); |
@@ -315,7 +317,7 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout) | |||
315 | int status; | 317 | int status; |
316 | 318 | ||
317 | if (verbose_mode) | 319 | if (verbose_mode) |
318 | fprintf(stderr, | 320 | fmprintf(stderr, |
319 | "Executing: 2nd program %s host %s, user %s, command %s\n", | 321 | "Executing: 2nd program %s host %s, user %s, command %s\n", |
320 | ssh_program, host, | 322 | ssh_program, host, |
321 | remuser ? remuser : "(unspecified)", cmd); | 323 | remuser ? remuser : "(unspecified)", cmd); |
@@ -386,6 +388,8 @@ main(int argc, char **argv) | |||
386 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 388 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
387 | sanitise_stdfd(); | 389 | sanitise_stdfd(); |
388 | 390 | ||
391 | setlocale(LC_CTYPE, ""); | ||
392 | |||
389 | /* Copy argv, because we modify it */ | 393 | /* Copy argv, because we modify it */ |
390 | newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv)); | 394 | newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv)); |
391 | for (n = 0; n < argc; n++) | 395 | for (n = 0; n < argc; n++) |
@@ -818,9 +822,8 @@ syserr: run_err("%s: %s", name, strerror(errno)); | |||
818 | snprintf(buf, sizeof buf, "C%04o %lld %s\n", | 822 | snprintf(buf, sizeof buf, "C%04o %lld %s\n", |
819 | (u_int) (stb.st_mode & FILEMODEMASK), | 823 | (u_int) (stb.st_mode & FILEMODEMASK), |
820 | (long long)stb.st_size, last); | 824 | (long long)stb.st_size, last); |
821 | if (verbose_mode) { | 825 | if (verbose_mode) |
822 | fprintf(stderr, "Sending file modes: %s", buf); | 826 | fmprintf(stderr, "Sending file modes: %s", buf); |
823 | } | ||
824 | (void) atomicio(vwrite, remout, buf, strlen(buf)); | 827 | (void) atomicio(vwrite, remout, buf, strlen(buf)); |
825 | if (response() < 0) | 828 | if (response() < 0) |
826 | goto next; | 829 | goto next; |
@@ -856,8 +859,6 @@ next: if (fd != -1) { | |||
856 | haderr = errno; | 859 | haderr = errno; |
857 | } | 860 | } |
858 | unset_nonblock(remout); | 861 | unset_nonblock(remout); |
859 | if (showprogress) | ||
860 | stop_progress_meter(); | ||
861 | 862 | ||
862 | if (fd != -1) { | 863 | if (fd != -1) { |
863 | if (close(fd) < 0 && !haderr) | 864 | if (close(fd) < 0 && !haderr) |
@@ -869,6 +870,8 @@ next: if (fd != -1) { | |||
869 | else | 870 | else |
870 | run_err("%s: %s", name, strerror(haderr)); | 871 | run_err("%s: %s", name, strerror(haderr)); |
871 | (void) response(); | 872 | (void) response(); |
873 | if (showprogress) | ||
874 | stop_progress_meter(); | ||
872 | } | 875 | } |
873 | } | 876 | } |
874 | 877 | ||
@@ -897,7 +900,7 @@ rsource(char *name, struct stat *statp) | |||
897 | (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", | 900 | (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", |
898 | (u_int) (statp->st_mode & FILEMODEMASK), 0, last); | 901 | (u_int) (statp->st_mode & FILEMODEMASK), 0, last); |
899 | if (verbose_mode) | 902 | if (verbose_mode) |
900 | fprintf(stderr, "Entering directory: %s", path); | 903 | fmprintf(stderr, "Entering directory: %s", path); |
901 | (void) atomicio(vwrite, remout, path, strlen(path)); | 904 | (void) atomicio(vwrite, remout, path, strlen(path)); |
902 | if (response() < 0) { | 905 | if (response() < 0) { |
903 | closedir(dirp); | 906 | closedir(dirp); |
@@ -937,7 +940,7 @@ sink(int argc, char **argv) | |||
937 | off_t size, statbytes; | 940 | off_t size, statbytes; |
938 | unsigned long long ull; | 941 | unsigned long long ull; |
939 | int setimes, targisdir, wrerrno = 0; | 942 | int setimes, targisdir, wrerrno = 0; |
940 | char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; | 943 | char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; |
941 | struct timeval tv[2]; | 944 | struct timeval tv[2]; |
942 | 945 | ||
943 | #define atime tv[0] | 946 | #define atime tv[0] |
@@ -972,12 +975,15 @@ sink(int argc, char **argv) | |||
972 | } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); | 975 | } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); |
973 | *cp = 0; | 976 | *cp = 0; |
974 | if (verbose_mode) | 977 | if (verbose_mode) |
975 | fprintf(stderr, "Sink: %s", buf); | 978 | fmprintf(stderr, "Sink: %s", buf); |
976 | 979 | ||
977 | if (buf[0] == '\01' || buf[0] == '\02') { | 980 | if (buf[0] == '\01' || buf[0] == '\02') { |
978 | if (iamremote == 0) | 981 | if (iamremote == 0) { |
982 | (void) snmprintf(visbuf, sizeof(visbuf), | ||
983 | NULL, "%s", buf + 1); | ||
979 | (void) atomicio(vwrite, STDERR_FILENO, | 984 | (void) atomicio(vwrite, STDERR_FILENO, |
980 | buf + 1, strlen(buf + 1)); | 985 | visbuf, strlen(visbuf)); |
986 | } | ||
981 | if (buf[0] == '\02') | 987 | if (buf[0] == '\02') |
982 | exit(1); | 988 | exit(1); |
983 | ++errs; | 989 | ++errs; |
@@ -1153,8 +1159,6 @@ bad: run_err("%s: %s", np, strerror(errno)); | |||
1153 | } | 1159 | } |
1154 | } | 1160 | } |
1155 | unset_nonblock(remin); | 1161 | unset_nonblock(remin); |
1156 | if (showprogress) | ||
1157 | stop_progress_meter(); | ||
1158 | if (count != 0 && wrerr == NO && | 1162 | if (count != 0 && wrerr == NO && |
1159 | atomicio(vwrite, ofd, bp->buf, count) != count) { | 1163 | atomicio(vwrite, ofd, bp->buf, count) != count) { |
1160 | wrerr = YES; | 1164 | wrerr = YES; |
@@ -1193,6 +1197,8 @@ bad: run_err("%s: %s", np, strerror(errno)); | |||
1193 | wrerrno = errno; | 1197 | wrerrno = errno; |
1194 | } | 1198 | } |
1195 | (void) response(); | 1199 | (void) response(); |
1200 | if (showprogress) | ||
1201 | stop_progress_meter(); | ||
1196 | if (setimes && wrerr == NO) { | 1202 | if (setimes && wrerr == NO) { |
1197 | setimes = 0; | 1203 | setimes = 0; |
1198 | if (utimes(np, tv) < 0) { | 1204 | if (utimes(np, tv) < 0) { |
@@ -1220,7 +1226,7 @@ screwup: | |||
1220 | int | 1226 | int |
1221 | response(void) | 1227 | response(void) |
1222 | { | 1228 | { |
1223 | char ch, *cp, resp, rbuf[2048]; | 1229 | char ch, *cp, resp, rbuf[2048], visbuf[2048]; |
1224 | 1230 | ||
1225 | if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) | 1231 | if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) |
1226 | lostconn(0); | 1232 | lostconn(0); |
@@ -1240,8 +1246,13 @@ response(void) | |||
1240 | *cp++ = ch; | 1246 | *cp++ = ch; |
1241 | } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); | 1247 | } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); |
1242 | 1248 | ||
1243 | if (!iamremote) | 1249 | if (!iamremote) { |
1244 | (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf); | 1250 | cp[-1] = '\0'; |
1251 | (void) snmprintf(visbuf, sizeof(visbuf), | ||
1252 | NULL, "%s\n", rbuf); | ||
1253 | (void) atomicio(vwrite, STDERR_FILENO, | ||
1254 | visbuf, strlen(visbuf)); | ||
1255 | } | ||
1245 | ++errs; | 1256 | ++errs; |
1246 | if (resp == 1) | 1257 | if (resp == 1) |
1247 | return (-1); | 1258 | return (-1); |
@@ -1279,7 +1290,7 @@ run_err(const char *fmt,...) | |||
1279 | 1290 | ||
1280 | if (!iamremote) { | 1291 | if (!iamremote) { |
1281 | va_start(ap, fmt); | 1292 | va_start(ap, fmt); |
1282 | vfprintf(stderr, fmt, ap); | 1293 | vfmprintf(stderr, fmt, ap); |
1283 | va_end(ap); | 1294 | va_end(ap); |
1284 | fprintf(stderr, "\n"); | 1295 | fprintf(stderr, "\n"); |
1285 | } | 1296 | } |
@@ -1325,7 +1336,7 @@ okname(char *cp0) | |||
1325 | } while (*++cp); | 1336 | } while (*++cp); |
1326 | return (1); | 1337 | return (1); |
1327 | 1338 | ||
1328 | bad: fprintf(stderr, "%s: invalid user name\n", cp0); | 1339 | bad: fmprintf(stderr, "%s: invalid user name\n", cp0); |
1329 | return (0); | 1340 | return (0); |
1330 | } | 1341 | } |
1331 | 1342 | ||