1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
22 ***************************************************************************/
26 #ifndef CURL_DISABLE_TELNET
27 /* -- WIN32 approved -- */
33 #ifdef HAVE_SYS_TYPES_H
34 #include <sys/types.h>
36 #ifdef HAVE_SYS_STAT_H
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #ifdef HAVE_SYS_TIME_H
55 #ifdef HAVE_ARPA_INET_H
56 #include <arpa/inet.h>
61 #include <sys/ioctl.h>
64 #ifdef HAVE_SYS_PARAM_H
65 #include <sys/param.h>
72 #include <curl/curl.h>
78 #define _MPRINTF_REPLACE /* use our functions only */
79 #include <curl/mprintf.h>
84 #include "arpa_telnet.h"
88 /* The last #include file should be: */
91 #define SUBBUFSIZE 512
93 #define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer;
94 #define CURL_SB_TERM(x) { x->subend = x->subpointer; CURL_SB_CLEAR(x); }
95 #define CURL_SB_ACCUM(x,c) \
96 if (x->subpointer < (x->subbuffer+sizeof x->subbuffer)) { \
97 *x->subpointer++ = (c); \
100 #define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
101 #define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
102 #define CURL_SB_EOF(x) (x->subpointer >= x->subend)
103 #define CURL_SB_LEN(x) (x->subend - x->subpointer)
106 typedef FARPROC WSOCK2_FUNC;
107 static CURLcode check_wsock2 ( struct SessionHandle *data );
111 void telrcv(struct connectdata *,
112 unsigned char *inbuf, /* Data received from socket */
113 ssize_t count); /* Number of bytes received */
115 static void printoption(struct SessionHandle *data,
116 const char *direction,
117 int cmd, int option);
119 static void negotiate(struct connectdata *);
120 static void send_negotiation(struct connectdata *, int cmd, int option);
121 static void set_local_option(struct connectdata *, int cmd, int option);
122 static void set_remote_option(struct connectdata *, int cmd, int option);
124 static void printsub(struct SessionHandle *data,
125 int direction, unsigned char *pointer,
127 static void suboption(struct connectdata *);
129 /* For negotiation compliant to RFC 1143 */
132 #define CURL_WANTYES 2
133 #define CURL_WANTNO 3
136 #define CURL_OPPOSITE 1
139 * Telnet receiver states for fsm
150 CURL_TS_SB, /* sub-option collection */
151 CURL_TS_SE /* looking for sub-option end */
155 int please_negotiate;
156 int already_negotiated;
159 int us_preferred[256];
162 int him_preferred[256];
163 char subopt_ttype[32]; /* Set with suboption TTYPE */
164 char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */
165 struct curl_slist *telnet_vars; /* Environment variables */
168 unsigned char subbuffer[SUBBUFSIZE];
169 unsigned char *subpointer, *subend; /* buffer for sub-options */
171 TelnetReceive telrcv_state;
176 check_wsock2 ( struct SessionHandle *data )
179 WORD wVersionRequested;
184 /* telnet requires at least WinSock 2.0 so ask for it. */
185 wVersionRequested = MAKEWORD(2, 0);
187 err = WSAStartup(wVersionRequested, &wsaData);
189 /* We must've called this once already, so this call */
190 /* should always succeed. But, just in case... */
192 failf(data,"WSAStartup failed (%d)",err);
193 return CURLE_FAILED_INIT;
196 /* We have to have a WSACleanup call for every successful */
197 /* WSAStartup call. */
200 /* Check that our version is supported */
201 if (LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
202 HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
203 /* Our version isn't supported */
204 failf(data,"insufficient winsock version to support "
206 return CURLE_FAILED_INIT;
209 /* Our version is supported */
214 CURLcode init_telnet(struct connectdata *conn)
218 tn = (struct TELNET *)calloc(1, sizeof(struct TELNET));
220 return CURLE_OUT_OF_MEMORY;
222 conn->proto.telnet = (void *)tn; /* make us known */
224 tn->telrcv_state = CURL_TS_DATA;
226 /* Init suboptions */
229 /* Set the options we want by default */
230 tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES;
231 tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES;
232 tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES;
233 tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES;
238 static void negotiate(struct connectdata *conn)
241 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
243 for(i = 0;i < CURL_NTELOPTS;i++)
245 if(tn->us_preferred[i] == CURL_YES)
246 set_local_option(conn, i, CURL_YES);
248 if(tn->him_preferred[i] == CURL_YES)
249 set_remote_option(conn, i, CURL_YES);
253 static void printoption(struct SessionHandle *data,
254 const char *direction, int cmd, int option)
259 if (data->set.verbose)
263 if (CURL_TELCMD_OK(option))
264 infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
266 infof(data, "%s IAC %d\n", direction, option);
270 fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
271 (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
274 if (CURL_TELOPT_OK(option))
275 opt = CURL_TELOPT(option);
276 else if (option == CURL_TELOPT_EXOPL)
282 infof(data, "%s %s %s\n", direction, fmt, opt);
284 infof(data, "%s %s %d\n", direction, fmt, option);
287 infof(data, "%s %d %d\n", direction, cmd, option);
292 static void send_negotiation(struct connectdata *conn, int cmd, int option)
294 unsigned char buf[3];
295 ssize_t bytes_written;
297 struct SessionHandle *data = conn->data;
300 buf[1] = (unsigned char)cmd;
301 buf[2] = (unsigned char)option;
303 bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
304 if(bytes_written < 0) {
305 err = Curl_sockerrno();
306 failf(data,"Sending data failed (%d)",err);
309 printoption(conn->data, "SENT", cmd, option);
313 void set_remote_option(struct connectdata *conn, int option, int newstate)
315 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
316 if(newstate == CURL_YES)
318 switch(tn->him[option])
321 tn->him[option] = CURL_WANTYES;
322 send_negotiation(conn, CURL_DO, option);
326 /* Already enabled */
330 switch(tn->himq[option])
333 /* Already negotiating for CURL_YES, queue the request */
334 tn->himq[option] = CURL_OPPOSITE;
337 /* Error: already queued an enable request */
343 switch(tn->himq[option])
346 /* Error: already negotiating for enable */
349 tn->himq[option] = CURL_EMPTY;
357 switch(tn->him[option])
360 /* Already disabled */
364 tn->him[option] = CURL_WANTNO;
365 send_negotiation(conn, CURL_DONT, option);
369 switch(tn->himq[option])
372 /* Already negotiating for NO */
375 tn->himq[option] = CURL_EMPTY;
381 switch(tn->himq[option])
384 tn->himq[option] = CURL_OPPOSITE;
395 void rec_will(struct connectdata *conn, int option)
397 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
398 switch(tn->him[option])
401 if(tn->him_preferred[option] == CURL_YES)
403 tn->him[option] = CURL_YES;
404 send_negotiation(conn, CURL_DO, option);
408 send_negotiation(conn, CURL_DONT, option);
413 /* Already enabled */
417 switch(tn->himq[option])
420 /* Error: DONT answered by WILL */
421 tn->him[option] = CURL_NO;
424 /* Error: DONT answered by WILL */
425 tn->him[option] = CURL_YES;
426 tn->himq[option] = CURL_EMPTY;
432 switch(tn->himq[option])
435 tn->him[option] = CURL_YES;
438 tn->him[option] = CURL_WANTNO;
439 tn->himq[option] = CURL_EMPTY;
440 send_negotiation(conn, CURL_DONT, option);
448 void rec_wont(struct connectdata *conn, int option)
450 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
451 switch(tn->him[option])
454 /* Already disabled */
458 tn->him[option] = CURL_NO;
459 send_negotiation(conn, CURL_DONT, option);
463 switch(tn->himq[option])
466 tn->him[option] = CURL_NO;
470 tn->him[option] = CURL_WANTYES;
471 tn->himq[option] = CURL_EMPTY;
472 send_negotiation(conn, CURL_DO, option);
478 switch(tn->himq[option])
481 tn->him[option] = CURL_NO;
484 tn->him[option] = CURL_NO;
485 tn->himq[option] = CURL_EMPTY;
493 set_local_option(struct connectdata *conn, int option, int newstate)
495 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
496 if(newstate == CURL_YES)
498 switch(tn->us[option])
501 tn->us[option] = CURL_WANTYES;
502 send_negotiation(conn, CURL_WILL, option);
506 /* Already enabled */
510 switch(tn->usq[option])
513 /* Already negotiating for CURL_YES, queue the request */
514 tn->usq[option] = CURL_OPPOSITE;
517 /* Error: already queued an enable request */
523 switch(tn->usq[option])
526 /* Error: already negotiating for enable */
529 tn->usq[option] = CURL_EMPTY;
537 switch(tn->us[option])
540 /* Already disabled */
544 tn->us[option] = CURL_WANTNO;
545 send_negotiation(conn, CURL_WONT, option);
549 switch(tn->usq[option])
552 /* Already negotiating for NO */
555 tn->usq[option] = CURL_EMPTY;
561 switch(tn->usq[option])
564 tn->usq[option] = CURL_OPPOSITE;
575 void rec_do(struct connectdata *conn, int option)
577 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
578 switch(tn->us[option])
581 if(tn->us_preferred[option] == CURL_YES)
583 tn->us[option] = CURL_YES;
584 send_negotiation(conn, CURL_WILL, option);
588 send_negotiation(conn, CURL_WONT, option);
593 /* Already enabled */
597 switch(tn->usq[option])
600 /* Error: DONT answered by WILL */
601 tn->us[option] = CURL_NO;
604 /* Error: DONT answered by WILL */
605 tn->us[option] = CURL_YES;
606 tn->usq[option] = CURL_EMPTY;
612 switch(tn->usq[option])
615 tn->us[option] = CURL_YES;
618 tn->us[option] = CURL_WANTNO;
619 tn->himq[option] = CURL_EMPTY;
620 send_negotiation(conn, CURL_WONT, option);
628 void rec_dont(struct connectdata *conn, int option)
630 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
631 switch(tn->us[option])
634 /* Already disabled */
638 tn->us[option] = CURL_NO;
639 send_negotiation(conn, CURL_WONT, option);
643 switch(tn->usq[option])
646 tn->us[option] = CURL_NO;
650 tn->us[option] = CURL_WANTYES;
651 tn->usq[option] = CURL_EMPTY;
652 send_negotiation(conn, CURL_WILL, option);
658 switch(tn->usq[option])
661 tn->us[option] = CURL_NO;
664 tn->us[option] = CURL_NO;
665 tn->usq[option] = CURL_EMPTY;
673 static void printsub(struct SessionHandle *data,
674 int direction, /* '<' or '>' */
675 unsigned char *pointer, /* where suboption data is */
676 size_t length) /* length of suboption data */
680 if (data->set.verbose)
684 infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
689 i = pointer[length-2];
690 j = pointer[length-1];
692 if (i != CURL_IAC || j != CURL_SE)
694 infof(data, "(terminated by ");
695 if (CURL_TELOPT_OK(i))
696 infof(data, "%s ", CURL_TELOPT(i));
697 else if (CURL_TELCMD_OK(i))
698 infof(data, "%s ", CURL_TELCMD(i));
700 infof(data, "%d ", i);
701 if (CURL_TELOPT_OK(j))
702 infof(data, "%s", CURL_TELOPT(j));
703 else if (CURL_TELCMD_OK(j))
704 infof(data, "%s", CURL_TELCMD(j));
706 infof(data, "%d", j);
707 infof(data, ", not IAC SE!) ");
714 infof(data, "(Empty suboption?)");
718 if (CURL_TELOPT_OK(pointer[0])) {
720 case CURL_TELOPT_TTYPE:
721 case CURL_TELOPT_XDISPLOC:
722 case CURL_TELOPT_NEW_ENVIRON:
723 infof(data, "%s", CURL_TELOPT(pointer[0]));
726 infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0]));
731 infof(data, "%d (unknown)", pointer[i]);
734 case CURL_TELQUAL_IS:
737 case CURL_TELQUAL_SEND:
738 infof(data, " SEND");
740 case CURL_TELQUAL_INFO:
741 infof(data, " INFO/REPLY");
743 case CURL_TELQUAL_NAME:
744 infof(data, " NAME");
749 case CURL_TELOPT_TTYPE:
750 case CURL_TELOPT_XDISPLOC:
752 infof(data, " \"%s\"", &pointer[2]);
754 case CURL_TELOPT_NEW_ENVIRON:
755 if(pointer[1] == CURL_TELQUAL_IS) {
757 for(i = 3;i < length;i++) {
759 case CURL_NEW_ENV_VAR:
762 case CURL_NEW_ENV_VALUE:
766 infof(data, "%c", pointer[i]);
773 for (i = 2; i < length; i++)
774 infof(data, " %.2x", pointer[i]);
785 static CURLcode check_telnet_options(struct connectdata *conn)
787 struct curl_slist *head;
788 char option_keyword[128];
789 char option_arg[256];
791 struct SessionHandle *data = conn->data;
792 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
794 /* Add the user name as an environment variable if it
795 was given on the command line */
796 if(conn->bits.user_passwd)
798 snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
799 tn->telnet_vars = curl_slist_append(tn->telnet_vars, option_arg);
801 tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
804 for(head = data->set.telnet_options; head; head=head->next) {
805 if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
806 option_keyword, option_arg) == 2) {
809 if(curl_strequal(option_keyword, "TTYPE")) {
810 strncpy(tn->subopt_ttype, option_arg, 31);
811 tn->subopt_ttype[31] = 0; /* String termination */
812 tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
816 /* Display variable */
817 if(curl_strequal(option_keyword, "XDISPLOC")) {
818 strncpy(tn->subopt_xdisploc, option_arg, 127);
819 tn->subopt_xdisploc[127] = 0; /* String termination */
820 tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
824 /* Environment variable */
825 if(curl_strequal(option_keyword, "NEW_ENV")) {
826 buf = strdup(option_arg);
828 return CURLE_OUT_OF_MEMORY;
829 tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
830 tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
834 failf(data, "Unknown telnet option %s", head->data);
835 return CURLE_UNKNOWN_TELNET_OPTION;
837 failf(data, "Syntax error in telnet option: %s", head->data);
838 return CURLE_TELNET_OPTION_SYNTAX;
848 * Look at the sub-option buffer, and try to be helpful to the other
852 static void suboption(struct connectdata *conn)
854 struct curl_slist *v;
855 unsigned char temp[2048];
856 ssize_t bytes_written;
862 struct SessionHandle *data = conn->data;
863 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
865 printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
866 switch (CURL_SB_GET(tn)) {
867 case CURL_TELOPT_TTYPE:
868 len = strlen(tn->subopt_ttype) + 4 + 2;
869 snprintf((char *)temp, sizeof(temp),
870 "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
871 CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
872 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
873 if(bytes_written < 0) {
874 err = Curl_sockerrno();
875 failf(data,"Sending data failed (%d)",err);
877 printsub(data, '>', &temp[2], len-2);
879 case CURL_TELOPT_XDISPLOC:
880 len = strlen(tn->subopt_xdisploc) + 4 + 2;
881 snprintf((char *)temp, sizeof(temp),
882 "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
883 CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
884 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
885 if(bytes_written < 0) {
886 err = Curl_sockerrno();
887 failf(data,"Sending data failed (%d)",err);
889 printsub(data, '>', &temp[2], len-2);
891 case CURL_TELOPT_NEW_ENVIRON:
892 snprintf((char *)temp, sizeof(temp),
893 "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
897 for(v = tn->telnet_vars;v;v = v->next) {
898 tmplen = (strlen(v->data) + 1);
899 /* Add the variable only if it fits */
900 if(len + tmplen < (int)sizeof(temp)-6) {
901 sscanf(v->data, "%127[^,],%127s", varname, varval);
902 snprintf((char *)&temp[len], sizeof(temp) - len,
903 "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
904 CURL_NEW_ENV_VALUE, varval);
908 snprintf((char *)&temp[len], sizeof(temp) - len,
909 "%c%c", CURL_IAC, CURL_SE);
911 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
912 if(bytes_written < 0) {
913 err = Curl_sockerrno();
914 failf(data,"Sending data failed (%d)",err);
916 printsub(data, '>', &temp[2], len-2);
923 void telrcv(struct connectdata *conn,
924 unsigned char *inbuf, /* Data received from socket */
925 ssize_t count) /* Number of bytes received */
929 struct SessionHandle *data = conn->data;
930 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
936 switch (tn->telrcv_state)
939 tn->telrcv_state = CURL_TS_DATA;
942 break; /* Ignore \0 after CR */
945 Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
951 tn->telrcv_state = CURL_TS_IAC;
956 tn->telrcv_state = CURL_TS_CR;
959 Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
967 tn->telrcv_state = CURL_TS_WILL;
970 tn->telrcv_state = CURL_TS_WONT;
973 tn->telrcv_state = CURL_TS_DO;
976 tn->telrcv_state = CURL_TS_DONT;
980 tn->telrcv_state = CURL_TS_SB;
983 Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
989 printoption(data, "RCVD", CURL_IAC, c);
992 tn->telrcv_state = CURL_TS_DATA;
996 printoption(data, "RCVD", CURL_WILL, c);
997 tn->please_negotiate = 1;
999 tn->telrcv_state = CURL_TS_DATA;
1003 printoption(data, "RCVD", CURL_WONT, c);
1004 tn->please_negotiate = 1;
1006 tn->telrcv_state = CURL_TS_DATA;
1010 printoption(data, "RCVD", CURL_DO, c);
1011 tn->please_negotiate = 1;
1013 tn->telrcv_state = CURL_TS_DATA;
1017 printoption(data, "RCVD", CURL_DONT, c);
1018 tn->please_negotiate = 1;
1020 tn->telrcv_state = CURL_TS_DATA;
1026 tn->telrcv_state = CURL_TS_SE;
1030 CURL_SB_ACCUM(tn,c);
1040 * This is an error. We only expect to get "IAC IAC" or "IAC SE".
1041 * Several things may have happend. An IAC was not doubled, the
1042 * IAC SE was left off, or another option got inserted into the
1043 * suboption are all possibilities. If we assume that the IAC was
1044 * not doubled, and really the IAC SE was left off, we could get
1045 * into an infinate loop here. So, instead, we terminate the
1046 * suboption, and process the partial suboption if we can.
1048 CURL_SB_ACCUM(tn, CURL_IAC);
1049 CURL_SB_ACCUM(tn, c);
1050 tn->subpointer -= 2;
1053 printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
1054 suboption(conn); /* handle sub-option */
1055 tn->telrcv_state = CURL_TS_IAC;
1058 CURL_SB_ACCUM(tn,c);
1059 tn->telrcv_state = CURL_TS_SB;
1063 CURL_SB_ACCUM(tn, CURL_IAC);
1064 CURL_SB_ACCUM(tn, CURL_SE);
1065 tn->subpointer -= 2;
1067 suboption(conn); /* handle sub-option */
1068 tn->telrcv_state = CURL_TS_DATA;
1075 CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status)
1077 struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
1078 (void)status; /* unused */
1080 curl_slist_free_all(tn->telnet_vars);
1082 free(conn->proto.telnet);
1083 conn->proto.telnet = NULL;
1088 CURLcode Curl_telnet(struct connectdata *conn, bool *done)
1091 struct SessionHandle *data = conn->data;
1092 curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
1095 WSOCK2_FUNC close_event_func;
1096 WSOCK2_FUNC create_event_func;
1097 WSOCK2_FUNC event_select_func;
1098 WSOCK2_FUNC enum_netevents_func;
1099 WSAEVENT event_handle;
1100 WSANETWORKEVENTS events;
1101 HANDLE stdin_handle;
1106 DWORD readfile_read;
1109 struct pollfd pfd[2];
1113 char *buf = data->state.buffer;
1116 *done = TRUE; /* uncontionally */
1118 code = init_telnet(conn);
1122 tn = (struct TELNET *)conn->proto.telnet;
1124 code = check_telnet_options(conn);
1130 ** This functionality only works with WinSock >= 2.0. So,
1131 ** make sure have it.
1133 code = check_wsock2(data);
1137 /* OK, so we have WinSock 2.0. We need to dynamically */
1138 /* load ws2_32.dll and get the function pointers we need. */
1139 wsock2 = LoadLibrary("WS2_32.DLL");
1140 if (wsock2 == NULL) {
1141 failf(data,"failed to load WS2_32.DLL (%d)",GetLastError());
1142 return CURLE_FAILED_INIT;
1145 /* Grab a pointer to WSACreateEvent */
1146 create_event_func = GetProcAddress(wsock2,"WSACreateEvent");
1147 if (create_event_func == NULL) {
1148 failf(data,"failed to find WSACreateEvent function (%d)",
1150 FreeLibrary(wsock2);
1151 return CURLE_FAILED_INIT;
1154 /* And WSACloseEvent */
1155 close_event_func = GetProcAddress(wsock2,"WSACloseEvent");
1156 if (create_event_func == NULL) {
1157 failf(data,"failed to find WSACloseEvent function (%d)",
1159 FreeLibrary(wsock2);
1160 return CURLE_FAILED_INIT;
1163 /* And WSAEventSelect */
1164 event_select_func = GetProcAddress(wsock2,"WSAEventSelect");
1165 if (event_select_func == NULL) {
1166 failf(data,"failed to find WSAEventSelect function (%d)",
1168 FreeLibrary(wsock2);
1169 return CURLE_FAILED_INIT;
1172 /* And WSAEnumNetworkEvents */
1173 enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents");
1174 if (enum_netevents_func == NULL) {
1175 failf(data,"failed to find WSAEnumNetworkEvents function (%d)",
1177 FreeLibrary(wsock2);
1178 return CURLE_FAILED_INIT;
1181 /* We want to wait for both stdin and the socket. Since
1182 ** the select() function in winsock only works on sockets
1183 ** we have to use the WaitForMultipleObjects() call.
1186 /* First, create a sockets event object */
1187 event_handle = (WSAEVENT)create_event_func();
1188 if (event_handle == WSA_INVALID_EVENT) {
1189 failf(data,"WSACreateEvent failed (%d)",WSAGetLastError());
1190 FreeLibrary(wsock2);
1191 return CURLE_FAILED_INIT;
1194 /* The get the Windows file handle for stdin */
1195 stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
1197 /* Create the list of objects to wait for */
1198 objs[0] = event_handle;
1199 objs[1] = stdin_handle;
1201 /* Tell winsock what events we want to listen to */
1202 if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
1203 close_event_func(event_handle);
1204 FreeLibrary(wsock2);
1208 /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
1209 else use the old WaitForMultipleObjects() way */
1210 if(GetFileType(stdin_handle) == FILE_TYPE_PIPE) {
1211 /* Don't wait for stdin_handle, just wait for event_handle */
1213 /* Check stdin_handle per 100 milliseconds */
1217 wait_timeout = INFINITE;
1220 /* Keep on listening and act on events */
1222 waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
1226 unsigned char outbuf[2];
1228 ssize_t bytes_written;
1232 if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
1236 nread = readfile_read;
1241 if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
1242 &readfile_read, NULL)) {
1246 nread = readfile_read;
1249 outbuf[0] = *buffer++;
1251 if(outbuf[0] == CURL_IAC)
1252 outbuf[out_count++] = CURL_IAC;
1254 Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
1255 out_count, &bytes_written);
1261 case WAIT_OBJECT_0 + 1:
1263 unsigned char outbuf[2];
1265 ssize_t bytes_written;
1268 if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
1269 &readfile_read, NULL)) {
1273 nread = readfile_read;
1276 outbuf[0] = *buffer++;
1278 if(outbuf[0] == CURL_IAC)
1279 outbuf[out_count++] = CURL_IAC;
1281 Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
1282 out_count, &bytes_written);
1288 if(enum_netevents_func(sockfd, event_handle, &events)
1290 if(events.lNetworkEvents & FD_READ) {
1291 /* This reallu OUGHT to check its return code. */
1292 (void)Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
1294 telrcv(conn, (unsigned char *)buf, nread);
1298 /* Negotiate if the peer has started negotiating,
1299 otherwise don't. We don't want to speak telnet with
1300 non-telnet servers, like POP or SMTP. */
1301 if(tn->please_negotiate && !tn->already_negotiated) {
1303 tn->already_negotiated = 1;
1307 if(events.lNetworkEvents & FD_CLOSE) {
1315 /* We called WSACreateEvent, so call WSACloseEvent */
1316 if (close_event_func(event_handle) == FALSE) {
1317 infof(data,"WSACloseEvent failed (%d)",WSAGetLastError());
1320 /* "Forget" pointers into the library we're about to free */
1321 create_event_func = NULL;
1322 close_event_func = NULL;
1323 event_select_func = NULL;
1324 enum_netevents_func = NULL;
1326 /* We called LoadLibrary, so call FreeLibrary */
1327 if (!FreeLibrary(wsock2))
1328 infof(data,"FreeLibrary(wsock2) failed (%d)",GetLastError());
1331 pfd[0].events = POLLIN;
1333 pfd[1].events = POLLIN;
1334 interval_ms = 1 * 1000;
1337 switch (Curl_poll(pfd, 2, interval_ms)) {
1338 case -1: /* error, stop reading */
1341 case 0: /* timeout */
1343 default: /* read! */
1344 if(pfd[1].revents & POLLIN) { /* read from stdin */
1345 unsigned char outbuf[2];
1347 ssize_t bytes_written;
1350 nread = read(0, buf, 255);
1353 outbuf[0] = *buffer++;
1355 if(outbuf[0] == CURL_IAC)
1356 outbuf[out_count++] = CURL_IAC;
1358 Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
1359 out_count, &bytes_written);
1363 if(pfd[0].revents & POLLIN) {
1364 /* This OUGHT to check the return code... */
1365 (void)Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
1367 /* if we receive 0 or less here, the server closed the connection and
1368 we bail out from this! */
1374 telrcv(conn, (unsigned char *)buf, nread);
1376 /* Negotiate if the peer has started negotiating,
1377 otherwise don't. We don't want to speak telnet with
1378 non-telnet servers, like POP or SMTP. */
1379 if(tn->please_negotiate && !tn->already_negotiated) {
1381 tn->already_negotiated = 1;
1385 if(data->set.timeout) {
1386 struct timeval now; /* current time */
1388 if(Curl_tvdiff(now, conn->created)/1000 >= data->set.timeout) {
1389 failf(data, "Time-out");
1390 code = CURLE_OPERATION_TIMEOUTED;
1396 /* mark this as "no further transfer wanted" */
1397 Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);