X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=scp.c;h=6353691ba7ca4f10bf061c701128492bf731a50d;hb=9c5951ed35cf9019bf17685b4356212eae1a63b3;hp=dcf80b2fc0bfe007823c079534464db110acd3c7;hpb=52a688abd1a9f3e1b7b5349f27407f1304aa5401;p=PuTTY.git diff --git a/scp.c b/scp.c index dcf80b2f..6353691b 100644 --- a/scp.c +++ b/scp.c @@ -53,6 +53,7 @@ static int preserve = 0; static int targetshouldbedirectory = 0; static int statistics = 1; static int portnumber = 0; +static int prev_stats_len = 0; static char *password = NULL; static int errs = 0; /* GUI Adaptation - Sept 2000 */ @@ -74,6 +75,12 @@ static void tell_user(FILE * stream, char *fmt, ...); static void gui_update_stats(char *name, unsigned long size, int percentage, unsigned long elapsed); +/* + * The maximum amount of queued data we accept before we stop and + * wait for the server to process some. + */ +#define MAX_SCP_BUFSIZE 16384 + void logevent(char *string) { } @@ -165,6 +172,46 @@ void verify_ssh_host_key(char *host, int port, char *keytype, } } +/* + * Ask whether the selected cipher is acceptable (since it was + * below the configured 'warn' threshold). + * cs: 0 = both ways, 1 = client->server, 2 = server->client + */ +void askcipher(char *ciphername, int cs) +{ + HANDLE hin; + DWORD savemode, i; + + static const char msg[] = + "The first %scipher supported by the server is\n" + "%s, which is below the configured warning threshold.\n" + "Continue with connection? (y/n) "; + static const char abandoned[] = "Connection abandoned.\n"; + + char line[32]; + + fprintf(stderr, msg, + (cs == 0) ? "" : + (cs == 1) ? "client-to-server " : + "server-to-client ", + ciphername); + fflush(stderr); + + hin = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hin, &savemode); + SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT | + ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)); + ReadFile(hin, line, sizeof(line) - 1, &i, NULL); + SetConsoleMode(hin, savemode); + + if (line[0] == 'y' || line[0] == 'Y') { + return; + } else { + fprintf(stderr, abandoned); + exit(0); + } +} + /* GUI Adaptation - Sept 2000 */ static void send_msg(HWND h, UINT message, WPARAM wParam) { @@ -308,7 +355,7 @@ static unsigned char *outptr; /* where to put the data */ static unsigned outlen; /* how much data required */ static unsigned char *pending = NULL; /* any spare data */ static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */ -void from_backend(int is_stderr, char *data, int datalen) +int from_backend(int is_stderr, char *data, int datalen) { unsigned char *p = (unsigned char *) data; unsigned len = (unsigned) datalen; @@ -319,7 +366,7 @@ void from_backend(int is_stderr, char *data, int datalen) */ if (is_stderr) { fwrite(data, 1, len, stderr); - return; + return 0; } inbuf_head = 0; @@ -328,7 +375,7 @@ void from_backend(int is_stderr, char *data, int datalen) * If this is before the real session begins, just return. */ if (!outptr) - return; + return 0; if (outlen > 0) { unsigned used = outlen; @@ -352,6 +399,19 @@ void from_backend(int is_stderr, char *data, int datalen) memcpy(pending + pendlen, p, len); pendlen += len; } + + return 0; +} +static int scp_process_network_event(void) +{ + fd_set readfds; + + FD_ZERO(&readfds); + FD_SET(scp_ssh_socket, &readfds); + if (select(1, &readfds, NULL, NULL, NULL) < 0) + return 0; /* doom */ + select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ); + return 1; } static int ssh_scp_recv(unsigned char *buf, int len) { @@ -381,13 +441,8 @@ static int ssh_scp_recv(unsigned char *buf, int len) } while (outlen > 0) { - fd_set readfds; - - FD_ZERO(&readfds); - FD_SET(scp_ssh_socket, &readfds); - if (select(1, &readfds, NULL, NULL, NULL) < 0) + if (!scp_process_network_event()) return 0; /* doom */ - select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ); } return len; @@ -566,6 +621,7 @@ static void print_stats(char *name, unsigned long size, unsigned long done, unsigned long eta; char etastr[10]; int pct; + int len; /* GUI Adaptation - Sept 2000 */ if (gui_mode) @@ -586,8 +642,11 @@ static void print_stats(char *name, unsigned long size, unsigned long done, pct = (int) (100.0 * (float) done / size); - printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%", - name, done / 1024, ratebs / 1024.0, etastr, pct); + len = printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%", + name, done / 1024, ratebs / 1024.0, etastr, pct); + if (len < prev_stats_len) + printf("%*s", prev_stats_len - len, ""); + prev_stats_len = len; if (done == size) printf("\n"); @@ -754,6 +813,8 @@ static void source(char *src) for (i = 0; i < size; i += 4096) { char transbuf[4096]; DWORD j, k = 4096; + int bufsize; + if (i + k > size) k = size - i; if (!ReadFile(f, transbuf, k, &j, NULL) || j != k) { @@ -761,7 +822,7 @@ static void source(char *src) printf("\n"); bump("%s: Read error", src); } - back->send(transbuf, k); + bufsize = back->send(transbuf, k); if (statistics) { stat_bytes += k; if (time(NULL) != stat_lasttime || i + k == size) { @@ -770,6 +831,18 @@ static void source(char *src) stat_starttime, stat_lasttime); } } + + /* + * If the network transfer is backing up - that is, the + * remote site is not accepting data as fast as we can + * produce it - then we must loop on network events until + * we have space in the buffer again. + */ + while (bufsize > MAX_SCP_BUFSIZE) { + if (!scp_process_network_event()) + bump("%s: Network error occurred", src); + bufsize = back->sendbuffer(); + } } CloseHandle(f);