📄 telnet.c
字号:
char varname[128]; char varval[128]; struct SessionHandle *data = conn->data; struct TELNET *tn = (struct TELNET *)conn->proto.telnet; printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2); switch (subchar = CURL_SB_GET(tn)) { case CURL_TELOPT_TTYPE: len = strlen(tn->subopt_ttype) + 4 + 2; snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE); (void)swrite(conn->firstsocket, temp, len); printsub(data, '>', &temp[2], len-2); break; case CURL_TELOPT_XDISPLOC: len = strlen(tn->subopt_xdisploc) + 4 + 2; snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE); (void)swrite(conn->firstsocket, temp, len); printsub(data, '>', &temp[2], len-2); break; case CURL_TELOPT_NEW_ENVIRON: snprintf((char *)temp, sizeof(temp), "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, CURL_TELQUAL_IS); len = 4; for(v = tn->telnet_vars;v;v = v->next) { tmplen = (strlen(v->data) + 1); /* Add the variable only if it fits */ if(len + tmplen < (int)sizeof(temp)-6) { sscanf(v->data, "%127[^,],%s", varname, varval); snprintf((char *)&temp[len], sizeof(temp) - len, "%c%s%c%s", CURL_NEW_ENV_VAR, varname, CURL_NEW_ENV_VALUE, varval); len += tmplen; } } snprintf((char *)&temp[len], sizeof(temp) - len, "%c%c", CURL_IAC, CURL_SE); len += 2; (void)swrite(conn->firstsocket, temp, len); printsub(data, '>', &temp[2], len-2); break; } return;}staticvoid telrcv(struct connectdata *conn, unsigned char *inbuf, /* Data received from socket */ int count) /* Number of bytes received */{ unsigned char c; int in = 0; struct SessionHandle *data = conn->data; struct TELNET *tn = (struct TELNET *)conn->proto.telnet; while(count--) { c = inbuf[in++]; switch (tn->telrcv_state) { case CURL_TS_CR: tn->telrcv_state = CURL_TS_DATA; if (c == '\0') { break; /* Ignore \0 after CR */ } Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1); continue; case CURL_TS_DATA: if (c == CURL_IAC) { tn->telrcv_state = CURL_TS_IAC; break; } else if(c == '\r') { tn->telrcv_state = CURL_TS_CR; } Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1); continue; case CURL_TS_IAC: process_iac: switch (c) { case CURL_WILL: tn->telrcv_state = CURL_TS_WILL; continue; case CURL_WONT: tn->telrcv_state = CURL_TS_WONT; continue; case CURL_DO: tn->telrcv_state = CURL_TS_DO; continue; case CURL_DONT: tn->telrcv_state = CURL_TS_DONT; continue; case CURL_SB: CURL_SB_CLEAR(tn); tn->telrcv_state = CURL_TS_SB; continue; case CURL_IAC: Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1); break; case CURL_DM: case CURL_NOP: case CURL_GA: default: printoption(data, "RCVD", CURL_IAC, c); break; } tn->telrcv_state = CURL_TS_DATA; continue; case CURL_TS_WILL: printoption(data, "RCVD", CURL_WILL, c); tn->please_negotiate = 1; rec_will(conn, c); tn->telrcv_state = CURL_TS_DATA; continue; case CURL_TS_WONT: printoption(data, "RCVD", CURL_WONT, c); tn->please_negotiate = 1; rec_wont(conn, c); tn->telrcv_state = CURL_TS_DATA; continue; case CURL_TS_DO: printoption(data, "RCVD", CURL_DO, c); tn->please_negotiate = 1; rec_do(conn, c); tn->telrcv_state = CURL_TS_DATA; continue; case CURL_TS_DONT: printoption(data, "RCVD", CURL_DONT, c); tn->please_negotiate = 1; rec_dont(conn, c); tn->telrcv_state = CURL_TS_DATA; continue; case CURL_TS_SB: if (c == CURL_IAC) { tn->telrcv_state = CURL_TS_SE; } else { CURL_SB_ACCUM(tn,c); } continue; case CURL_TS_SE: 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 happend. 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 not doubled, * and really the IAC SE was left off, we could * get into an infinate loop here. So, instead, * we terminate the suboption, and process the * partial suboption if we can. */ CURL_SB_ACCUM(tn, (unsigned char)CURL_IAC); CURL_SB_ACCUM(tn, c); tn->subpointer -= 2; CURL_SB_TERM(tn); printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); suboption(conn); /* handle sub-option */ tn->telrcv_state = CURL_TS_IAC; goto process_iac; } CURL_SB_ACCUM(tn,c); tn->telrcv_state = CURL_TS_SB; } else { CURL_SB_ACCUM(tn, (unsigned char)CURL_IAC); CURL_SB_ACCUM(tn, (unsigned char)CURL_SE); tn->subpointer -= 2; CURL_SB_TERM(tn); suboption(conn); /* handle sub-option */ tn->telrcv_state = CURL_TS_DATA; } break; } }}CURLcode Curl_telnet_done(struct connectdata *conn){ struct TELNET *tn = (struct TELNET *)conn->proto.telnet; curl_slist_free_all(tn->telnet_vars); free(conn->proto.telnet); conn->proto.telnet = NULL; return CURLE_OK;}CURLcode Curl_telnet(struct connectdata *conn){ CURLcode code; struct SessionHandle *data = conn->data; int sockfd = conn->firstsocket;#ifdef WIN32 WSAEVENT event_handle; WSANETWORKEVENTS events; HANDLE stdin_handle; HANDLE objs[2]; DWORD waitret;#else fd_set readfd; fd_set keepfd;#endif bool keepon = TRUE; char *buf = data->state.buffer; ssize_t nread; struct TELNET *tn; code = init_telnet(conn); if(code) return code; tn = (struct TELNET *)conn->proto.telnet; code = check_telnet_options(conn); if(code) return code;#ifdef WIN32 /* We want to wait for both stdin and the socket. Since ** the select() function in winsock only works on sockets ** we have to use the WaitForMultipleObjects() call. */ /* First, create a sockets event object */ event_handle = WSACreateEvent(); /* The get the Windows file handle for stdin */ stdin_handle = GetStdHandle(STD_INPUT_HANDLE); /* Create the list of objects to wait for */ objs[0] = stdin_handle; objs[1] = event_handle; /* Tell winsock what events we want to listen to */ if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) { return 0; } /* Keep on listening and act on events */ while(keepon) { waitret = WaitForMultipleObjects(2, objs, FALSE, INFINITE); switch(waitret - WAIT_OBJECT_0) { case 0: { unsigned char outbuf[2]; int out_count = 0; ssize_t bytes_written; char *buffer = buf; if(!ReadFile(stdin_handle, buf, 255, (LPDWORD)&nread, NULL)) { keepon = FALSE; break; } while(nread--) { outbuf[0] = *buffer++; out_count = 1; if(outbuf[0] == CURL_IAC) outbuf[out_count++] = CURL_IAC; Curl_write(conn, conn->firstsocket, outbuf, out_count, &bytes_written); } } break; case 1: if(WSAEnumNetworkEvents(sockfd, event_handle, &events) != SOCKET_ERROR) { if(events.lNetworkEvents & FD_READ) { /* This reallu OUGHT to check its return code. */ Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); telrcv(conn, (unsigned char *)buf, nread); 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. */ if(tn->please_negotiate && !tn->already_negotiated) { negotiate(conn); tn->already_negotiated = 1; } } if(events.lNetworkEvents & FD_CLOSE) { keepon = FALSE; } } break; } }#else FD_ZERO (&readfd); /* clear it */ FD_SET (sockfd, &readfd); FD_SET (0, &readfd); keepfd = readfd; while (keepon) { struct timeval interval; readfd = keepfd; /* set this every lap in the loop */ interval.tv_sec = 1; interval.tv_usec = 0; switch (select (sockfd + 1, &readfd, NULL, NULL, &interval)) { case -1: /* error, stop reading */ keepon = FALSE; continue; case 0: /* timeout */ break; default: /* read! */ if(FD_ISSET(0, &readfd)) { /* read from stdin */ unsigned char outbuf[2]; int out_count = 0; ssize_t bytes_written; char *buffer = buf; nread = read(0, buf, 255); while(nread--) { outbuf[0] = *buffer++; out_count = 1; if(outbuf[0] == CURL_IAC) outbuf[out_count++] = CURL_IAC; Curl_write(conn, conn->firstsocket, outbuf, out_count, &bytes_written); } } if(FD_ISSET(sockfd, &readfd)) { /* This OUGHT to check the return code... */ Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); /* if we receive 0 or less here, the server closed the connection and we bail out from this! */ if (nread <= 0) { keepon = FALSE; break; } telrcv(conn, (unsigned char *)buf, nread); /* 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. */ if(tn->please_negotiate && !tn->already_negotiated) { negotiate(conn); tn->already_negotiated = 1; } } } if(data->set.timeout) { struct timeval now; /* current time */ now = Curl_tvnow(); if(Curl_tvdiff(now, conn->created)/1000 >= data->set.timeout) { failf(data, "Time-out"); code = CURLE_OPERATION_TIMEOUTED; keepon = FALSE; } } }#endif /* mark this as "no further transfer wanted" */ Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL); return code;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -