summaryrefslogtreecommitdiff
path: root/scp.c
diff options
context:
space:
mode:
Diffstat (limited to 'scp.c')
-rw-r--r--scp.c211
1 files changed, 10 insertions, 201 deletions
diff --git a/scp.c b/scp.c
index 8324549d7..44b5b4582 100644
--- a/scp.c
+++ b/scp.c
@@ -75,13 +75,14 @@
75 */ 75 */
76 76
77#include "includes.h" 77#include "includes.h"
78RCSID("$OpenBSD: scp.c,v 1.96 2002/12/13 15:20:52 markus Exp $"); 78RCSID("$OpenBSD: scp.c,v 1.97 2003/01/10 08:19:07 fgsch Exp $");
79 79
80#include "xmalloc.h" 80#include "xmalloc.h"
81#include "atomicio.h" 81#include "atomicio.h"
82#include "pathnames.h" 82#include "pathnames.h"
83#include "log.h" 83#include "log.h"
84#include "misc.h" 84#include "misc.h"
85#include "progressmeter.h"
85 86
86#ifdef HAVE___PROGNAME 87#ifdef HAVE___PROGNAME
87extern char *__progname; 88extern char *__progname;
@@ -89,30 +90,9 @@ extern char *__progname;
89char *__progname; 90char *__progname;
90#endif 91#endif
91 92
92/* For progressmeter() -- number of seconds before xfer considered "stalled" */
93#define STALLTIME 5
94/* alarm() interval for updating progress meter */
95#define PROGRESSTIME 1
96
97/* Visual statistics about files as they are transferred. */
98void progressmeter(int);
99
100/* Returns width of the terminal (for progress meter calculations). */
101int getttywidth(void);
102int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
103
104/* Struct for addargs */ 93/* Struct for addargs */
105arglist args; 94arglist args;
106 95
107/* Time a transfer started. */
108static struct timeval start;
109
110/* Number of bytes of current file transferred so far. */
111volatile off_t statbytes;
112
113/* Total size of current file. */
114off_t totalbytes = 0;
115
116/* Name of current file being transferred. */ 96/* Name of current file being transferred. */
117char *curfile; 97char *curfile;
118 98
@@ -505,7 +485,7 @@ source(argc, argv)
505 struct stat stb; 485 struct stat stb;
506 static BUF buffer; 486 static BUF buffer;
507 BUF *bp; 487 BUF *bp;
508 off_t i, amt, result; 488 off_t i, amt, result, statbytes;
509 int fd, haderr, indx; 489 int fd, haderr, indx;
510 char *last, *name, buf[2048]; 490 char *last, *name, buf[2048];
511 int len; 491 int len;
@@ -578,10 +558,8 @@ syserr: run_err("%s: %s", name, strerror(errno));
578next: (void) close(fd); 558next: (void) close(fd);
579 continue; 559 continue;
580 } 560 }
581 if (showprogress) { 561 if (showprogress)
582 totalbytes = stb.st_size; 562 start_progress_meter(curfile, stb.st_size, &statbytes);
583 progressmeter(-1);
584 }
585 /* Keep writing after an error so that we stay sync'd up. */ 563 /* Keep writing after an error so that we stay sync'd up. */
586 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 564 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
587 amt = bp->cnt; 565 amt = bp->cnt;
@@ -602,7 +580,7 @@ next: (void) close(fd);
602 } 580 }
603 } 581 }
604 if (showprogress) 582 if (showprogress)
605 progressmeter(1); 583 stop_progress_meter();
606 584
607 if (close(fd) < 0 && !haderr) 585 if (close(fd) < 0 && !haderr)
608 haderr = errno; 586 haderr = errno;
@@ -682,7 +660,7 @@ sink(argc, argv)
682 BUF *bp; 660 BUF *bp;
683 off_t i, j; 661 off_t i, j;
684 int amt, count, exists, first, mask, mode, ofd, omode; 662 int amt, count, exists, first, mask, mode, ofd, omode;
685 off_t size; 663 off_t size, statbytes;
686 int setimes, targisdir, wrerrno = 0; 664 int setimes, targisdir, wrerrno = 0;
687 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; 665 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
688 struct timeval tv[2]; 666 struct timeval tv[2];
@@ -844,11 +822,9 @@ bad: run_err("%s: %s", np, strerror(errno));
844 cp = bp->buf; 822 cp = bp->buf;
845 wrerr = NO; 823 wrerr = NO;
846 824
847 if (showprogress) {
848 totalbytes = size;
849 progressmeter(-1);
850 }
851 statbytes = 0; 825 statbytes = 0;
826 if (showprogress)
827 start_progress_meter(curfile, size, &statbytes);
852 for (count = i = 0; i < size; i += 4096) { 828 for (count = i = 0; i < size; i += 4096) {
853 amt = 4096; 829 amt = 4096;
854 if (i + amt > size) 830 if (i + amt > size)
@@ -882,7 +858,7 @@ bad: run_err("%s: %s", np, strerror(errno));
882 } 858 }
883 } 859 }
884 if (showprogress) 860 if (showprogress)
885 progressmeter(1); 861 stop_progress_meter();
886 if (count != 0 && wrerr == NO && 862 if (count != 0 && wrerr == NO &&
887 (j = atomicio(write, ofd, bp->buf, count)) != count) { 863 (j = atomicio(write, ofd, bp->buf, count)) != count) {
888 wrerr = YES; 864 wrerr = YES;
@@ -1086,170 +1062,3 @@ lostconn(signo)
1086 else 1062 else
1087 exit(1); 1063 exit(1);
1088} 1064}
1089
1090static void
1091updateprogressmeter(int ignore)
1092{
1093 int save_errno = errno;
1094
1095 progressmeter(0);
1096 signal(SIGALRM, updateprogressmeter);
1097 alarm(PROGRESSTIME);
1098 errno = save_errno;
1099}
1100
1101static int
1102foregroundproc(void)
1103{
1104 static pid_t pgrp = -1;
1105 int ctty_pgrp;
1106
1107 if (pgrp == -1)
1108 pgrp = getpgrp();
1109
1110#ifdef HAVE_TCGETPGRP
1111 return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 &&
1112 ctty_pgrp == pgrp);
1113#else
1114 return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
1115 ctty_pgrp == pgrp));
1116#endif
1117}
1118
1119void
1120progressmeter(int flag)
1121{
1122 static const char spaces[] = " "
1123 " "
1124 " "
1125 " "
1126 " "
1127 " ";
1128 static const char prefixes[] = " KMGTP";
1129 static struct timeval lastupdate;
1130 static off_t lastsize;
1131 struct timeval now, td, wait;
1132 off_t cursize, abbrevsize, bytespersec;
1133 double elapsed;
1134 int ratio, remaining, i, ai, bi, nspaces;
1135 char buf[512];
1136
1137 if (flag == -1) {
1138 (void) gettimeofday(&start, (struct timezone *) 0);
1139 lastupdate = start;
1140 lastsize = 0;
1141 }
1142 if (foregroundproc() == 0)
1143 return;
1144
1145 (void) gettimeofday(&now, (struct timezone *) 0);
1146 cursize = statbytes;
1147 if (totalbytes != 0) {
1148 ratio = 100.0 * cursize / totalbytes;
1149 ratio = MAX(ratio, 0);
1150 ratio = MIN(ratio, 100);
1151 } else
1152 ratio = 100;
1153
1154 abbrevsize = cursize;
1155 for (ai = 0; abbrevsize >= 10000 && ai < sizeof(prefixes); ai++)
1156 abbrevsize >>= 10;
1157
1158 timersub(&now, &lastupdate, &wait);
1159 if (cursize > lastsize) {
1160 lastupdate = now;
1161 lastsize = cursize;
1162 wait.tv_sec = 0;
1163 }
1164 timersub(&now, &start, &td);
1165 elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
1166
1167 bytespersec = 0;
1168 if (statbytes > 0) {
1169 bytespersec = statbytes;
1170 if (elapsed > 0.0)
1171 bytespersec /= elapsed;
1172 }
1173 for (bi = 1; bytespersec >= 1024000 && bi < sizeof(prefixes); bi++)
1174 bytespersec >>= 10;
1175
1176 nspaces = MIN(getttywidth() - 79, sizeof(spaces) - 1);
1177
1178#ifdef HAVE_LONG_LONG_INT
1179 snprintf(buf, sizeof(buf),
1180 "\r%-45.45s%.*s%3d%% %4lld%c%c %3lld.%01d%cB/s",
1181 curfile,
1182 nspaces,
1183 spaces,
1184 ratio,
1185 (long long)abbrevsize,
1186 prefixes[ai],
1187 ai == 0 ? ' ' : 'B',
1188 (long long)(bytespersec / 1024),
1189 (int)((bytespersec % 1024) * 10 / 1024),
1190 prefixes[bi]
1191 );
1192#else
1193 snprintf(buf, sizeof(buf),
1194 "\r%-45.45s%.*s%3d%% %4lld%c%c %3lu.%01d%cB/s",
1195 curfile,
1196 nspaces,
1197 spaces,
1198 ratio,
1199 (u_long)abbrevsize,
1200 prefixes[ai],
1201 ai == 0 ? ' ' : 'B',
1202 (u_long)(bytespersec / 1024),
1203 (int)((bytespersec % 1024) * 10 / 1024),
1204 prefixes[bi]
1205 );
1206#endif
1207
1208 if (flag != 1 &&
1209 (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {
1210 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1211 " --:-- ETA");
1212 } else if (wait.tv_sec >= STALLTIME) {
1213 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1214 " - stalled -");
1215 } else {
1216 if (flag != 1)
1217 remaining = (int)(totalbytes / (statbytes / elapsed) -
1218 elapsed);
1219 else
1220 remaining = elapsed;
1221
1222 i = remaining / 3600;
1223 if (i)
1224 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1225 "%2d:", i);
1226 else
1227 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1228 " ");
1229 i = remaining % 3600;
1230 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1231 "%02d:%02d%s", i / 60, i % 60,
1232 (flag != 1) ? " ETA" : " ");
1233 }
1234 atomicio(write, fileno(stdout), buf, strlen(buf));
1235
1236 if (flag == -1) {
1237 mysignal(SIGALRM, updateprogressmeter);
1238 alarm(PROGRESSTIME);
1239 } else if (flag == 1) {
1240 alarm(0);
1241 atomicio(write, fileno(stdout), "\n", 1);
1242 statbytes = 0;
1243 }
1244}
1245
1246int
1247getttywidth(void)
1248{
1249 struct winsize winsize;
1250
1251 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
1252 return (winsize.ws_col ? winsize.ws_col : 80);
1253 else
1254 return (80);
1255}