Git init
[external/curl.git] / lib / telnet.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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.
13  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 #include "setup.h"
24
25 #ifndef CURL_DISABLE_TELNET
26 /* -- WIN32 approved -- */
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32
33 #if defined(WIN32)
34 #include <time.h>
35 #include <io.h>
36 #else
37 #ifdef HAVE_SYS_SOCKET_H
38 #include <sys/socket.h>
39 #endif
40 #include <netinet/in.h>
41 #ifdef HAVE_SYS_TIME_H
42 #include <sys/time.h>
43 #endif
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 #include <netdb.h>
48 #ifdef HAVE_ARPA_INET_H
49 #include <arpa/inet.h>
50 #endif
51 #ifdef HAVE_NET_IF_H
52 #include <net/if.h>
53 #endif
54 #ifdef HAVE_SYS_IOCTL_H
55 #include <sys/ioctl.h>
56 #endif
57
58 #ifdef HAVE_SYS_PARAM_H
59 #include <sys/param.h>
60 #endif
61
62 #endif  /* WIN32 */
63
64 #include "urldata.h"
65 #include <curl/curl.h>
66 #include "transfer.h"
67 #include "sendf.h"
68 #include "telnet.h"
69 #include "connect.h"
70 #include "progress.h"
71
72 #define _MPRINTF_REPLACE /* use our functions only */
73 #include <curl/mprintf.h>
74
75 #define  TELOPTS
76 #define  TELCMDS
77
78 #include "arpa_telnet.h"
79 #include "curl_memory.h"
80 #include "select.h"
81 #include "strequal.h"
82 #include "rawstr.h"
83
84 /* The last #include file should be: */
85 #include "memdebug.h"
86
87 #define SUBBUFSIZE 512
88
89 #define CURL_SB_CLEAR(x)  x->subpointer = x->subbuffer;
90 #define CURL_SB_TERM(x)   { x->subend = x->subpointer; CURL_SB_CLEAR(x); }
91 #define CURL_SB_ACCUM(x,c) \
92   if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) { \
93     *x->subpointer++ = (c); \
94   }
95
96 #define  CURL_SB_GET(x) ((*x->subpointer++)&0xff)
97 #define  CURL_SB_PEEK(x)   ((*x->subpointer)&0xff)
98 #define  CURL_SB_EOF(x) (x->subpointer >= x->subend)
99 #define  CURL_SB_LEN(x) (x->subend - x->subpointer)
100
101 #ifdef CURL_DISABLE_VERBOSE_STRINGS
102 #define printoption(a,b,c,d)  do { } while(0)
103 #endif
104
105 #ifdef USE_WINSOCK
106 typedef FARPROC WSOCK2_FUNC;
107 static CURLcode check_wsock2 ( struct SessionHandle *data );
108 #endif
109
110 static
111 CURLcode telrcv(struct connectdata *,
112                 const unsigned char *inbuf, /* Data received from socket */
113                 ssize_t count);             /* Number of bytes received */
114
115 #ifndef CURL_DISABLE_VERBOSE_STRINGS
116 static void printoption(struct SessionHandle *data,
117                         const char *direction,
118                         int cmd, int option);
119 #endif
120
121 static void negotiate(struct connectdata *);
122 static void send_negotiation(struct connectdata *, int cmd, int option);
123 static void set_local_option(struct connectdata *, int cmd, int option);
124 static void set_remote_option(struct connectdata *, int cmd, int option);
125
126 static void printsub(struct SessionHandle *data,
127                      int direction, unsigned char *pointer,
128                      size_t length);
129 static void suboption(struct connectdata *);
130
131 static CURLcode telnet_do(struct connectdata *conn, bool *done);
132 static CURLcode telnet_done(struct connectdata *conn,
133                                  CURLcode, bool premature);
134
135 /* For negotiation compliant to RFC 1143 */
136 #define CURL_NO          0
137 #define CURL_YES         1
138 #define CURL_WANTYES     2
139 #define CURL_WANTNO      3
140
141 #define CURL_EMPTY       0
142 #define CURL_OPPOSITE    1
143
144 /*
145  * Telnet receiver states for fsm
146  */
147 typedef enum
148 {
149    CURL_TS_DATA = 0,
150    CURL_TS_IAC,
151    CURL_TS_WILL,
152    CURL_TS_WONT,
153    CURL_TS_DO,
154    CURL_TS_DONT,
155    CURL_TS_CR,
156    CURL_TS_SB,   /* sub-option collection */
157    CURL_TS_SE   /* looking for sub-option end */
158 } TelnetReceive;
159
160 struct TELNET {
161   int please_negotiate;
162   int already_negotiated;
163   int us[256];
164   int usq[256];
165   int us_preferred[256];
166   int him[256];
167   int himq[256];
168   int him_preferred[256];
169   char subopt_ttype[32];             /* Set with suboption TTYPE */
170   char subopt_xdisploc[128];          /* Set with suboption XDISPLOC */
171   struct curl_slist *telnet_vars; /* Environment variables */
172
173   /* suboptions */
174   unsigned char subbuffer[SUBBUFSIZE];
175   unsigned char *subpointer, *subend;      /* buffer for sub-options */
176
177   TelnetReceive telrcv_state;
178 };
179
180
181 /*
182  * TELNET protocol handler.
183  */
184
185 const struct Curl_handler Curl_handler_telnet = {
186   "TELNET",                             /* scheme */
187   ZERO_NULL,                            /* setup_connection */
188   telnet_do,                            /* do_it */
189   telnet_done,                          /* done */
190   ZERO_NULL,                            /* do_more */
191   ZERO_NULL,                            /* connect_it */
192   ZERO_NULL,                            /* connecting */
193   ZERO_NULL,                            /* doing */
194   ZERO_NULL,                            /* proto_getsock */
195   ZERO_NULL,                            /* doing_getsock */
196   ZERO_NULL,                            /* perform_getsock */
197   ZERO_NULL,                            /* disconnect */
198   PORT_TELNET,                          /* defport */
199   PROT_TELNET                           /* protocol */
200 };
201
202
203 #ifdef USE_WINSOCK
204 static CURLcode
205 check_wsock2 ( struct SessionHandle *data )
206 {
207   int err;
208   WORD wVersionRequested;
209   WSADATA wsaData;
210
211   DEBUGASSERT(data);
212
213   /* telnet requires at least WinSock 2.0 so ask for it. */
214   wVersionRequested = MAKEWORD(2, 0);
215
216   err = WSAStartup(wVersionRequested, &wsaData);
217
218   /* We must've called this once already, so this call */
219   /* should always succeed.  But, just in case... */
220   if(err != 0) {
221     failf(data,"WSAStartup failed (%d)",err);
222     return CURLE_FAILED_INIT;
223   }
224
225   /* We have to have a WSACleanup call for every successful */
226   /* WSAStartup call. */
227   WSACleanup();
228
229   /* Check that our version is supported */
230   if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
231       HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
232       /* Our version isn't supported */
233       failf(data,"insufficient winsock version to support "
234             "telnet");
235       return CURLE_FAILED_INIT;
236   }
237
238   /* Our version is supported */
239   return CURLE_OK;
240 }
241 #endif
242
243 static
244 CURLcode init_telnet(struct connectdata *conn)
245 {
246   struct TELNET *tn;
247
248   tn = calloc(1, sizeof(struct TELNET));
249   if(!tn)
250     return CURLE_OUT_OF_MEMORY;
251
252   conn->data->state.proto.telnet = (void *)tn; /* make us known */
253
254   tn->telrcv_state = CURL_TS_DATA;
255
256   /* Init suboptions */
257   CURL_SB_CLEAR(tn);
258
259   /* Set the options we want by default */
260   tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES;
261   tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES;
262   tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES;
263   tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES;
264
265   return CURLE_OK;
266 }
267
268 static void negotiate(struct connectdata *conn)
269 {
270   int i;
271   struct TELNET *tn = (struct TELNET *) conn->data->state.proto.telnet;
272
273   for(i = 0;i < CURL_NTELOPTS;i++)
274   {
275     if(tn->us_preferred[i] == CURL_YES)
276       set_local_option(conn, i, CURL_YES);
277
278     if(tn->him_preferred[i] == CURL_YES)
279       set_remote_option(conn, i, CURL_YES);
280   }
281 }
282
283 #ifndef CURL_DISABLE_VERBOSE_STRINGS
284 static void printoption(struct SessionHandle *data,
285                         const char *direction, int cmd, int option)
286 {
287   const char *fmt;
288   const char *opt;
289
290   if(data->set.verbose)
291   {
292     if(cmd == CURL_IAC)
293     {
294       if(CURL_TELCMD_OK(option))
295         infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
296       else
297         infof(data, "%s IAC %d\n", direction, option);
298     }
299     else
300     {
301       fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
302         (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
303       if(fmt)
304       {
305         if(CURL_TELOPT_OK(option))
306           opt = CURL_TELOPT(option);
307         else if(option == CURL_TELOPT_EXOPL)
308           opt = "EXOPL";
309         else
310           opt = NULL;
311
312         if(opt)
313           infof(data, "%s %s %s\n", direction, fmt, opt);
314         else
315           infof(data, "%s %s %d\n", direction, fmt, option);
316       }
317       else
318         infof(data, "%s %d %d\n", direction, cmd, option);
319     }
320   }
321 }
322 #endif
323
324 static void send_negotiation(struct connectdata *conn, int cmd, int option)
325 {
326    unsigned char buf[3];
327    ssize_t bytes_written;
328    int err;
329    struct SessionHandle *data = conn->data;
330
331    buf[0] = CURL_IAC;
332    buf[1] = (unsigned char)cmd;
333    buf[2] = (unsigned char)option;
334
335    bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
336    if(bytes_written < 0) {
337      err = SOCKERRNO;
338      failf(data,"Sending data failed (%d)",err);
339    }
340
341    printoption(conn->data, "SENT", cmd, option);
342 }
343
344 static
345 void set_remote_option(struct connectdata *conn, int option, int newstate)
346 {
347   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
348   if(newstate == CURL_YES)
349   {
350     switch(tn->him[option])
351     {
352       case CURL_NO:
353         tn->him[option] = CURL_WANTYES;
354         send_negotiation(conn, CURL_DO, option);
355         break;
356
357       case CURL_YES:
358         /* Already enabled */
359         break;
360
361       case CURL_WANTNO:
362         switch(tn->himq[option])
363         {
364           case CURL_EMPTY:
365             /* Already negotiating for CURL_YES, queue the request */
366             tn->himq[option] = CURL_OPPOSITE;
367             break;
368           case CURL_OPPOSITE:
369             /* Error: already queued an enable request */
370             break;
371         }
372         break;
373
374       case CURL_WANTYES:
375         switch(tn->himq[option])
376         {
377           case CURL_EMPTY:
378             /* Error: already negotiating for enable */
379             break;
380           case CURL_OPPOSITE:
381             tn->himq[option] = CURL_EMPTY;
382             break;
383         }
384         break;
385     }
386   }
387   else /* NO */
388   {
389     switch(tn->him[option])
390     {
391       case CURL_NO:
392         /* Already disabled */
393         break;
394
395       case CURL_YES:
396         tn->him[option] = CURL_WANTNO;
397         send_negotiation(conn, CURL_DONT, option);
398         break;
399
400       case CURL_WANTNO:
401         switch(tn->himq[option])
402         {
403           case CURL_EMPTY:
404             /* Already negotiating for NO */
405             break;
406           case CURL_OPPOSITE:
407             tn->himq[option] = CURL_EMPTY;
408             break;
409         }
410         break;
411
412       case CURL_WANTYES:
413         switch(tn->himq[option])
414         {
415           case CURL_EMPTY:
416             tn->himq[option] = CURL_OPPOSITE;
417             break;
418           case CURL_OPPOSITE:
419             break;
420         }
421         break;
422     }
423   }
424 }
425
426 static
427 void rec_will(struct connectdata *conn, int option)
428 {
429   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
430   switch(tn->him[option])
431   {
432     case CURL_NO:
433       if(tn->him_preferred[option] == CURL_YES)
434       {
435         tn->him[option] = CURL_YES;
436         send_negotiation(conn, CURL_DO, option);
437       }
438       else
439       {
440         send_negotiation(conn, CURL_DONT, option);
441       }
442       break;
443
444     case CURL_YES:
445       /* Already enabled */
446       break;
447
448     case CURL_WANTNO:
449       switch(tn->himq[option])
450       {
451         case CURL_EMPTY:
452           /* Error: DONT answered by WILL */
453           tn->him[option] = CURL_NO;
454           break;
455         case CURL_OPPOSITE:
456           /* Error: DONT answered by WILL */
457           tn->him[option] = CURL_YES;
458           tn->himq[option] = CURL_EMPTY;
459           break;
460       }
461       break;
462
463     case CURL_WANTYES:
464       switch(tn->himq[option])
465       {
466         case CURL_EMPTY:
467           tn->him[option] = CURL_YES;
468           break;
469         case CURL_OPPOSITE:
470           tn->him[option] = CURL_WANTNO;
471           tn->himq[option] = CURL_EMPTY;
472           send_negotiation(conn, CURL_DONT, option);
473           break;
474       }
475       break;
476   }
477 }
478
479 static
480 void rec_wont(struct connectdata *conn, int option)
481 {
482   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
483   switch(tn->him[option])
484   {
485     case CURL_NO:
486       /* Already disabled */
487       break;
488
489     case CURL_YES:
490       tn->him[option] = CURL_NO;
491       send_negotiation(conn, CURL_DONT, option);
492       break;
493
494     case CURL_WANTNO:
495       switch(tn->himq[option])
496       {
497         case CURL_EMPTY:
498           tn->him[option] = CURL_NO;
499           break;
500
501         case CURL_OPPOSITE:
502           tn->him[option] = CURL_WANTYES;
503           tn->himq[option] = CURL_EMPTY;
504           send_negotiation(conn, CURL_DO, option);
505           break;
506       }
507       break;
508
509     case CURL_WANTYES:
510       switch(tn->himq[option])
511       {
512         case CURL_EMPTY:
513           tn->him[option] = CURL_NO;
514           break;
515         case CURL_OPPOSITE:
516           tn->him[option] = CURL_NO;
517           tn->himq[option] = CURL_EMPTY;
518           break;
519       }
520       break;
521   }
522 }
523
524 static void
525 set_local_option(struct connectdata *conn, int option, int newstate)
526 {
527   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
528   if(newstate == CURL_YES)
529   {
530     switch(tn->us[option])
531     {
532       case CURL_NO:
533         tn->us[option] = CURL_WANTYES;
534         send_negotiation(conn, CURL_WILL, option);
535         break;
536
537       case CURL_YES:
538         /* Already enabled */
539         break;
540
541       case CURL_WANTNO:
542         switch(tn->usq[option])
543         {
544           case CURL_EMPTY:
545             /* Already negotiating for CURL_YES, queue the request */
546             tn->usq[option] = CURL_OPPOSITE;
547             break;
548           case CURL_OPPOSITE:
549             /* Error: already queued an enable request */
550             break;
551         }
552         break;
553
554       case CURL_WANTYES:
555         switch(tn->usq[option])
556         {
557           case CURL_EMPTY:
558             /* Error: already negotiating for enable */
559             break;
560           case CURL_OPPOSITE:
561             tn->usq[option] = CURL_EMPTY;
562             break;
563         }
564         break;
565     }
566   }
567   else /* NO */
568   {
569     switch(tn->us[option])
570     {
571       case CURL_NO:
572         /* Already disabled */
573         break;
574
575       case CURL_YES:
576         tn->us[option] = CURL_WANTNO;
577         send_negotiation(conn, CURL_WONT, option);
578         break;
579
580       case CURL_WANTNO:
581         switch(tn->usq[option])
582         {
583           case CURL_EMPTY:
584             /* Already negotiating for NO */
585             break;
586           case CURL_OPPOSITE:
587             tn->usq[option] = CURL_EMPTY;
588             break;
589         }
590         break;
591
592       case CURL_WANTYES:
593         switch(tn->usq[option])
594         {
595           case CURL_EMPTY:
596             tn->usq[option] = CURL_OPPOSITE;
597             break;
598           case CURL_OPPOSITE:
599             break;
600         }
601         break;
602     }
603   }
604 }
605
606 static
607 void rec_do(struct connectdata *conn, int option)
608 {
609   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
610   switch(tn->us[option])
611   {
612     case CURL_NO:
613       if(tn->us_preferred[option] == CURL_YES)
614       {
615         tn->us[option] = CURL_YES;
616         send_negotiation(conn, CURL_WILL, option);
617       }
618       else
619       {
620         send_negotiation(conn, CURL_WONT, option);
621       }
622       break;
623
624     case CURL_YES:
625       /* Already enabled */
626       break;
627
628     case CURL_WANTNO:
629       switch(tn->usq[option])
630       {
631         case CURL_EMPTY:
632           /* Error: DONT answered by WILL */
633           tn->us[option] = CURL_NO;
634           break;
635         case CURL_OPPOSITE:
636           /* Error: DONT answered by WILL */
637           tn->us[option] = CURL_YES;
638           tn->usq[option] = CURL_EMPTY;
639           break;
640       }
641       break;
642
643     case CURL_WANTYES:
644       switch(tn->usq[option])
645       {
646         case CURL_EMPTY:
647           tn->us[option] = CURL_YES;
648           break;
649         case CURL_OPPOSITE:
650           tn->us[option] = CURL_WANTNO;
651           tn->himq[option] = CURL_EMPTY;
652           send_negotiation(conn, CURL_WONT, option);
653           break;
654       }
655       break;
656   }
657 }
658
659 static
660 void rec_dont(struct connectdata *conn, int option)
661 {
662   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
663   switch(tn->us[option])
664   {
665     case CURL_NO:
666       /* Already disabled */
667       break;
668
669     case CURL_YES:
670       tn->us[option] = CURL_NO;
671       send_negotiation(conn, CURL_WONT, option);
672       break;
673
674     case CURL_WANTNO:
675       switch(tn->usq[option])
676       {
677         case CURL_EMPTY:
678           tn->us[option] = CURL_NO;
679           break;
680
681         case CURL_OPPOSITE:
682           tn->us[option] = CURL_WANTYES;
683           tn->usq[option] = CURL_EMPTY;
684           send_negotiation(conn, CURL_WILL, option);
685           break;
686       }
687       break;
688
689     case CURL_WANTYES:
690       switch(tn->usq[option])
691       {
692         case CURL_EMPTY:
693           tn->us[option] = CURL_NO;
694           break;
695         case CURL_OPPOSITE:
696           tn->us[option] = CURL_NO;
697           tn->usq[option] = CURL_EMPTY;
698           break;
699       }
700       break;
701   }
702 }
703
704
705 static void printsub(struct SessionHandle *data,
706                      int direction,             /* '<' or '>' */
707                      unsigned char *pointer,    /* where suboption data is */
708                      size_t length)             /* length of suboption data */
709 {
710   unsigned int i = 0;
711
712   if(data->set.verbose)
713   {
714     if(direction)
715     {
716       infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
717       if(length >= 3)
718       {
719         int j;
720
721         i = pointer[length-2];
722         j = pointer[length-1];
723
724         if(i != CURL_IAC || j != CURL_SE)
725         {
726           infof(data, "(terminated by ");
727           if(CURL_TELOPT_OK(i))
728             infof(data, "%s ", CURL_TELOPT(i));
729           else if(CURL_TELCMD_OK(i))
730             infof(data, "%s ", CURL_TELCMD(i));
731           else
732             infof(data, "%u ", i);
733           if(CURL_TELOPT_OK(j))
734             infof(data, "%s", CURL_TELOPT(j));
735           else if(CURL_TELCMD_OK(j))
736             infof(data, "%s", CURL_TELCMD(j));
737           else
738             infof(data, "%d", j);
739           infof(data, ", not IAC SE!) ");
740         }
741       }
742       length -= 2;
743     }
744     if(length < 1)
745     {
746       infof(data, "(Empty suboption?)");
747       return;
748     }
749
750     if(CURL_TELOPT_OK(pointer[0])) {
751       switch(pointer[0]) {
752         case CURL_TELOPT_TTYPE:
753         case CURL_TELOPT_XDISPLOC:
754         case CURL_TELOPT_NEW_ENVIRON:
755           infof(data, "%s", CURL_TELOPT(pointer[0]));
756           break;
757         default:
758           infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0]));
759           break;
760       }
761     }
762     else
763       infof(data, "%d (unknown)", pointer[i]);
764
765     switch(pointer[1]) {
766       case CURL_TELQUAL_IS:
767         infof(data, " IS");
768         break;
769       case CURL_TELQUAL_SEND:
770         infof(data, " SEND");
771         break;
772       case CURL_TELQUAL_INFO:
773         infof(data, " INFO/REPLY");
774         break;
775       case CURL_TELQUAL_NAME:
776         infof(data, " NAME");
777         break;
778     }
779
780     switch(pointer[0]) {
781       case CURL_TELOPT_TTYPE:
782       case CURL_TELOPT_XDISPLOC:
783         pointer[length] = 0;
784         infof(data, " \"%s\"", &pointer[2]);
785         break;
786       case CURL_TELOPT_NEW_ENVIRON:
787         if(pointer[1] == CURL_TELQUAL_IS) {
788           infof(data, " ");
789           for(i = 3;i < length;i++) {
790             switch(pointer[i]) {
791               case CURL_NEW_ENV_VAR:
792                 infof(data, ", ");
793                 break;
794               case CURL_NEW_ENV_VALUE:
795                 infof(data, " = ");
796                 break;
797               default:
798                 infof(data, "%c", pointer[i]);
799                 break;
800             }
801           }
802         }
803         break;
804       default:
805         for (i = 2; i < length; i++)
806           infof(data, " %.2x", pointer[i]);
807         break;
808     }
809
810     if(direction)
811     {
812       infof(data, "\n");
813     }
814   }
815 }
816
817 static CURLcode check_telnet_options(struct connectdata *conn)
818 {
819   struct curl_slist *head;
820   char option_keyword[128];
821   char option_arg[256];
822   char *buf;
823   struct SessionHandle *data = conn->data;
824   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
825
826   /* Add the user name as an environment variable if it
827      was given on the command line */
828   if(conn->bits.user_passwd)
829   {
830     snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
831     tn->telnet_vars = curl_slist_append(tn->telnet_vars, option_arg);
832
833     tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
834   }
835
836   for(head = data->set.telnet_options; head; head=head->next) {
837     if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
838               option_keyword, option_arg) == 2) {
839
840       /* Terminal type */
841       if(Curl_raw_equal(option_keyword, "TTYPE")) {
842         strncpy(tn->subopt_ttype, option_arg, 31);
843         tn->subopt_ttype[31] = 0; /* String termination */
844         tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
845         continue;
846       }
847
848       /* Display variable */
849       if(Curl_raw_equal(option_keyword, "XDISPLOC")) {
850         strncpy(tn->subopt_xdisploc, option_arg, 127);
851         tn->subopt_xdisploc[127] = 0; /* String termination */
852         tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
853         continue;
854       }
855
856       /* Environment variable */
857       if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
858         buf = strdup(option_arg);
859         if(!buf)
860           return CURLE_OUT_OF_MEMORY;
861         tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
862         tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
863         continue;
864       }
865
866       failf(data, "Unknown telnet option %s", head->data);
867       return CURLE_UNKNOWN_TELNET_OPTION;
868     } else {
869       failf(data, "Syntax error in telnet option: %s", head->data);
870       return CURLE_TELNET_OPTION_SYNTAX;
871     }
872   }
873
874   return CURLE_OK;
875 }
876
877 /*
878  * suboption()
879  *
880  * Look at the sub-option buffer, and try to be helpful to the other
881  * side.
882  */
883
884 static void suboption(struct connectdata *conn)
885 {
886   struct curl_slist *v;
887   unsigned char temp[2048];
888   ssize_t bytes_written;
889   size_t len;
890   size_t tmplen;
891   int err;
892   char varname[128];
893   char varval[128];
894   struct SessionHandle *data = conn->data;
895   struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
896
897   printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
898   switch (CURL_SB_GET(tn)) {
899     case CURL_TELOPT_TTYPE:
900       len = strlen(tn->subopt_ttype) + 4 + 2;
901       snprintf((char *)temp, sizeof(temp),
902                "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
903                CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
904       bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
905       if(bytes_written < 0) {
906         err = SOCKERRNO;
907         failf(data,"Sending data failed (%d)",err);
908       }
909       printsub(data, '>', &temp[2], len-2);
910       break;
911     case CURL_TELOPT_XDISPLOC:
912       len = strlen(tn->subopt_xdisploc) + 4 + 2;
913       snprintf((char *)temp, sizeof(temp),
914                "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
915                CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
916       bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
917       if(bytes_written < 0) {
918         err = SOCKERRNO;
919         failf(data,"Sending data failed (%d)",err);
920       }
921       printsub(data, '>', &temp[2], len-2);
922       break;
923     case CURL_TELOPT_NEW_ENVIRON:
924       snprintf((char *)temp, sizeof(temp),
925                "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
926                CURL_TELQUAL_IS);
927       len = 4;
928
929       for(v = tn->telnet_vars;v;v = v->next) {
930         tmplen = (strlen(v->data) + 1);
931         /* Add the variable only if it fits */
932         if(len + tmplen < (int)sizeof(temp)-6) {
933           sscanf(v->data, "%127[^,],%127s", varname, varval);
934           snprintf((char *)&temp[len], sizeof(temp) - len,
935                    "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
936                    CURL_NEW_ENV_VALUE, varval);
937           len += tmplen;
938         }
939       }
940       snprintf((char *)&temp[len], sizeof(temp) - len,
941                "%c%c", CURL_IAC, CURL_SE);
942       len += 2;
943       bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
944       if(bytes_written < 0) {
945         err = SOCKERRNO;
946         failf(data,"Sending data failed (%d)",err);
947       }
948       printsub(data, '>', &temp[2], len-2);
949       break;
950   }
951   return;
952 }
953
954 static
955 CURLcode telrcv(struct connectdata *conn,
956                 const unsigned char *inbuf, /* Data received from socket */
957                 ssize_t count)              /* Number of bytes received */
958 {
959   unsigned char c;
960   CURLcode result;
961   int in = 0;
962   int startwrite=-1;
963   struct SessionHandle *data = conn->data;
964   struct TELNET *tn = (struct TELNET *)data->state.proto.telnet;
965
966 #define startskipping()                                       \
967   if(startwrite >= 0) {                                       \
968     result = Curl_client_write(conn,                          \
969                                CLIENTWRITE_BODY,              \
970                                (char *)&inbuf[startwrite],    \
971                                in-startwrite);                \
972     if(result != CURLE_OK)                                    \
973       return result;                                          \
974   }                                                           \
975   startwrite = -1
976
977 #define writebyte() \
978     if(startwrite < 0) \
979       startwrite = in
980
981 #define bufferflush() startskipping()
982
983   while(count--)
984   {
985     c = inbuf[in];
986
987     /*infof(data,"In rcv state %d char %d\n", tn->telrcv_state, c);*/
988     switch (tn->telrcv_state)
989     {
990       case CURL_TS_CR:
991         tn->telrcv_state = CURL_TS_DATA;
992         if(c == '\0')
993         {
994           startskipping();
995           break;   /* Ignore \0 after CR */
996         }
997         writebyte();
998         break;
999
1000       case CURL_TS_DATA:
1001         if(c == CURL_IAC)
1002         {
1003           tn->telrcv_state = CURL_TS_IAC;
1004           startskipping();
1005           break;
1006         }
1007         else if(c == '\r')
1008         {
1009           tn->telrcv_state = CURL_TS_CR;
1010         }
1011         writebyte();
1012         break;
1013
1014       case CURL_TS_IAC:
1015       process_iac:
1016       DEBUGASSERT(startwrite < 0);
1017       switch (c)
1018       {
1019         case CURL_WILL:
1020           tn->telrcv_state = CURL_TS_WILL;
1021           break;
1022         case CURL_WONT:
1023           tn->telrcv_state = CURL_TS_WONT;
1024           break;
1025         case CURL_DO:
1026           tn->telrcv_state = CURL_TS_DO;
1027           break;
1028         case CURL_DONT:
1029           tn->telrcv_state = CURL_TS_DONT;
1030           break;
1031         case CURL_SB:
1032           CURL_SB_CLEAR(tn);
1033           tn->telrcv_state = CURL_TS_SB;
1034           break;
1035         case CURL_IAC:
1036           tn->telrcv_state = CURL_TS_DATA;
1037           writebyte();
1038           break;
1039         case CURL_DM:
1040         case CURL_NOP:
1041         case CURL_GA:
1042         default:
1043           tn->telrcv_state = CURL_TS_DATA;
1044           printoption(data, "RCVD", CURL_IAC, c);
1045           break;
1046       }
1047       break;
1048
1049       case CURL_TS_WILL:
1050         printoption(data, "RCVD", CURL_WILL, c);
1051         tn->please_negotiate = 1;
1052         rec_will(conn, c);
1053         tn->telrcv_state = CURL_TS_DATA;
1054         break;
1055
1056       case CURL_TS_WONT:
1057         printoption(data, "RCVD", CURL_WONT, c);
1058         tn->please_negotiate = 1;
1059         rec_wont(conn, c);
1060         tn->telrcv_state = CURL_TS_DATA;
1061         break;
1062
1063       case CURL_TS_DO:
1064         printoption(data, "RCVD", CURL_DO, c);
1065         tn->please_negotiate = 1;
1066         rec_do(conn, c);
1067         tn->telrcv_state = CURL_TS_DATA;
1068         break;
1069
1070       case CURL_TS_DONT:
1071         printoption(data, "RCVD", CURL_DONT, c);
1072         tn->please_negotiate = 1;
1073         rec_dont(conn, c);
1074         tn->telrcv_state = CURL_TS_DATA;
1075         break;
1076
1077       case CURL_TS_SB:
1078         if(c == CURL_IAC)
1079         {
1080           tn->telrcv_state = CURL_TS_SE;
1081         }
1082         else
1083         {
1084           CURL_SB_ACCUM(tn,c);
1085         }
1086         break;
1087
1088       case CURL_TS_SE:
1089         if(c != CURL_SE)
1090         {
1091           if(c != CURL_IAC)
1092           {
1093             /*
1094              * This is an error.  We only expect to get "IAC IAC" or "IAC SE".
1095              * Several things may have happend.  An IAC was not doubled, the
1096              * IAC SE was left off, or another option got inserted into the
1097              * suboption are all possibilities.  If we assume that the IAC was
1098              * not doubled, and really the IAC SE was left off, we could get
1099              * into an infinate loop here.  So, instead, we terminate the
1100              * suboption, and process the partial suboption if we can.
1101              */
1102             CURL_SB_ACCUM(tn, CURL_IAC);
1103             CURL_SB_ACCUM(tn, c);
1104             tn->subpointer -= 2;
1105             CURL_SB_TERM(tn);
1106
1107             printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
1108             suboption(conn);   /* handle sub-option */
1109             tn->telrcv_state = CURL_TS_IAC;
1110             goto process_iac;
1111           }
1112           CURL_SB_ACCUM(tn,c);
1113           tn->telrcv_state = CURL_TS_SB;
1114         }
1115         else
1116         {
1117           CURL_SB_ACCUM(tn, CURL_IAC);
1118           CURL_SB_ACCUM(tn, CURL_SE);
1119           tn->subpointer -= 2;
1120           CURL_SB_TERM(tn);
1121           suboption(conn);   /* handle sub-option */
1122           tn->telrcv_state = CURL_TS_DATA;
1123         }
1124         break;
1125     }
1126     ++in;
1127   }
1128   bufferflush();
1129   return CURLE_OK;
1130 }
1131
1132 /* Escape and send a telnet data block */
1133 /* TODO: write large chunks of data instead of one byte at a time */
1134 static CURLcode send_telnet_data(struct connectdata *conn,
1135                                  char *buffer, ssize_t nread)
1136 {
1137   unsigned char outbuf[2];
1138   ssize_t bytes_written, total_written;
1139   int out_count;
1140   CURLcode rc = CURLE_OK;
1141
1142   while(rc == CURLE_OK && nread--) {
1143     outbuf[0] = *buffer++;
1144     out_count = 1;
1145     if(outbuf[0] == CURL_IAC)
1146       outbuf[out_count++] = CURL_IAC;
1147
1148     total_written = 0;
1149     do {
1150       /* Make sure socket is writable to avoid EWOULDBLOCK condition */
1151       struct pollfd pfd[1];
1152       pfd[0].fd = conn->sock[FIRSTSOCKET];
1153       pfd[0].events = POLLOUT;
1154       switch (Curl_poll(pfd, 1, -1)) {
1155         case -1:                    /* error, abort writing */
1156         case 0:                     /* timeout (will never happen) */
1157           rc = CURLE_SEND_ERROR;
1158           break;
1159         default:                    /* write! */
1160           bytes_written = 0;
1161           rc = Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf+total_written,
1162                           out_count-total_written, &bytes_written);
1163           total_written += bytes_written;
1164           break;
1165       }
1166     /* handle partial write */
1167     } while (rc == CURLE_OK && total_written < out_count);
1168   }
1169   return rc;
1170 }
1171
1172 static CURLcode telnet_done(struct connectdata *conn,
1173                                  CURLcode status, bool premature)
1174 {
1175   struct TELNET *tn = (struct TELNET *)conn->data->state.proto.telnet;
1176   (void)status; /* unused */
1177   (void)premature; /* not used */
1178
1179   curl_slist_free_all(tn->telnet_vars);
1180
1181   free(conn->data->state.proto.telnet);
1182   conn->data->state.proto.telnet = NULL;
1183
1184   return CURLE_OK;
1185 }
1186
1187 static CURLcode telnet_do(struct connectdata *conn, bool *done)
1188 {
1189   CURLcode code;
1190   struct SessionHandle *data = conn->data;
1191   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
1192 #ifdef USE_WINSOCK
1193   HMODULE wsock2;
1194   WSOCK2_FUNC close_event_func;
1195   WSOCK2_FUNC create_event_func;
1196   WSOCK2_FUNC event_select_func;
1197   WSOCK2_FUNC enum_netevents_func;
1198   WSAEVENT event_handle;
1199   WSANETWORKEVENTS events;
1200   HANDLE stdin_handle;
1201   HANDLE objs[2];
1202   DWORD  obj_count;
1203   DWORD  wait_timeout;
1204   DWORD waitret;
1205   DWORD readfile_read;
1206   int err;
1207 #else
1208   int interval_ms;
1209   struct pollfd pfd[2];
1210   int poll_cnt;
1211   curl_off_t total_dl = 0;
1212   curl_off_t total_ul = 0;
1213 #endif
1214   ssize_t nread;
1215   struct timeval now;
1216   bool keepon = TRUE;
1217   char *buf = data->state.buffer;
1218   struct TELNET *tn;
1219
1220   *done = TRUE; /* unconditionally */
1221
1222   code = init_telnet(conn);
1223   if(code)
1224     return code;
1225
1226   tn = (struct TELNET *)data->state.proto.telnet;
1227
1228   code = check_telnet_options(conn);
1229   if(code)
1230     return code;
1231
1232 #ifdef USE_WINSOCK
1233   /*
1234   ** This functionality only works with WinSock >= 2.0.  So,
1235   ** make sure have it.
1236   */
1237   code = check_wsock2(data);
1238   if(code)
1239     return code;
1240
1241   /* OK, so we have WinSock 2.0.  We need to dynamically */
1242   /* load ws2_32.dll and get the function pointers we need. */
1243   wsock2 = LoadLibrary("WS2_32.DLL");
1244   if(wsock2 == NULL) {
1245     failf(data,"failed to load WS2_32.DLL (%d)", ERRNO);
1246     return CURLE_FAILED_INIT;
1247   }
1248
1249   /* Grab a pointer to WSACreateEvent */
1250   create_event_func = GetProcAddress(wsock2,"WSACreateEvent");
1251   if(create_event_func == NULL) {
1252     failf(data,"failed to find WSACreateEvent function (%d)",
1253           ERRNO);
1254     FreeLibrary(wsock2);
1255     return CURLE_FAILED_INIT;
1256   }
1257
1258   /* And WSACloseEvent */
1259   close_event_func = GetProcAddress(wsock2,"WSACloseEvent");
1260   if(close_event_func == NULL) {
1261     failf(data,"failed to find WSACloseEvent function (%d)",
1262           ERRNO);
1263     FreeLibrary(wsock2);
1264     return CURLE_FAILED_INIT;
1265   }
1266
1267   /* And WSAEventSelect */
1268   event_select_func = GetProcAddress(wsock2,"WSAEventSelect");
1269   if(event_select_func == NULL) {
1270     failf(data,"failed to find WSAEventSelect function (%d)",
1271           ERRNO);
1272     FreeLibrary(wsock2);
1273     return CURLE_FAILED_INIT;
1274   }
1275
1276   /* And WSAEnumNetworkEvents */
1277   enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents");
1278   if(enum_netevents_func == NULL) {
1279     failf(data,"failed to find WSAEnumNetworkEvents function (%d)",
1280           ERRNO);
1281     FreeLibrary(wsock2);
1282     return CURLE_FAILED_INIT;
1283   }
1284
1285   /* We want to wait for both stdin and the socket. Since
1286   ** the select() function in winsock only works on sockets
1287   ** we have to use the WaitForMultipleObjects() call.
1288   */
1289
1290   /* First, create a sockets event object */
1291   event_handle = (WSAEVENT)create_event_func();
1292   if(event_handle == WSA_INVALID_EVENT) {
1293     failf(data,"WSACreateEvent failed (%d)", SOCKERRNO);
1294     FreeLibrary(wsock2);
1295     return CURLE_FAILED_INIT;
1296   }
1297
1298   /* The get the Windows file handle for stdin */
1299   stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
1300
1301   /* Create the list of objects to wait for */
1302   objs[0] = event_handle;
1303   objs[1] = stdin_handle;
1304
1305   /* Tell winsock what events we want to listen to */
1306   if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
1307     close_event_func(event_handle);
1308     FreeLibrary(wsock2);
1309     return CURLE_OK;
1310   }
1311
1312   /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
1313      else use the old WaitForMultipleObjects() way */
1314   if(GetFileType(stdin_handle) == FILE_TYPE_PIPE) {
1315     /* Don't wait for stdin_handle, just wait for event_handle */
1316     obj_count = 1;
1317     /* Check stdin_handle per 100 milliseconds */
1318     wait_timeout = 100;
1319   } else {
1320     obj_count = 2;
1321     wait_timeout = 1000;
1322   }
1323
1324   /* Keep on listening and act on events */
1325   while(keepon) {
1326     waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
1327     switch(waitret) {
1328     case WAIT_TIMEOUT:
1329     {
1330       for(;;) {
1331         if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
1332           keepon = FALSE;
1333           code = CURLE_READ_ERROR;
1334           break;
1335         }
1336
1337         if(!readfile_read)
1338           break;
1339
1340         if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
1341                      &readfile_read, NULL)) {
1342           keepon = FALSE;
1343           code = CURLE_READ_ERROR;
1344           break;
1345         }
1346
1347         code = send_telnet_data(conn, buf, readfile_read);
1348         if(code) {
1349           keepon = FALSE;
1350           break;
1351         }
1352       }
1353     }
1354     break;
1355
1356     case WAIT_OBJECT_0 + 1:
1357     {
1358       if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
1359                    &readfile_read, NULL)) {
1360         keepon = FALSE;
1361         code = CURLE_READ_ERROR;
1362         break;
1363       }
1364
1365       code = send_telnet_data(conn, buf, readfile_read);
1366       if(code) {
1367         keepon = FALSE;
1368         break;
1369       }
1370     }
1371     break;
1372
1373     case WAIT_OBJECT_0:
1374
1375       if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
1376         if((err = SOCKERRNO) != EINPROGRESS) {
1377           infof(data,"WSAEnumNetworkEvents failed (%d)", err);
1378           keepon = FALSE;
1379           code = CURLE_READ_ERROR;
1380         }
1381         break;
1382       }
1383       if(events.lNetworkEvents & FD_READ) {
1384         /* read data from network */
1385         code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
1386         /* read would've blocked. Loop again */
1387         if(code == CURLE_AGAIN)
1388           break;
1389         /* returned not-zero, this an error */
1390         else if(code) {
1391           keepon = FALSE;
1392           break;
1393         }
1394         /* returned zero but actually received 0 or less here,
1395            the server closed the connection and we bail out */
1396         else if(nread <= 0) {
1397           keepon = FALSE;
1398           break;
1399         }
1400
1401         code = telrcv(conn, (unsigned char *)buf, nread);
1402         if(code) {
1403           keepon = FALSE;
1404           break;
1405         }
1406
1407         /* Negotiate if the peer has started negotiating,
1408            otherwise don't. We don't want to speak telnet with
1409            non-telnet servers, like POP or SMTP. */
1410         if(tn->please_negotiate && !tn->already_negotiated) {
1411           negotiate(conn);
1412           tn->already_negotiated = 1;
1413         }
1414       }
1415       if(events.lNetworkEvents & FD_CLOSE) {
1416         keepon = FALSE;
1417       }
1418       break;
1419
1420     }
1421
1422     if(data->set.timeout) {
1423       now = Curl_tvnow();
1424       if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
1425         failf(data, "Time-out");
1426         code = CURLE_OPERATION_TIMEDOUT;
1427         keepon = FALSE;
1428       }
1429     }
1430   }
1431
1432   /* We called WSACreateEvent, so call WSACloseEvent */
1433   if(close_event_func(event_handle) == FALSE) {
1434     infof(data,"WSACloseEvent failed (%d)", SOCKERRNO);
1435   }
1436
1437   /* "Forget" pointers into the library we're about to free */
1438   create_event_func = NULL;
1439   close_event_func = NULL;
1440   event_select_func = NULL;
1441   enum_netevents_func = NULL;
1442
1443   /* We called LoadLibrary, so call FreeLibrary */
1444   if(!FreeLibrary(wsock2))
1445     infof(data,"FreeLibrary(wsock2) failed (%d)", ERRNO);
1446 #else
1447   pfd[0].fd = sockfd;
1448   pfd[0].events = POLLIN;
1449
1450   if (data->set.is_fread_set) {
1451     poll_cnt = 1;
1452     interval_ms = 100; /* poll user-supplied read function */
1453   }
1454   else {
1455     pfd[1].fd = 0;
1456     pfd[1].events = POLLIN;
1457     poll_cnt = 2;
1458     interval_ms = 1 * 1000;
1459   }
1460
1461   while(keepon) {
1462     switch (Curl_poll(pfd, poll_cnt, interval_ms)) {
1463     case -1:                    /* error, stop reading */
1464       keepon = FALSE;
1465       continue;
1466     case 0:                     /* timeout */
1467       pfd[0].revents = 0;
1468       pfd[1].revents = 0;
1469       /* fall through */
1470     default:                    /* read! */
1471       if(pfd[0].revents & POLLIN) {
1472         /* read data from network */
1473         code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
1474         /* read would've blocked. Loop again */
1475         if(code == CURLE_AGAIN)
1476           break;
1477         /* returned not-zero, this an error */
1478         else if(code) {
1479           keepon = FALSE;
1480           break;
1481         }
1482         /* returned zero but actually received 0 or less here,
1483            the server closed the connection and we bail out */
1484         else if(nread <= 0) {
1485           keepon = FALSE;
1486           break;
1487         }
1488
1489         total_dl += nread;
1490         Curl_pgrsSetDownloadCounter(data, total_dl);
1491         code = telrcv(conn, (unsigned char *)buf, nread);
1492         if(code) {
1493           keepon = FALSE;
1494           break;
1495         }
1496
1497         /* Negotiate if the peer has started negotiating,
1498            otherwise don't. We don't want to speak telnet with
1499            non-telnet servers, like POP or SMTP. */
1500         if(tn->please_negotiate && !tn->already_negotiated) {
1501           negotiate(conn);
1502           tn->already_negotiated = 1;
1503         }
1504       }
1505
1506       nread = 0;
1507       if (poll_cnt == 2) {
1508         if(pfd[1].revents & POLLIN) { /* read from stdin */
1509           nread = read(0, buf, BUFSIZE - 1);
1510         }
1511       }
1512       else {
1513         /* read from user-supplied method */
1514         nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
1515         if (nread == CURL_READFUNC_ABORT) {
1516           keepon = FALSE;
1517           break;
1518         }
1519         if (nread == CURL_READFUNC_PAUSE)
1520           break;
1521       }
1522
1523       if (nread > 0) {
1524         code = send_telnet_data(conn, buf, nread);
1525         if(code) {
1526           keepon = FALSE;
1527           break;
1528         }
1529         total_ul += nread;
1530         Curl_pgrsSetUploadCounter(data, total_ul);
1531       }
1532       else if (nread < 0)
1533         keepon = FALSE;
1534
1535       break;
1536     } /* poll switch statement */
1537
1538     if(data->set.timeout) {
1539       now = Curl_tvnow();
1540       if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
1541         failf(data, "Time-out");
1542         code = CURLE_OPERATION_TIMEDOUT;
1543         keepon = FALSE;
1544       }
1545     }
1546
1547     if(Curl_pgrsUpdate(conn)) {
1548        code = CURLE_ABORTED_BY_CALLBACK;
1549        break;
1550     }
1551   }
1552 #endif
1553   /* mark this as "no further transfer wanted" */
1554   Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1555
1556   return code;
1557 }
1558 #endif