diff options
Diffstat (limited to 'scp.c')
-rw-r--r-- | scp.c | 211 |
1 files changed, 10 insertions, 201 deletions
@@ -75,13 +75,14 @@ | |||
75 | */ | 75 | */ |
76 | 76 | ||
77 | #include "includes.h" | 77 | #include "includes.h" |
78 | RCSID("$OpenBSD: scp.c,v 1.96 2002/12/13 15:20:52 markus Exp $"); | 78 | RCSID("$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 |
87 | extern char *__progname; | 88 | extern char *__progname; |
@@ -89,30 +90,9 @@ extern char *__progname; | |||
89 | char *__progname; | 90 | char *__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. */ | ||
98 | void progressmeter(int); | ||
99 | |||
100 | /* Returns width of the terminal (for progress meter calculations). */ | ||
101 | int getttywidth(void); | ||
102 | int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); | ||
103 | |||
104 | /* Struct for addargs */ | 93 | /* Struct for addargs */ |
105 | arglist args; | 94 | arglist args; |
106 | 95 | ||
107 | /* Time a transfer started. */ | ||
108 | static struct timeval start; | ||
109 | |||
110 | /* Number of bytes of current file transferred so far. */ | ||
111 | volatile off_t statbytes; | ||
112 | |||
113 | /* Total size of current file. */ | ||
114 | off_t totalbytes = 0; | ||
115 | |||
116 | /* Name of current file being transferred. */ | 96 | /* Name of current file being transferred. */ |
117 | char *curfile; | 97 | char *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)); | |||
578 | next: (void) close(fd); | 558 | next: (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 | |||
1090 | static void | ||
1091 | updateprogressmeter(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 | |||
1101 | static int | ||
1102 | foregroundproc(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 | |||
1119 | void | ||
1120 | progressmeter(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 | |||
1246 | int | ||
1247 | getttywidth(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 | } | ||