aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/lib/telnet.c
diff options
context:
space:
mode:
authorAlexander Smirnov <alex@ydb.tech>2024-10-16 12:11:24 +0000
committerAlexander Smirnov <alex@ydb.tech>2024-10-16 12:11:24 +0000
commit40811e93f3fdf9342a9295369994012420fac548 (patch)
treea8d85e094a9c21e10aa250f537c101fc2016a049 /contrib/libs/curl/lib/telnet.c
parent30ebe5357bb143648c6be4d151ecd4944af81ada (diff)
parent28a0c4a9f297064538a018c512cd9bbd00a1a35d (diff)
downloadydb-40811e93f3fdf9342a9295369994012420fac548.tar.gz
Merge branch 'rightlib' into mergelibs-241016-1210
Diffstat (limited to 'contrib/libs/curl/lib/telnet.c')
-rw-r--r--contrib/libs/curl/lib/telnet.c157
1 files changed, 74 insertions, 83 deletions
diff --git a/contrib/libs/curl/lib/telnet.c b/contrib/libs/curl/lib/telnet.c
index 8cd19b1b09..836e255c9d 100644
--- a/contrib/libs/curl/lib/telnet.c
+++ b/contrib/libs/curl/lib/telnet.c
@@ -160,7 +160,6 @@ struct TELNET {
unsigned short subopt_wsy; /* Set with suboption NAWS */
TelnetReceive telrcv_state;
struct curl_slist *telnet_vars; /* Environment variables */
- struct dynbuf out; /* output buffer */
/* suboptions */
unsigned char subbuffer[SUBBUFSIZE];
@@ -173,7 +172,7 @@ struct TELNET {
*/
const struct Curl_handler Curl_handler_telnet = {
- "telnet", /* scheme */
+ "TELNET", /* scheme */
ZERO_NULL, /* setup_connection */
telnet_do, /* do_it */
telnet_done, /* done */
@@ -186,8 +185,7 @@ const struct Curl_handler Curl_handler_telnet = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* write_resp */
- ZERO_NULL, /* write_resp_hd */
+ ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_TELNET, /* defport */
@@ -206,7 +204,6 @@ CURLcode init_telnet(struct Curl_easy *data)
if(!tn)
return CURLE_OUT_OF_MEMORY;
- Curl_dyn_init(&tn->out, 0xffff);
data->req.p.telnet = tn; /* make us known */
tn->telrcv_state = CURL_TS_DATA;
@@ -798,14 +795,12 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
struct TELNET *tn = data->req.p.telnet;
CURLcode result = CURLE_OK;
- /* Add the username as an environment variable if it
+ /* Add the user name as an environment variable if it
was given on the command line */
if(data->state.aptr.user) {
char buffer[256];
- if(str_is_nonascii(data->conn->user)) {
- DEBUGF(infof(data, "set a non ASCII username in telnet"));
+ if(str_is_nonascii(data->conn->user))
return CURLE_BAD_FUNCTION_ARGUMENT;
- }
msnprintf(buffer, sizeof(buffer), "USER,%s", data->conn->user);
beg = curl_slist_append(tn->telnet_vars, buffer);
if(!beg) {
@@ -831,27 +826,23 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
case 5:
/* Terminal type */
if(strncasecompare(option, "TTYPE", 5)) {
- size_t l = strlen(arg);
- if(l < sizeof(tn->subopt_ttype)) {
- strcpy(tn->subopt_ttype, arg);
- tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
- break;
- }
+ strncpy(tn->subopt_ttype, arg, 31);
+ tn->subopt_ttype[31] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
}
- result = CURLE_UNKNOWN_OPTION;
+ else
+ result = CURLE_UNKNOWN_OPTION;
break;
case 8:
/* Display variable */
if(strncasecompare(option, "XDISPLOC", 8)) {
- size_t l = strlen(arg);
- if(l < sizeof(tn->subopt_xdisploc)) {
- strcpy(tn->subopt_xdisploc, arg);
- tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
- break;
- }
+ strncpy(tn->subopt_xdisploc, arg, 127);
+ tn->subopt_xdisploc[127] = 0; /* String termination */
+ tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
}
- result = CURLE_UNKNOWN_OPTION;
+ else
+ result = CURLE_UNKNOWN_OPTION;
break;
case 7:
@@ -1191,12 +1182,12 @@ process_iac:
if(c != CURL_SE) {
if(c != CURL_IAC) {
/*
- * This is an error. We only expect to get "IAC IAC" or "IAC SE".
- * Several things may have happened. An IAC was not doubled, the
+ * This is an error. We only expect to get "IAC IAC" or "IAC SE".
+ * Several things may have happened. An IAC was not doubled, the
* IAC SE was left off, or another option got inserted into the
- * suboption are all possibilities. If we assume that the IAC was
+ * suboption are all possibilities. If we assume that the IAC was
* not doubled, and really the IAC SE was left off, we could get
- * into an infinite loop here. So, instead, we terminate the
+ * into an infinite loop here. So, instead, we terminate the
* suboption, and process the partial suboption if we can.
*/
CURL_SB_ACCUM(tn, CURL_IAC);
@@ -1232,37 +1223,37 @@ process_iac:
static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread)
{
- size_t i, outlen;
- unsigned char *outbuf;
+ ssize_t escapes, i, outlen;
+ unsigned char *outbuf = NULL;
CURLcode result = CURLE_OK;
- size_t bytes_written;
- size_t total_written = 0;
+ ssize_t bytes_written, total_written;
struct connectdata *conn = data->conn;
- struct TELNET *tn = data->req.p.telnet;
- DEBUGASSERT(tn);
- DEBUGASSERT(nread > 0);
- if(nread < 0)
- return CURLE_TOO_LARGE;
+ /* Determine size of new buffer after escaping */
+ escapes = 0;
+ for(i = 0; i < nread; i++)
+ if((unsigned char)buffer[i] == CURL_IAC)
+ escapes++;
+ outlen = nread + escapes;
- if(memchr(buffer, CURL_IAC, nread)) {
- /* only use the escape buffer when necessary */
- Curl_dyn_reset(&tn->out);
+ if(outlen == nread)
+ outbuf = (unsigned char *)buffer;
+ else {
+ ssize_t j;
+ outbuf = malloc(nread + escapes + 1);
+ if(!outbuf)
+ return CURLE_OUT_OF_MEMORY;
- for(i = 0; i < (size_t)nread && !result; i++) {
- result = Curl_dyn_addn(&tn->out, &buffer[i], 1);
- if(!result && ((unsigned char)buffer[i] == CURL_IAC))
- /* IAC is FF in hex */
- result = Curl_dyn_addn(&tn->out, "\xff", 1);
+ j = 0;
+ for(i = 0; i < nread; i++) {
+ outbuf[j++] = (unsigned char)buffer[i];
+ if((unsigned char)buffer[i] == CURL_IAC)
+ outbuf[j++] = CURL_IAC;
}
-
- outlen = Curl_dyn_len(&tn->out);
- outbuf = Curl_dyn_uptr(&tn->out);
- }
- else {
- outlen = (size_t)nread;
- outbuf = (unsigned char *)buffer;
+ outbuf[j] = '\0';
}
+
+ total_written = 0;
while(!result && total_written < outlen) {
/* Make sure socket is writable to avoid EWOULDBLOCK condition */
struct pollfd pfd[1];
@@ -1275,13 +1266,19 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
break;
default: /* write! */
bytes_written = 0;
- result = Curl_xfer_send(data, outbuf + total_written,
- outlen - total_written, FALSE, &bytes_written);
+ result = Curl_nwrite(data, FIRSTSOCKET,
+ outbuf + total_written,
+ outlen - total_written,
+ &bytes_written);
total_written += bytes_written;
break;
}
}
+ /* Free malloc copy if escaped */
+ if(outbuf != (unsigned char *)buffer)
+ free(outbuf);
+
return result;
}
@@ -1297,7 +1294,6 @@ static CURLcode telnet_done(struct Curl_easy *data,
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
- Curl_dyn_free(&tn->out);
return CURLE_OK;
}
@@ -1325,7 +1321,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
ssize_t nread;
struct curltime now;
bool keepon = TRUE;
- char buffer[4*1024];
+ char *buf = data->state.buffer;
struct TELNET *tn;
*done = TRUE; /* unconditionally */
@@ -1342,7 +1338,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
#ifdef USE_WINSOCK
/* We want to wait for both stdin and the socket. Since
- ** the select() function in Winsock only works on sockets
+ ** the select() function in winsock only works on sockets
** we have to use the WaitForMultipleObjects() call.
*/
@@ -1353,7 +1349,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
return CURLE_FAILED_INIT;
}
- /* Tell Winsock what events we want to listen to */
+ /* Tell winsock what events we want to listen to */
if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
WSACloseEvent(event_handle);
return CURLE_OK;
@@ -1370,7 +1366,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
else use the old WaitForMultipleObjects() way */
if(GetFileType(stdin_handle) == FILE_TYPE_PIPE ||
data->set.is_fread_set) {
- /* Do not wait for stdin_handle, just wait for event_handle */
+ /* Don't wait for stdin_handle, just wait for event_handle */
obj_count = 1;
/* Check stdin_handle per 100 milliseconds */
wait_timeout = 100;
@@ -1382,7 +1378,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
/* Keep on listening and act on events */
while(keepon) {
- const DWORD buf_size = (DWORD)sizeof(buffer);
+ const DWORD buf_size = (DWORD)data->set.buffer_size;
DWORD waitret = WaitForMultipleObjects(obj_count, objs,
FALSE, wait_timeout);
switch(waitret) {
@@ -1393,7 +1389,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
if(data->set.is_fread_set) {
size_t n;
/* read from user-supplied method */
- n = data->state.fread_func(buffer, 1, buf_size, data->state.in);
+ n = data->state.fread_func(buf, 1, buf_size, data->state.in);
if(n == CURL_READFUNC_ABORT) {
keepon = FALSE;
result = CURLE_READ_ERROR;
@@ -1421,7 +1417,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
if(!readfile_read)
break;
- if(!ReadFile(stdin_handle, buffer, buf_size,
+ if(!ReadFile(stdin_handle, buf, buf_size,
&readfile_read, NULL)) {
keepon = FALSE;
result = CURLE_READ_ERROR;
@@ -1429,7 +1425,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
}
- result = send_telnet_data(data, buffer, readfile_read);
+ result = send_telnet_data(data, buf, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1440,14 +1436,14 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
case WAIT_OBJECT_0 + 1:
{
- if(!ReadFile(stdin_handle, buffer, buf_size,
+ if(!ReadFile(stdin_handle, buf, buf_size,
&readfile_read, NULL)) {
keepon = FALSE;
result = CURLE_READ_ERROR;
break;
}
- result = send_telnet_data(data, buffer, readfile_read);
+ result = send_telnet_data(data, buf, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1469,8 +1465,8 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
if(events.lNetworkEvents & FD_READ) {
/* read data from network */
- result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
- /* read would have blocked. Loop again */
+ result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
+ /* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
/* returned not-zero, this an error */
@@ -1485,14 +1481,14 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
break;
}
- result = telrcv(data, (unsigned char *) buffer, nread);
+ result = telrcv(data, (unsigned char *) buf, nread);
if(result) {
keepon = FALSE;
break;
}
/* Negotiate if the peer has started negotiating,
- otherwise do not. We do not want to speak telnet with
+ otherwise don't. We don't want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
negotiate(data);
@@ -1535,28 +1531,23 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
pfd[1].events = POLLIN;
poll_cnt = 2;
interval_ms = 1 * 1000;
- if(pfd[1].fd < 0) {
- failf(data, "cannot read input");
- result = CURLE_RECV_ERROR;
- keepon = FALSE;
- }
}
while(keepon) {
DEBUGF(infof(data, "telnet_do, poll %d fds", poll_cnt));
- switch(Curl_poll(pfd, (unsigned int)poll_cnt, interval_ms)) {
+ switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
case -1: /* error, stop reading */
keepon = FALSE;
continue;
case 0: /* timeout */
pfd[0].revents = 0;
pfd[1].revents = 0;
- FALLTHROUGH();
+ /* FALLTHROUGH */
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
- result = Curl_xfer_recv(data, buffer, sizeof(buffer), &nread);
- /* read would have blocked. Loop again */
+ result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
+ /* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
/* returned not-zero, this an error */
@@ -1581,14 +1572,14 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
total_dl += nread;
result = Curl_pgrsSetDownloadCounter(data, total_dl);
if(!result)
- result = telrcv(data, (unsigned char *)buffer, nread);
+ result = telrcv(data, (unsigned char *)buf, nread);
if(result) {
keepon = FALSE;
break;
}
/* Negotiate if the peer has started negotiating,
- otherwise do not. We do not want to speak telnet with
+ otherwise don't. We don't want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
negotiate(data);
@@ -1599,12 +1590,12 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
nread = 0;
if(poll_cnt == 2) {
if(pfd[1].revents & POLLIN) { /* read from in file */
- nread = read(pfd[1].fd, buffer, sizeof(buffer));
+ nread = read(pfd[1].fd, buf, data->set.buffer_size);
}
}
else {
/* read from user-supplied method */
- nread = (int)data->state.fread_func(buffer, 1, sizeof(buffer),
+ nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size,
data->state.in);
if(nread == CURL_READFUNC_ABORT) {
keepon = FALSE;
@@ -1615,7 +1606,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
if(nread > 0) {
- result = send_telnet_data(data, buffer, nread);
+ result = send_telnet_data(data, buf, nread);
if(result) {
keepon = FALSE;
break;
@@ -1645,7 +1636,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
#endif
/* mark this as "no further transfer wanted" */
- Curl_xfer_setup_nop(data);
+ Curl_setup_transfer(data, -1, -1, FALSE, -1);
return result;
}