Deleted Added
full compact
scp.c (107857) scp.c (113911)
1/*
2 * scp - secure remote copy. This is basically patched BSD rcp which
3 * uses ssh to do the data transfer (instead of using rcmd).
4 *
5 * NOTE: This version should NOT be suid root. (This uses ssh to
6 * do the transfer and ssh has the necessary privileges.)
7 *
8 * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>

--- 61 unchanged lines hidden (view full) ---

70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 */
76
77#include "includes.h"
1/*
2 * scp - secure remote copy. This is basically patched BSD rcp which
3 * uses ssh to do the data transfer (instead of using rcmd).
4 *
5 * NOTE: This version should NOT be suid root. (This uses ssh to
6 * do the transfer and ssh has the necessary privileges.)
7 *
8 * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>

--- 61 unchanged lines hidden (view full) ---

70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 */
76
77#include "includes.h"
78RCSID("$OpenBSD: scp.c,v 1.91 2002/06/19 00:27:55 deraadt Exp $");
79RCSID("$FreeBSD: head/crypto/openssh/scp.c 107857 2002-12-14 13:38:49Z des $");
78RCSID("$OpenBSD: scp.c,v 1.102 2003/03/05 22:33:43 markus Exp $");
79RCSID("$FreeBSD: head/crypto/openssh/scp.c 113911 2003-04-23 17:13:13Z des $");
80
81#include "xmalloc.h"
82#include "atomicio.h"
83#include "pathnames.h"
84#include "log.h"
85#include "misc.h"
80
81#include "xmalloc.h"
82#include "atomicio.h"
83#include "pathnames.h"
84#include "log.h"
85#include "misc.h"
86#include "progressmeter.h"
86
87#ifdef HAVE___PROGNAME
88extern char *__progname;
89#else
90char *__progname;
91#endif
92
87
88#ifdef HAVE___PROGNAME
89extern char *__progname;
90#else
91char *__progname;
92#endif
93
93/* For progressmeter() -- number of seconds before xfer considered "stalled" */
94#define STALLTIME 5
95/* alarm() interval for updating progress meter */
96#define PROGRESSTIME 1
94void bwlimit(int);
97
95
98/* Visual statistics about files as they are transferred. */
99void progressmeter(int);
100
101/* Returns width of the terminal (for progress meter calculations). */
102int getttywidth(void);
103int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
104
105/* Struct for addargs */
106arglist args;
107
96/* Struct for addargs */
97arglist args;
98
108/* Time a transfer started. */
109static struct timeval start;
99/* Bandwidth limit */
100off_t limitbw = 0;
110
101
111/* Number of bytes of current file transferred so far. */
112volatile off_t statbytes;
113
114/* Total size of current file. */
115off_t totalbytes = 0;
116
117/* Name of current file being transferred. */
118char *curfile;
119
120/* This is set to non-zero to enable verbose mode. */
121int verbose_mode = 0;
122
123/* This is set to zero if the progressmeter is not desired. */
124int showprogress = 1;
125
126/* This is the program to execute for the secured connection. ("ssh" or -S) */
127char *ssh_program = _PATH_SSH_PROGRAM;
128
102/* Name of current file being transferred. */
103char *curfile;
104
105/* This is set to non-zero to enable verbose mode. */
106int verbose_mode = 0;
107
108/* This is set to zero if the progressmeter is not desired. */
109int showprogress = 1;
110
111/* This is the program to execute for the secured connection. ("ssh" or -S) */
112char *ssh_program = _PATH_SSH_PROGRAM;
113
114/* This is used to store the pid of ssh_program */
115pid_t do_cmd_pid;
116
129/*
130 * This function executes the given command as the specified user on the
131 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
132 * assigns the input and output file descriptors on success.
133 */
134
135int
136do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)

--- 18 unchanged lines hidden (view full) ---

155 if (pipe(pout) < 0)
156 fatal("pipe: %s", strerror(errno));
157
158 /* Free the reserved descriptors. */
159 close(reserved[0]);
160 close(reserved[1]);
161
162 /* For a child to execute the command on the remote host using ssh. */
117/*
118 * This function executes the given command as the specified user on the
119 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
120 * assigns the input and output file descriptors on success.
121 */
122
123int
124do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)

--- 18 unchanged lines hidden (view full) ---

143 if (pipe(pout) < 0)
144 fatal("pipe: %s", strerror(errno));
145
146 /* Free the reserved descriptors. */
147 close(reserved[0]);
148 close(reserved[1]);
149
150 /* For a child to execute the command on the remote host using ssh. */
163 if (fork() == 0) {
151 do_cmd_pid = fork();
152 if (do_cmd_pid == 0) {
164 /* Child. */
165 close(pin[1]);
166 close(pout[0]);
167 dup2(pin[0], 0);
168 dup2(pout[1], 1);
169 close(pin[0]);
170 close(pout[1]);
171
172 args.list[0] = ssh_program;
173 if (remuser != NULL)
174 addargs(&args, "-l%s", remuser);
175 addargs(&args, "%s", host);
176 addargs(&args, "%s", cmd);
177
178 execvp(ssh_program, args.list);
179 perror(ssh_program);
180 exit(1);
153 /* Child. */
154 close(pin[1]);
155 close(pout[0]);
156 dup2(pin[0], 0);
157 dup2(pout[1], 1);
158 close(pin[0]);
159 close(pout[1]);
160
161 args.list[0] = ssh_program;
162 if (remuser != NULL)
163 addargs(&args, "-l%s", remuser);
164 addargs(&args, "%s", host);
165 addargs(&args, "%s", cmd);
166
167 execvp(ssh_program, args.list);
168 perror(ssh_program);
169 exit(1);
170 } else if (do_cmd_pid == -1) {
171 fatal("fork: %s", strerror(errno));
181 }
182 /* Parent. Close the other side, and return the local side. */
183 close(pin[0]);
184 *fdout = pin[1];
185 close(pout[1]);
186 *fdin = pout[0];
187 return 0;
188}

--- 26 unchanged lines hidden (view full) ---

215void toremote(char *, int, char *[]);
216void usage(void);
217
218int
219main(argc, argv)
220 int argc;
221 char *argv[];
222{
172 }
173 /* Parent. Close the other side, and return the local side. */
174 close(pin[0]);
175 *fdout = pin[1];
176 close(pout[1]);
177 *fdin = pout[0];
178 return 0;
179}

--- 26 unchanged lines hidden (view full) ---

206void toremote(char *, int, char *[]);
207void usage(void);
208
209int
210main(argc, argv)
211 int argc;
212 char *argv[];
213{
223 int ch, fflag, tflag;
224 char *targ;
214 int ch, fflag, tflag, status;
215 double speed;
216 char *targ, *endp;
225 extern char *optarg;
226 extern int optind;
227
228 __progname = get_progname(argv[0]);
229
230 args.list = NULL;
231 addargs(&args, "ssh"); /* overwritten with ssh_program */
232 addargs(&args, "-x");
233 addargs(&args, "-oForwardAgent no");
234 addargs(&args, "-oClearAllForwardings yes");
235
236 fflag = tflag = 0;
217 extern char *optarg;
218 extern int optind;
219
220 __progname = get_progname(argv[0]);
221
222 args.list = NULL;
223 addargs(&args, "ssh"); /* overwritten with ssh_program */
224 addargs(&args, "-x");
225 addargs(&args, "-oForwardAgent no");
226 addargs(&args, "-oClearAllForwardings yes");
227
228 fflag = tflag = 0;
237 while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1)
229 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
238 switch (ch) {
239 /* User-visible flags. */
230 switch (ch) {
231 /* User-visible flags. */
232 case '1':
233 case '2':
240 case '4':
241 case '6':
242 case 'C':
243 addargs(&args, "-%c", ch);
244 break;
245 case 'o':
246 case 'c':
247 case 'i':
248 case 'F':
249 addargs(&args, "-%c%s", ch, optarg);
250 break;
251 case 'P':
252 addargs(&args, "-p%s", optarg);
253 break;
254 case 'B':
255 addargs(&args, "-oBatchmode yes");
256 break;
234 case '4':
235 case '6':
236 case 'C':
237 addargs(&args, "-%c", ch);
238 break;
239 case 'o':
240 case 'c':
241 case 'i':
242 case 'F':
243 addargs(&args, "-%c%s", ch, optarg);
244 break;
245 case 'P':
246 addargs(&args, "-p%s", optarg);
247 break;
248 case 'B':
249 addargs(&args, "-oBatchmode yes");
250 break;
251 case 'l':
252 speed = strtod(optarg, &endp);
253 if (speed <= 0 || *endp != '\0')
254 usage();
255 limitbw = speed * 1024;
256 break;
257 case 'p':
258 pflag = 1;
259 break;
260 case 'r':
261 iamrecursive = 1;
262 break;
263 case 'S':
264 ssh_program = xstrdup(optarg);

--- 48 unchanged lines hidden (view full) ---

313 exit(errs != 0);
314 }
315 if (argc < 2)
316 usage();
317 if (argc > 2)
318 targetshouldbedirectory = 1;
319
320 remin = remout = -1;
257 case 'p':
258 pflag = 1;
259 break;
260 case 'r':
261 iamrecursive = 1;
262 break;
263 case 'S':
264 ssh_program = xstrdup(optarg);

--- 48 unchanged lines hidden (view full) ---

313 exit(errs != 0);
314 }
315 if (argc < 2)
316 usage();
317 if (argc > 2)
318 targetshouldbedirectory = 1;
319
320 remin = remout = -1;
321 do_cmd_pid = -1;
321 /* Command to be executed on remote system using "ssh". */
322 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
323 verbose_mode ? " -v" : "",
324 iamrecursive ? " -r" : "", pflag ? " -p" : "",
325 targetshouldbedirectory ? " -d" : "");
326
327 (void) signal(SIGPIPE, lostconn);
328
329 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
330 toremote(targ, argc, argv);
331 else {
332 tolocal(argc, argv); /* Dest is local host. */
333 if (targetshouldbedirectory)
334 verifydir(argv[argc - 1]);
335 }
322 /* Command to be executed on remote system using "ssh". */
323 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
324 verbose_mode ? " -v" : "",
325 iamrecursive ? " -r" : "", pflag ? " -p" : "",
326 targetshouldbedirectory ? " -d" : "");
327
328 (void) signal(SIGPIPE, lostconn);
329
330 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
331 toremote(targ, argc, argv);
332 else {
333 tolocal(argc, argv); /* Dest is local host. */
334 if (targetshouldbedirectory)
335 verifydir(argv[argc - 1]);
336 }
337 /*
338 * Finally check the exit status of the ssh process, if one was forked
339 * and no error has occured yet
340 */
341 if (do_cmd_pid != -1 && errs == 0) {
342 if (remin != -1)
343 (void) close(remin);
344 if (remout != -1)
345 (void) close(remout);
346 if (waitpid(do_cmd_pid, &status, 0) == -1)
347 errs = 1;
348 else {
349 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
350 errs = 1;
351 }
352 }
336 exit(errs != 0);
337}
338
339void
340toremote(targ, argc, argv)
341 char *targ, *argv[];
342 int argc;
343{
344 int i, len;
345 char *bp, *host, *src, *suser, *thost, *tuser;
346
347 *targ++ = 0;
348 if (*targ == 0)
349 targ = ".";
350
353 exit(errs != 0);
354}
355
356void
357toremote(targ, argc, argv)
358 char *targ, *argv[];
359 int argc;
360{
361 int i, len;
362 char *bp, *host, *src, *suser, *thost, *tuser;
363
364 *targ++ = 0;
365 if (*targ == 0)
366 targ = ".";
367
351 if ((thost = strchr(argv[argc - 1], '@'))) {
368 if ((thost = strrchr(argv[argc - 1], '@'))) {
352 /* user@host */
353 *thost++ = 0;
354 tuser = argv[argc - 1];
355 if (*tuser == '\0')
356 tuser = NULL;
369 /* user@host */
370 *thost++ = 0;
371 tuser = argv[argc - 1];
372 if (*tuser == '\0')
373 tuser = NULL;
357 else if (!okname(tuser))
358 exit(1);
359 } else {
360 thost = argv[argc - 1];
361 tuser = NULL;
362 }
363
364 for (i = 0; i < argc - 1; i++) {
365 src = colon(argv[i]);
366 if (src) { /* remote to remote */
367 static char *ssh_options =
368 "-x -o'ClearAllForwardings yes'";
369 *src++ = 0;
370 if (*src == 0)
371 src = ".";
374 } else {
375 thost = argv[argc - 1];
376 tuser = NULL;
377 }
378
379 for (i = 0; i < argc - 1; i++) {
380 src = colon(argv[i]);
381 if (src) { /* remote to remote */
382 static char *ssh_options =
383 "-x -o'ClearAllForwardings yes'";
384 *src++ = 0;
385 if (*src == 0)
386 src = ".";
372 host = strchr(argv[i], '@');
387 host = strrchr(argv[i], '@');
373 len = strlen(ssh_program) + strlen(argv[i]) +
374 strlen(src) + (tuser ? strlen(tuser) : 0) +
375 strlen(thost) + strlen(targ) +
376 strlen(ssh_options) + CMDNEEDS + 20;
377 bp = xmalloc(len);
378 if (host) {
379 *host++ = 0;
380 host = cleanhostname(host);
381 suser = argv[i];
382 if (*suser == '\0')
383 suser = pwd->pw_name;
388 len = strlen(ssh_program) + strlen(argv[i]) +
389 strlen(src) + (tuser ? strlen(tuser) : 0) +
390 strlen(thost) + strlen(targ) +
391 strlen(ssh_options) + CMDNEEDS + 20;
392 bp = xmalloc(len);
393 if (host) {
394 *host++ = 0;
395 host = cleanhostname(host);
396 suser = argv[i];
397 if (*suser == '\0')
398 suser = pwd->pw_name;
384 else if (!okname(suser))
399 else if (!okname(suser)) {
400 xfree(bp);
385 continue;
401 continue;
402 }
403 if (tuser && !okname(tuser)) {
404 xfree(bp);
405 continue;
406 }
386 snprintf(bp, len,
387 "%s%s %s -n "
388 "-l %s %s %s %s '%s%s%s:%s'",
389 ssh_program, verbose_mode ? " -v" : "",
390 ssh_options, suser, host, cmd, src,
391 tuser ? tuser : "", tuser ? "@" : "",
392 thost, targ);
393 } else {

--- 49 unchanged lines hidden (view full) ---

443 if (system(bp))
444 ++errs;
445 (void) xfree(bp);
446 continue;
447 }
448 *src++ = 0;
449 if (*src == 0)
450 src = ".";
407 snprintf(bp, len,
408 "%s%s %s -n "
409 "-l %s %s %s %s '%s%s%s:%s'",
410 ssh_program, verbose_mode ? " -v" : "",
411 ssh_options, suser, host, cmd, src,
412 tuser ? tuser : "", tuser ? "@" : "",
413 thost, targ);
414 } else {

--- 49 unchanged lines hidden (view full) ---

464 if (system(bp))
465 ++errs;
466 (void) xfree(bp);
467 continue;
468 }
469 *src++ = 0;
470 if (*src == 0)
471 src = ".";
451 if ((host = strchr(argv[i], '@')) == NULL) {
472 if ((host = strrchr(argv[i], '@')) == NULL) {
452 host = argv[i];
453 suser = NULL;
454 } else {
455 *host++ = 0;
456 suser = argv[i];
457 if (*suser == '\0')
458 suser = pwd->pw_name;
473 host = argv[i];
474 suser = NULL;
475 } else {
476 *host++ = 0;
477 suser = argv[i];
478 if (*suser == '\0')
479 suser = pwd->pw_name;
459 else if (!okname(suser))
460 continue;
461 }
462 host = cleanhostname(host);
463 len = strlen(src) + CMDNEEDS + 20;
464 bp = xmalloc(len);
465 (void) snprintf(bp, len, "%s -f %s", cmd, src);
466 if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
467 (void) xfree(bp);
468 ++errs;

--- 9 unchanged lines hidden (view full) ---

478void
479source(argc, argv)
480 int argc;
481 char *argv[];
482{
483 struct stat stb;
484 static BUF buffer;
485 BUF *bp;
480 }
481 host = cleanhostname(host);
482 len = strlen(src) + CMDNEEDS + 20;
483 bp = xmalloc(len);
484 (void) snprintf(bp, len, "%s -f %s", cmd, src);
485 if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
486 (void) xfree(bp);
487 ++errs;

--- 9 unchanged lines hidden (view full) ---

497void
498source(argc, argv)
499 int argc;
500 char *argv[];
501{
502 struct stat stb;
503 static BUF buffer;
504 BUF *bp;
486 off_t i, amt, result;
505 off_t i, amt, result, statbytes;
487 int fd, haderr, indx;
488 char *last, *name, buf[2048];
489 int len;
490
491 for (indx = 0; indx < argc; ++indx) {
492 name = argv[indx];
493 statbytes = 0;
494 len = strlen(name);

--- 48 unchanged lines hidden (view full) ---

543#else
544 /* XXX: Handle integer overflow? */
545 snprintf(buf, sizeof buf, "C%04o %lu %s\n",
546 (u_int) (stb.st_mode & FILEMODEMASK),
547 (u_long) stb.st_size, last);
548#endif
549 if (verbose_mode) {
550 fprintf(stderr, "Sending file modes: %s", buf);
506 int fd, haderr, indx;
507 char *last, *name, buf[2048];
508 int len;
509
510 for (indx = 0; indx < argc; ++indx) {
511 name = argv[indx];
512 statbytes = 0;
513 len = strlen(name);

--- 48 unchanged lines hidden (view full) ---

562#else
563 /* XXX: Handle integer overflow? */
564 snprintf(buf, sizeof buf, "C%04o %lu %s\n",
565 (u_int) (stb.st_mode & FILEMODEMASK),
566 (u_long) stb.st_size, last);
567#endif
568 if (verbose_mode) {
569 fprintf(stderr, "Sending file modes: %s", buf);
551 fflush(stderr);
552 }
553 (void) atomicio(write, remout, buf, strlen(buf));
554 if (response() < 0)
555 goto next;
556 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
557next: (void) close(fd);
558 continue;
559 }
570 }
571 (void) atomicio(write, remout, buf, strlen(buf));
572 if (response() < 0)
573 goto next;
574 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
575next: (void) close(fd);
576 continue;
577 }
560 if (showprogress) {
561 totalbytes = stb.st_size;
562 progressmeter(-1);
563 }
578 if (showprogress)
579 start_progress_meter(curfile, stb.st_size, &statbytes);
564 /* Keep writing after an error so that we stay sync'd up. */
565 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
566 amt = bp->cnt;
567 if (i + amt > stb.st_size)
568 amt = stb.st_size - i;
569 if (!haderr) {
570 result = atomicio(read, fd, bp->buf, amt);
571 if (result != amt)
572 haderr = result >= 0 ? EIO : errno;
573 }
574 if (haderr)
575 (void) atomicio(write, remout, bp->buf, amt);
576 else {
577 result = atomicio(write, remout, bp->buf, amt);
578 if (result != amt)
579 haderr = result >= 0 ? EIO : errno;
580 statbytes += result;
581 }
580 /* Keep writing after an error so that we stay sync'd up. */
581 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
582 amt = bp->cnt;
583 if (i + amt > stb.st_size)
584 amt = stb.st_size - i;
585 if (!haderr) {
586 result = atomicio(read, fd, bp->buf, amt);
587 if (result != amt)
588 haderr = result >= 0 ? EIO : errno;
589 }
590 if (haderr)
591 (void) atomicio(write, remout, bp->buf, amt);
592 else {
593 result = atomicio(write, remout, bp->buf, amt);
594 if (result != amt)
595 haderr = result >= 0 ? EIO : errno;
596 statbytes += result;
597 }
598 if (limitbw)
599 bwlimit(amt);
582 }
583 if (showprogress)
600 }
601 if (showprogress)
584 progressmeter(1);
602 stop_progress_meter();
585
586 if (close(fd) < 0 && !haderr)
587 haderr = errno;
588 if (!haderr)
589 (void) atomicio(write, remout, "", 1);
590 else
591 run_err("%s: %s", name, strerror(haderr));
592 (void) response();

--- 51 unchanged lines hidden (view full) ---

644 source(1, vect);
645 }
646 (void) closedir(dirp);
647 (void) atomicio(write, remout, "E\n", 2);
648 (void) response();
649}
650
651void
603
604 if (close(fd) < 0 && !haderr)
605 haderr = errno;
606 if (!haderr)
607 (void) atomicio(write, remout, "", 1);
608 else
609 run_err("%s: %s", name, strerror(haderr));
610 (void) response();

--- 51 unchanged lines hidden (view full) ---

662 source(1, vect);
663 }
664 (void) closedir(dirp);
665 (void) atomicio(write, remout, "E\n", 2);
666 (void) response();
667}
668
669void
670bwlimit(int amount)
671{
672 static struct timeval bwstart, bwend;
673 static int lamt, thresh = 16384;
674 u_int64_t wait;
675 struct timespec ts, rm;
676
677 if (!timerisset(&bwstart)) {
678 gettimeofday(&bwstart, NULL);
679 return;
680 }
681
682 lamt += amount;
683 if (lamt < thresh)
684 return;
685
686 gettimeofday(&bwend, NULL);
687 timersub(&bwend, &bwstart, &bwend);
688 if (!timerisset(&bwend))
689 return;
690
691 lamt *= 8;
692 wait = (double)1000000L * lamt / limitbw;
693
694 bwstart.tv_sec = wait / 1000000L;
695 bwstart.tv_usec = wait % 1000000L;
696
697 if (timercmp(&bwstart, &bwend, >)) {
698 timersub(&bwstart, &bwend, &bwend);
699
700 /* Adjust the wait time */
701 if (bwend.tv_sec) {
702 thresh /= 2;
703 if (thresh < 2048)
704 thresh = 2048;
705 } else if (bwend.tv_usec < 100) {
706 thresh *= 2;
707 if (thresh > 32768)
708 thresh = 32768;
709 }
710
711 TIMEVAL_TO_TIMESPEC(&bwend, &ts);
712 while (nanosleep(&ts, &rm) == -1) {
713 if (errno != EINTR)
714 break;
715 ts = rm;
716 }
717 }
718
719 lamt = 0;
720 gettimeofday(&bwstart, NULL);
721}
722
723void
652sink(argc, argv)
653 int argc;
654 char *argv[];
655{
656 static BUF buffer;
657 struct stat stb;
658 enum {
659 YES, NO, DISPLAYED
660 } wrerr;
661 BUF *bp;
662 off_t i, j;
663 int amt, count, exists, first, mask, mode, ofd, omode;
724sink(argc, argv)
725 int argc;
726 char *argv[];
727{
728 static BUF buffer;
729 struct stat stb;
730 enum {
731 YES, NO, DISPLAYED
732 } wrerr;
733 BUF *bp;
734 off_t i, j;
735 int amt, count, exists, first, mask, mode, ofd, omode;
664 off_t size;
736 off_t size, statbytes;
665 int setimes, targisdir, wrerrno = 0;
666 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
667 struct timeval tv[2];
668
669#define atime tv[0]
670#define mtime tv[1]
671#define SCREWUP(str) do { why = str; goto screwup; } while (0)
672

--- 145 unchanged lines hidden (view full) ---

818 (void) atomicio(write, remout, "", 1);
819 if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
820 (void) close(ofd);
821 continue;
822 }
823 cp = bp->buf;
824 wrerr = NO;
825
737 int setimes, targisdir, wrerrno = 0;
738 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
739 struct timeval tv[2];
740
741#define atime tv[0]
742#define mtime tv[1]
743#define SCREWUP(str) do { why = str; goto screwup; } while (0)
744

--- 145 unchanged lines hidden (view full) ---

890 (void) atomicio(write, remout, "", 1);
891 if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
892 (void) close(ofd);
893 continue;
894 }
895 cp = bp->buf;
896 wrerr = NO;
897
826 if (showprogress) {
827 totalbytes = size;
828 progressmeter(-1);
829 }
830 statbytes = 0;
898 statbytes = 0;
899 if (showprogress)
900 start_progress_meter(curfile, size, &statbytes);
831 for (count = i = 0; i < size; i += 4096) {
832 amt = 4096;
833 if (i + amt > size)
834 amt = size - i;
835 count += amt;
836 do {
837 j = read(remin, cp, amt);
838 if (j == -1 && (errno == EINTR ||
839 errno == EAGAIN)) {
840 continue;
841 } else if (j <= 0) {
842 run_err("%s", j ? strerror(errno) :
843 "dropped connection");
844 exit(1);
845 }
846 amt -= j;
847 cp += j;
848 statbytes += j;
849 } while (amt > 0);
901 for (count = i = 0; i < size; i += 4096) {
902 amt = 4096;
903 if (i + amt > size)
904 amt = size - i;
905 count += amt;
906 do {
907 j = read(remin, cp, amt);
908 if (j == -1 && (errno == EINTR ||
909 errno == EAGAIN)) {
910 continue;
911 } else if (j <= 0) {
912 run_err("%s", j ? strerror(errno) :
913 "dropped connection");
914 exit(1);
915 }
916 amt -= j;
917 cp += j;
918 statbytes += j;
919 } while (amt > 0);
920
921 if (limitbw)
922 bwlimit(4096);
923
850 if (count == bp->cnt) {
851 /* Keep reading so we stay sync'd up. */
852 if (wrerr == NO) {
853 j = atomicio(write, ofd, bp->buf, count);
854 if (j != count) {
855 wrerr = YES;
856 wrerrno = j >= 0 ? EIO : errno;
857 }
858 }
859 count = 0;
860 cp = bp->buf;
861 }
862 }
863 if (showprogress)
924 if (count == bp->cnt) {
925 /* Keep reading so we stay sync'd up. */
926 if (wrerr == NO) {
927 j = atomicio(write, ofd, bp->buf, count);
928 if (j != count) {
929 wrerr = YES;
930 wrerrno = j >= 0 ? EIO : errno;
931 }
932 }
933 count = 0;
934 cp = bp->buf;
935 }
936 }
937 if (showprogress)
864 progressmeter(1);
938 stop_progress_meter();
865 if (count != 0 && wrerr == NO &&
866 (j = atomicio(write, ofd, bp->buf, count)) != count) {
867 wrerr = YES;
868 wrerrno = j >= 0 ? EIO : errno;
869 }
939 if (count != 0 && wrerr == NO &&
940 (j = atomicio(write, ofd, bp->buf, count)) != count) {
941 wrerr = YES;
942 wrerrno = j >= 0 ? EIO : errno;
943 }
870 if (ftruncate(ofd, size)) {
944 if (wrerr == NO && ftruncate(ofd, size) != 0) {
871 run_err("%s: truncate: %s", np, strerror(errno));
872 wrerr = DISPLAYED;
873 }
874 if (pflag) {
875 if (exists || omode != mode)
876#ifdef HAVE_FCHMOD
877 if (fchmod(ofd, omode))
878#else /* HAVE_FCHMOD */

--- 72 unchanged lines hidden (view full) ---

951 }
952 /* NOTREACHED */
953}
954
955void
956usage(void)
957{
958 (void) fprintf(stderr,
945 run_err("%s: truncate: %s", np, strerror(errno));
946 wrerr = DISPLAYED;
947 }
948 if (pflag) {
949 if (exists || omode != mode)
950#ifdef HAVE_FCHMOD
951 if (fchmod(ofd, omode))
952#else /* HAVE_FCHMOD */

--- 72 unchanged lines hidden (view full) ---

1025 }
1026 /* NOTREACHED */
1027}
1028
1029void
1030usage(void)
1031{
1032 (void) fprintf(stderr,
959 "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
960 " [-c cipher] [-i identity] [-o option]\n"
1033 "usage: scp [-pqrvBC1246] [-F config] [-S program] [-P port]\n"
1034 " [-c cipher] [-i identity] [-l limit] [-o option]\n"
961 " [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
962 exit(1);
963}
964
965void
966run_err(const char *fmt,...)
967{
968 static FILE *fp;

--- 40 unchanged lines hidden (view full) ---

1009 int c;
1010 char *cp;
1011
1012 cp = cp0;
1013 do {
1014 c = (int)*cp;
1015 if (c & 0200)
1016 goto bad;
1035 " [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
1036 exit(1);
1037}
1038
1039void
1040run_err(const char *fmt,...)
1041{
1042 static FILE *fp;

--- 40 unchanged lines hidden (view full) ---

1083 int c;
1084 char *cp;
1085
1086 cp = cp0;
1087 do {
1088 c = (int)*cp;
1089 if (c & 0200)
1090 goto bad;
1017 if (!isalpha(c) && !isdigit(c) &&
1018 c != '_' && c != '-' && c != '.' && c != '+')
1019 goto bad;
1091 if (!isalpha(c) && !isdigit(c)) {
1092 switch (c) {
1093 case '\'':
1094 case '"':
1095 case '`':
1096 case ' ':
1097 case '#':
1098 goto bad;
1099 default:
1100 break;
1101 }
1102 }
1020 } while (*++cp);
1021 return (1);
1022
1023bad: fprintf(stderr, "%s: invalid user name\n", cp0);
1024 return (0);
1025}
1026
1027BUF *

--- 4 unchanged lines hidden (view full) ---

1032 size_t size;
1033#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1034 struct stat stb;
1035
1036 if (fstat(fd, &stb) < 0) {
1037 run_err("fstat: %s", strerror(errno));
1038 return (0);
1039 }
1103 } while (*++cp);
1104 return (1);
1105
1106bad: fprintf(stderr, "%s: invalid user name\n", cp0);
1107 return (0);
1108}
1109
1110BUF *

--- 4 unchanged lines hidden (view full) ---

1115 size_t size;
1116#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1117 struct stat stb;
1118
1119 if (fstat(fd, &stb) < 0) {
1120 run_err("fstat: %s", strerror(errno));
1121 return (0);
1122 }
1040 if (stb.st_blksize == 0)
1123 size = roundup(stb.st_blksize, blksize);
1124 if (size == 0)
1041 size = blksize;
1125 size = blksize;
1042 else
1043 size = roundup(stb.st_blksize, blksize);
1044#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
1045 size = blksize;
1046#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
1047 if (bp->cnt >= size)
1048 return (bp);
1049 if (bp->buf == NULL)
1050 bp->buf = xmalloc(size);
1051 else

--- 9 unchanged lines hidden (view full) ---

1061{
1062 if (!iamremote)
1063 write(STDERR_FILENO, "lost connection\n", 16);
1064 if (signo)
1065 _exit(1);
1066 else
1067 exit(1);
1068}
1126#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
1127 size = blksize;
1128#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
1129 if (bp->cnt >= size)
1130 return (bp);
1131 if (bp->buf == NULL)
1132 bp->buf = xmalloc(size);
1133 else

--- 9 unchanged lines hidden (view full) ---

1143{
1144 if (!iamremote)
1145 write(STDERR_FILENO, "lost connection\n", 16);
1146 if (signo)
1147 _exit(1);
1148 else
1149 exit(1);
1150}
1069
1070static void
1071updateprogressmeter(int ignore)
1072{
1073 int save_errno = errno;
1074
1075 progressmeter(0);
1076 signal(SIGALRM, updateprogressmeter);
1077 alarm(PROGRESSTIME);
1078 errno = save_errno;
1079}
1080
1081static int
1082foregroundproc(void)
1083{
1084 static pid_t pgrp = -1;
1085 int ctty_pgrp;
1086
1087 if (pgrp == -1)
1088 pgrp = getpgrp();
1089
1090#ifdef HAVE_TCGETPGRP
1091 return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 &&
1092 ctty_pgrp == pgrp);
1093#else
1094 return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
1095 ctty_pgrp == pgrp));
1096#endif
1097}
1098
1099void
1100progressmeter(int flag)
1101{
1102 static const char prefixes[] = " KMGTP";
1103 static struct timeval lastupdate;
1104 static off_t lastsize;
1105 struct timeval now, td, wait;
1106 off_t cursize, abbrevsize;
1107 double elapsed;
1108 int ratio, barlength, i, remaining;
1109 char buf[512];
1110
1111 if (flag == -1) {
1112 (void) gettimeofday(&start, (struct timezone *) 0);
1113 lastupdate = start;
1114 lastsize = 0;
1115 }
1116 if (foregroundproc() == 0)
1117 return;
1118
1119 (void) gettimeofday(&now, (struct timezone *) 0);
1120 cursize = statbytes;
1121 if (totalbytes != 0) {
1122 ratio = 100.0 * cursize / totalbytes;
1123 ratio = MAX(ratio, 0);
1124 ratio = MIN(ratio, 100);
1125 } else
1126 ratio = 100;
1127
1128 snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio);
1129
1130 barlength = getttywidth() - 51;
1131 if (barlength > 0) {
1132 i = barlength * ratio / 100;
1133 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1134 "|%.*s%*s|", i,
1135 "*******************************************************"
1136 "*******************************************************"
1137 "*******************************************************"
1138 "*******************************************************"
1139 "*******************************************************"
1140 "*******************************************************"
1141 "*******************************************************",
1142 barlength - i, "");
1143 }
1144 i = 0;
1145 abbrevsize = cursize;
1146 while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
1147 i++;
1148 abbrevsize >>= 10;
1149 }
1150 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5lu %c%c ",
1151 (unsigned long) abbrevsize, prefixes[i],
1152 prefixes[i] == ' ' ? ' ' : 'B');
1153
1154 timersub(&now, &lastupdate, &wait);
1155 if (cursize > lastsize) {
1156 lastupdate = now;
1157 lastsize = cursize;
1158 if (wait.tv_sec >= STALLTIME) {
1159 start.tv_sec += wait.tv_sec;
1160 start.tv_usec += wait.tv_usec;
1161 }
1162 wait.tv_sec = 0;
1163 }
1164 timersub(&now, &start, &td);
1165 elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
1166
1167 if (flag != 1 &&
1168 (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {
1169 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1170 " --:-- ETA");
1171 } else if (wait.tv_sec >= STALLTIME) {
1172 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1173 " - stalled -");
1174 } else {
1175 if (flag != 1)
1176 remaining = (int)(totalbytes / (statbytes / elapsed) -
1177 elapsed);
1178 else
1179 remaining = elapsed;
1180
1181 i = remaining / 3600;
1182 if (i)
1183 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1184 "%2d:", i);
1185 else
1186 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1187 " ");
1188 i = remaining % 3600;
1189 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1190 "%02d:%02d%s", i / 60, i % 60,
1191 (flag != 1) ? " ETA" : " ");
1192 }
1193 atomicio(write, fileno(stdout), buf, strlen(buf));
1194
1195 if (flag == -1) {
1196 mysignal(SIGALRM, updateprogressmeter);
1197 alarm(PROGRESSTIME);
1198 } else if (flag == 1) {
1199 alarm(0);
1200 atomicio(write, fileno(stdout), "\n", 1);
1201 statbytes = 0;
1202 }
1203}
1204
1205int
1206getttywidth(void)
1207{
1208 struct winsize winsize;
1209
1210 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
1211 return (winsize.ws_col ? winsize.ws_col : 80);
1212 else
1213 return (80);
1214}