From 38d2afcefb3519f7e6a3b7c3afda4f5bfb67bde9 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 29 Apr 2010 00:49:04 +0200 Subject: telnet: Allow programatic use of telnet. The main change is to allow input from user-specified methods, when they are specified with CURLOPT_READFUNCTION. All calls to fflush(stdout) in telnet.c were removed, which makes using 'curl telnet://foo.com' painful since prompts and other data are not always returned to the user promptly. Use 'curl --no-buffer telnet://foo.com' instead. In general, the user should have their CURLOPT_WRITEFUNCTION do a fflush for interactive use. Also fix assumption that reading from stdin never returns < 0. Old code could crash in that case. Call progress functions in telnet main loop. Signed-off-by: Ben Greear --- lib/telnet.c | 96 +++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 27 deletions(-) (limited to 'lib/telnet.c') diff --git a/lib/telnet.c b/lib/telnet.c index 9409f4955..e7f05eb91 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -67,6 +67,7 @@ #include "sendf.h" #include "telnet.h" #include "connect.h" +#include "progress.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -962,16 +963,16 @@ CURLcode telrcv(struct connectdata *conn, struct SessionHandle *data = conn->data; struct TELNET *tn = (struct TELNET *)data->state.proto.telnet; -#define startskipping() \ - if(startwrite >= 0) { \ - result = Curl_client_write(conn, \ - CLIENTWRITE_BODY, \ - (char *)&inbuf[startwrite], \ - in-startwrite); \ - if(result != CURLE_OK) \ - return result; \ - } \ - startwrite = -1 +#define startskipping() \ + if(startwrite >= 0) { \ + result = Curl_client_write(conn, \ + CLIENTWRITE_BODY, \ + (char *)&inbuf[startwrite], \ + in-startwrite); \ + if(result != CURLE_OK) \ + return result; \ + } \ + startwrite = -1 #define writebyte() \ if(startwrite < 0) \ @@ -1206,6 +1207,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) #else int interval_ms; struct pollfd pfd[2]; + int poll_cnt; #endif int ret; ssize_t nread; @@ -1213,6 +1215,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) bool keepon = TRUE; char *buf = data->state.buffer; struct TELNET *tn; + curl_off_t total_dl = 0; + curl_off_t total_ul = 0; *done = TRUE; /* unconditionally */ @@ -1402,8 +1406,6 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) break; } - fflush(stdout); - /* Negotiate if the peer has started negotiating, otherwise don't. We don't want to speak telnet with non-telnet servers, like POP or SMTP. */ @@ -1446,27 +1448,28 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) #else pfd[0].fd = sockfd; pfd[0].events = POLLIN; - pfd[1].fd = 0; - pfd[1].events = POLLIN; - interval_ms = 1 * 1000; + + if (data->set.is_fread_set) { + poll_cnt = 1; + interval_ms = 100; /* poll user-supplied read function */ + } + else { + pfd[1].fd = 0; + pfd[1].events = POLLIN; + poll_cnt = 2; + interval_ms = 1 * 1000; + } while(keepon) { - switch (Curl_poll(pfd, 2, interval_ms)) { + switch (Curl_poll(pfd, poll_cnt, interval_ms)) { case -1: /* error, stop reading */ keepon = FALSE; continue; case 0: /* timeout */ - break; + pfd[0].revents = 0; + pfd[1].revents = 0; + /* fall through */ default: /* read! */ - if(pfd[1].revents & POLLIN) { /* read from stdin */ - nread = read(0, buf, 255); - code = send_telnet_data(conn, buf, nread); - if(code) { - keepon = FALSE; - break; - } - } - if(pfd[0].revents & POLLIN) { /* read data from network */ ret = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); @@ -1486,6 +1489,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) break; } + total_dl += nread; + Curl_pgrsSetDownloadCounter(data, total_dl); code = telrcv(conn, (unsigned char *)buf, nread); if(code) { keepon = FALSE; @@ -1500,7 +1505,39 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) tn->already_negotiated = 1; } } - } + + nread = 0; + if (poll_cnt == 2) { + if(pfd[1].revents & POLLIN) { /* read from stdin */ + nread = read(0, buf, BUFSIZE - 1); + } + } + else { + /* read from user-supplied method */ + nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in); + if (nread == CURL_READFUNC_ABORT) { + keepon = FALSE; + break; + } + if (nread == CURL_READFUNC_PAUSE) + break; + } + + if (nread > 0) { + code = send_telnet_data(conn, buf, nread); + if(code) { + keepon = FALSE; + break; + } + total_ul += nread; + Curl_pgrsSetUploadCounter(data, total_ul); + } + else if (nread < 0) + keepon = FALSE; + + break; + } /* poll switch statement */ + if(data->set.timeout) { now = Curl_tvnow(); if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { @@ -1509,6 +1546,11 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) keepon = FALSE; } } + + if(Curl_pgrsUpdate(conn)) { + code = CURLE_ABORTED_BY_CALLBACK; + break; + } } #endif /* mark this as "no further transfer wanted" */ -- cgit v1.2.3