~ubuntu-branches/ubuntu/dapper/curl/dapper-security

« back to all changes in this revision

Viewing changes to lib/telnet.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2005-03-23 18:41:29 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050323184129-le70d05a0hk5w62j
Tags: 7.12.3-2ubuntu3
Fix the version numbers internal to debian/rules.  Closes; #8088

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/***************************************************************************
2
 
 *                                  _   _ ____  _     
3
 
 *  Project                     ___| | | |  _ \| |    
4
 
 *                             / __| | | | |_) | |    
5
 
 *                            | (__| |_| |  _ <| |___ 
 
2
 *                                  _   _ ____  _
 
3
 *  Project                     ___| | | |  _ \| |
 
4
 *                             / __| | | | |_) | |
 
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
8
 * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
12
12
 * are also available at http://curl.haxx.se/docs/copyright.html.
13
 
 * 
 
13
 *
14
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
15
 * copies of the Software, and permit persons to whom the Software is
16
16
 * furnished to do so, under the terms of the COPYING file.
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: telnet.c,v 1.58 2004/03/23 15:28:31 bagder Exp $
 
21
 * $Id: telnet.c,v 1.71 2004/11/19 08:52:33 bagder Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
#include "setup.h"
30
30
#include <stdarg.h>
31
31
#include <stdlib.h>
32
32
#include <ctype.h>
 
33
#ifdef HAVE_SYS_TYPES_H
33
34
#include <sys/types.h>
 
35
#endif
 
36
#ifdef HAVE_SYS_STAT_H
34
37
#include <sys/stat.h>
35
 
 
 
38
#endif
36
39
#include <errno.h>
37
40
 
38
41
#if defined(WIN32)
61
64
#include <sys/param.h>
62
65
#endif
63
66
 
64
 
#ifdef HAVE_SYS_SELECT_H
65
 
#include <sys/select.h>
66
 
#endif
67
 
 
68
67
 
69
68
#endif
70
69
 
81
80
#define  TELCMDS
82
81
 
83
82
#include "arpa_telnet.h"
 
83
#include "memory.h"
 
84
#include "select.h"
84
85
 
85
86
/* The last #include file should be: */
86
 
#ifdef CURLDEBUG
87
87
#include "memdebug.h"
88
 
#endif
89
88
 
90
89
#define SUBBUFSIZE 512
91
90
 
108
107
 
109
108
static
110
109
void telrcv(struct connectdata *,
111
 
            unsigned char *inbuf,       /* Data received from socket */
112
 
            int count);                 /* Number of bytes received */
 
110
            unsigned char *inbuf,       /* Data received from socket */
 
111
            ssize_t count);             /* Number of bytes received */
113
112
 
114
113
static void printoption(struct SessionHandle *data,
115
 
                        const char *direction,
116
 
                        int cmd, int option);
 
114
                        const char *direction,
 
115
                        int cmd, int option);
117
116
 
118
117
static void negotiate(struct connectdata *);
119
118
static void send_negotiation(struct connectdata *, int cmd, int option);
121
120
static void set_remote_option(struct connectdata *, int cmd, int option);
122
121
 
123
122
static void printsub(struct SessionHandle *data,
124
 
                     int direction, unsigned char *pointer, int length);
 
123
                     int direction, unsigned char *pointer,
 
124
                     size_t length);
125
125
static void suboption(struct connectdata *);
126
126
 
127
127
/* For negotiation compliant to RFC 1143 */
128
 
#define CURL_NO          0
129
 
#define CURL_YES         1
130
 
#define CURL_WANTYES     2
131
 
#define CURL_WANTNO      3
 
128
#define CURL_NO          0
 
129
#define CURL_YES         1
 
130
#define CURL_WANTYES     2
 
131
#define CURL_WANTNO      3
132
132
 
133
 
#define CURL_EMPTY       0
 
133
#define CURL_EMPTY       0
134
134
#define CURL_OPPOSITE    1
135
135
 
136
136
/*
152
152
struct TELNET {
153
153
  int please_negotiate;
154
154
  int already_negotiated;
155
 
  int us[256]; 
156
 
  int usq[256]; 
157
 
  int us_preferred[256]; 
158
 
  int him[256]; 
159
 
  int himq[256]; 
160
 
  int him_preferred[256]; 
 
155
  int us[256];
 
156
  int usq[256];
 
157
  int us_preferred[256];
 
158
  int him[256];
 
159
  int himq[256];
 
160
  int him_preferred[256];
161
161
  char subopt_ttype[32];             /* Set with suboption TTYPE */
162
162
  char subopt_xdisploc[128];          /* Set with suboption XDISPLOC */
163
163
  struct curl_slist *telnet_vars; /* Environment variables */
165
165
  /* suboptions */
166
166
  char subbuffer[SUBBUFSIZE];
167
167
  char *subpointer, *subend;      /* buffer for sub-options */
168
 
  
 
168
 
169
169
  TelnetReceive telrcv_state;
170
170
};
171
171
 
173
173
static CURLcode
174
174
check_wsock2 ( struct SessionHandle *data )
175
175
{
176
 
  int err; 
177
 
  WORD wVersionRequested;  
178
 
  WSADATA wsaData; 
 
176
  int err;
 
177
  WORD wVersionRequested;
 
178
  WSADATA wsaData;
179
179
 
180
180
  curlassert(data);
181
181
 
182
182
  /* telnet requires at least WinSock 2.0 so ask for it. */
183
183
  wVersionRequested = MAKEWORD(2, 0);
184
184
 
185
 
  err = WSAStartup(wVersionRequested, &wsaData); 
186
 
  
 
185
  err = WSAStartup(wVersionRequested, &wsaData);
 
186
 
187
187
  /* We must've called this once already, so this call */
188
188
  /* should always succeed.  But, just in case... */
189
189
  if (err != 0) {
190
190
    failf(data,"WSAStartup failed (%d)",err);
191
 
    return CURLE_FAILED_INIT; 
 
191
    return CURLE_FAILED_INIT;
192
192
  }
193
193
 
194
194
  /* We have to have a WSACleanup call for every successful */
200
200
      HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
201
201
      /* Our version isn't supported */
202
202
      failf(data,"insufficient winsock version to support "
203
 
            "telnet");
 
203
            "telnet");
204
204
      return CURLE_FAILED_INIT;
205
205
  }
206
206
 
213
213
{
214
214
  struct TELNET *tn;
215
215
 
216
 
  tn = (struct TELNET *)malloc(sizeof(struct TELNET));
 
216
  tn = (struct TELNET *)calloc(1, sizeof(struct TELNET));
217
217
  if(!tn)
218
218
    return CURLE_OUT_OF_MEMORY;
219
 
  
 
219
 
220
220
  conn->proto.telnet = (void *)tn; /* make us known */
221
221
 
222
 
  memset(tn, 0, sizeof(struct TELNET));
223
 
 
224
222
  tn->telrcv_state = CURL_TS_DATA;
225
223
 
226
224
  /* Init suboptions */
227
225
  CURL_SB_CLEAR(tn);
228
226
 
229
 
  /* Set all options to NO */
230
 
#if 0
231
 
  /* NO is zero => default fill pattern */
232
 
  memset(tn->us, CURL_NO, 256);
233
 
  memset(tn->usq, CURL_NO, 256);
234
 
  memset(tn->us_preferred, CURL_NO, 256);
235
 
  memset(tn->him, CURL_NO, 256);
236
 
  memset(tn->himq, CURL_NO, 256);
237
 
  memset(tn->him_preferred, CURL_NO, 256);
238
 
#endif
239
227
  /* Set the options we want by default */
240
228
  tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES;
241
229
  tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES;
249
237
{
250
238
  int i;
251
239
  struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
252
 
   
 
240
 
253
241
  for(i = 0;i < CURL_NTELOPTS;i++)
254
242
  {
255
243
    if(tn->us_preferred[i] == CURL_YES)
256
244
      set_local_option(conn, i, CURL_YES);
257
 
      
 
245
 
258
246
    if(tn->him_preferred[i] == CURL_YES)
259
247
      set_remote_option(conn, i, CURL_YES);
260
248
  }
261
249
}
262
250
 
263
251
static void printoption(struct SessionHandle *data,
264
 
                        const char *direction, int cmd, int option)
 
252
                        const char *direction, int cmd, int option)
265
253
{
266
254
  const char *fmt;
267
255
  const char *opt;
268
 
   
 
256
 
269
257
  if (data->set.verbose)
270
258
  {
271
259
    if (cmd == CURL_IAC)
272
260
    {
273
261
      if (CURL_TELCMD_OK(option))
274
 
        Curl_infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
 
262
        infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
275
263
      else
276
 
        Curl_infof(data, "%s IAC %d\n", direction, option);
 
264
        infof(data, "%s IAC %d\n", direction, option);
277
265
    }
278
266
    else
279
267
    {
289
277
          opt = NULL;
290
278
 
291
279
        if(opt)
292
 
          Curl_infof(data, "%s %s %s\n", direction, fmt, opt);
 
280
          infof(data, "%s %s %s\n", direction, fmt, opt);
293
281
        else
294
 
          Curl_infof(data, "%s %s %d\n", direction, fmt, option);
 
282
          infof(data, "%s %s %d\n", direction, fmt, option);
295
283
      }
296
284
      else
297
 
        Curl_infof(data, "%s %d %d\n", direction, cmd, option);
 
285
        infof(data, "%s %d %d\n", direction, cmd, option);
298
286
    }
299
287
  }
300
288
}
306
294
   buf[0] = CURL_IAC;
307
295
   buf[1] = cmd;
308
296
   buf[2] = option;
309
 
   
310
 
   (void)swrite(conn->sock[FIRSTSOCKET], buf, 3);
311
 
   
 
297
 
 
298
   (void)swrite(conn->sock[FIRSTSOCKET], (char *)buf, 3);
 
299
 
312
300
   printoption(conn->data, "SENT", cmd, option);
313
301
}
314
302
 
324
312
        tn->him[option] = CURL_WANTYES;
325
313
        send_negotiation(conn, CURL_DO, option);
326
314
        break;
327
 
         
 
315
 
328
316
      case CURL_YES:
329
317
        /* Already enabled */
330
318
        break;
331
 
         
 
319
 
332
320
      case CURL_WANTNO:
333
321
        switch(tn->himq[option])
334
322
        {
341
329
            break;
342
330
        }
343
331
        break;
344
 
         
 
332
 
345
333
      case CURL_WANTYES:
346
334
        switch(tn->himq[option])
347
335
        {
362
350
      case CURL_NO:
363
351
        /* Already disabled */
364
352
        break;
365
 
         
 
353
 
366
354
      case CURL_YES:
367
355
        tn->him[option] = CURL_WANTNO;
368
356
        send_negotiation(conn, CURL_DONT, option);
369
357
        break;
370
 
         
 
358
 
371
359
      case CURL_WANTNO:
372
360
        switch(tn->himq[option])
373
361
        {
379
367
            break;
380
368
        }
381
369
        break;
382
 
         
 
370
 
383
371
      case CURL_WANTYES:
384
372
        switch(tn->himq[option])
385
373
        {
411
399
        send_negotiation(conn, CURL_DONT, option);
412
400
      }
413
401
      break;
414
 
         
 
402
 
415
403
    case CURL_YES:
416
404
      /* Already enabled */
417
405
      break;
418
 
         
 
406
 
419
407
    case CURL_WANTNO:
420
408
      switch(tn->himq[option])
421
409
      {
430
418
          break;
431
419
      }
432
420
      break;
433
 
         
 
421
 
434
422
    case CURL_WANTYES:
435
423
      switch(tn->himq[option])
436
424
      {
446
434
      break;
447
435
  }
448
436
}
449
 
   
 
437
 
450
438
static
451
439
void rec_wont(struct connectdata *conn, int option)
452
440
{
456
444
    case CURL_NO:
457
445
      /* Already disabled */
458
446
      break;
459
 
         
 
447
 
460
448
    case CURL_YES:
461
449
      tn->him[option] = CURL_NO;
462
450
      send_negotiation(conn, CURL_DONT, option);
463
451
      break;
464
 
         
 
452
 
465
453
    case CURL_WANTNO:
466
454
      switch(tn->himq[option])
467
455
      {
468
456
        case CURL_EMPTY:
469
457
          tn->him[option] = CURL_NO;
470
458
          break;
471
 
         
 
459
 
472
460
        case CURL_OPPOSITE:
473
461
          tn->him[option] = CURL_WANTYES;
474
462
          tn->himq[option] = CURL_EMPTY;
476
464
          break;
477
465
      }
478
466
      break;
479
 
         
 
467
 
480
468
    case CURL_WANTYES:
481
469
      switch(tn->himq[option])
482
470
      {
491
479
      break;
492
480
  }
493
481
}
494
 
   
 
482
 
495
483
static void
496
484
set_local_option(struct connectdata *conn, int option, int newstate)
497
485
{
504
492
        tn->us[option] = CURL_WANTYES;
505
493
        send_negotiation(conn, CURL_WILL, option);
506
494
        break;
507
 
         
 
495
 
508
496
      case CURL_YES:
509
497
        /* Already enabled */
510
498
        break;
511
 
         
 
499
 
512
500
      case CURL_WANTNO:
513
501
        switch(tn->usq[option])
514
502
        {
521
509
            break;
522
510
        }
523
511
        break;
524
 
         
 
512
 
525
513
      case CURL_WANTYES:
526
514
        switch(tn->usq[option])
527
515
        {
542
530
      case CURL_NO:
543
531
        /* Already disabled */
544
532
        break;
545
 
         
 
533
 
546
534
      case CURL_YES:
547
535
        tn->us[option] = CURL_WANTNO;
548
536
        send_negotiation(conn, CURL_WONT, option);
549
537
        break;
550
 
         
 
538
 
551
539
      case CURL_WANTNO:
552
540
        switch(tn->usq[option])
553
541
        {
559
547
            break;
560
548
        }
561
549
        break;
562
 
         
 
550
 
563
551
      case CURL_WANTYES:
564
552
        switch(tn->usq[option])
565
553
        {
591
579
        send_negotiation(conn, CURL_WONT, option);
592
580
      }
593
581
      break;
594
 
         
 
582
 
595
583
    case CURL_YES:
596
584
      /* Already enabled */
597
585
      break;
598
 
         
 
586
 
599
587
    case CURL_WANTNO:
600
588
      switch(tn->usq[option])
601
589
      {
610
598
          break;
611
599
      }
612
600
      break;
613
 
         
 
601
 
614
602
    case CURL_WANTYES:
615
603
      switch(tn->usq[option])
616
604
      {
627
615
  }
628
616
}
629
617
 
630
 
static   
 
618
static
631
619
void rec_dont(struct connectdata *conn, int option)
632
620
{
633
621
  struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
636
624
    case CURL_NO:
637
625
      /* Already disabled */
638
626
      break;
639
 
         
 
627
 
640
628
    case CURL_YES:
641
629
      tn->us[option] = CURL_NO;
642
630
      send_negotiation(conn, CURL_WONT, option);
643
631
      break;
644
 
         
 
632
 
645
633
    case CURL_WANTNO:
646
634
      switch(tn->usq[option])
647
635
      {
648
636
        case CURL_EMPTY:
649
637
          tn->us[option] = CURL_NO;
650
638
          break;
651
 
         
 
639
 
652
640
        case CURL_OPPOSITE:
653
641
          tn->us[option] = CURL_WANTYES;
654
642
          tn->usq[option] = CURL_EMPTY;
656
644
          break;
657
645
      }
658
646
      break;
659
 
         
 
647
 
660
648
    case CURL_WANTYES:
661
649
      switch(tn->usq[option])
662
650
      {
674
662
 
675
663
 
676
664
static void printsub(struct SessionHandle *data,
677
 
                     int direction,             /* '<' or '>' */
678
 
                     unsigned char *pointer,    /* where suboption data is */
679
 
                     int length)                /* length of suboption data */
 
665
                     int direction,             /* '<' or '>' */
 
666
                     unsigned char *pointer,    /* where suboption data is */
 
667
                     size_t length)             /* length of suboption data */
680
668
{
681
 
  int i = 0;
 
669
  unsigned int i = 0;
682
670
 
683
671
  if (data->set.verbose)
684
672
  {
685
673
    if (direction)
686
674
    {
687
 
      Curl_infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
 
675
      infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
688
676
      if (length >= 3)
689
677
      {
690
678
        int j;
694
682
 
695
683
        if (i != CURL_IAC || j != CURL_SE)
696
684
        {
697
 
          Curl_infof(data, "(terminated by ");
 
685
          infof(data, "(terminated by ");
698
686
          if (CURL_TELOPT_OK(i))
699
 
            Curl_infof(data, "%s ", CURL_TELOPT(i));
 
687
            infof(data, "%s ", CURL_TELOPT(i));
700
688
          else if (CURL_TELCMD_OK(i))
701
 
            Curl_infof(data, "%s ", CURL_TELCMD(i));
 
689
            infof(data, "%s ", CURL_TELCMD(i));
702
690
          else
703
 
            Curl_infof(data, "%d ", i);
 
691
            infof(data, "%d ", i);
704
692
          if (CURL_TELOPT_OK(j))
705
 
            Curl_infof(data, "%s", CURL_TELOPT(j));
 
693
            infof(data, "%s", CURL_TELOPT(j));
706
694
          else if (CURL_TELCMD_OK(j))
707
 
            Curl_infof(data, "%s", CURL_TELCMD(j));
 
695
            infof(data, "%s", CURL_TELCMD(j));
708
696
          else
709
 
            Curl_infof(data, "%d", j);
710
 
          Curl_infof(data, ", not IAC SE!) ");
 
697
            infof(data, "%d", j);
 
698
          infof(data, ", not IAC SE!) ");
711
699
        }
712
700
      }
713
701
      length -= 2;
714
702
    }
715
703
    if (length < 1)
716
704
    {
717
 
      Curl_infof(data, "(Empty suboption?)");
 
705
      infof(data, "(Empty suboption?)");
718
706
      return;
719
707
    }
720
708
 
723
711
        case CURL_TELOPT_TTYPE:
724
712
        case CURL_TELOPT_XDISPLOC:
725
713
        case CURL_TELOPT_NEW_ENVIRON:
726
 
          Curl_infof(data, "%s", CURL_TELOPT(pointer[0]));
 
714
          infof(data, "%s", CURL_TELOPT(pointer[0]));
727
715
          break;
728
716
        default:
729
 
          Curl_infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0]));
 
717
          infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0]));
730
718
          break;
731
719
      }
732
720
    }
733
721
    else
734
 
      Curl_infof(data, "%d (unknown)", pointer[i]);
 
722
      infof(data, "%d (unknown)", pointer[i]);
735
723
 
736
724
    switch(pointer[1]) {
737
725
      case CURL_TELQUAL_IS:
738
 
        Curl_infof(data, " IS");
 
726
        infof(data, " IS");
739
727
        break;
740
728
      case CURL_TELQUAL_SEND:
741
 
        Curl_infof(data, " SEND");
 
729
        infof(data, " SEND");
742
730
        break;
743
731
      case CURL_TELQUAL_INFO:
744
 
        Curl_infof(data, " INFO/REPLY");
 
732
        infof(data, " INFO/REPLY");
745
733
        break;
746
734
      case CURL_TELQUAL_NAME:
747
 
        Curl_infof(data, " NAME");
 
735
        infof(data, " NAME");
748
736
        break;
749
737
    }
750
 
      
 
738
 
751
739
    switch(pointer[0]) {
752
740
      case CURL_TELOPT_TTYPE:
753
741
      case CURL_TELOPT_XDISPLOC:
754
742
        pointer[length] = 0;
755
 
        Curl_infof(data, " \"%s\"", &pointer[2]);
 
743
        infof(data, " \"%s\"", &pointer[2]);
756
744
        break;
757
745
      case CURL_TELOPT_NEW_ENVIRON:
758
746
        if(pointer[1] == CURL_TELQUAL_IS) {
759
 
          Curl_infof(data, " ");
 
747
          infof(data, " ");
760
748
          for(i = 3;i < length;i++) {
761
749
            switch(pointer[i]) {
762
750
              case CURL_NEW_ENV_VAR:
763
 
                Curl_infof(data, ", ");
 
751
                infof(data, ", ");
764
752
                break;
765
753
              case CURL_NEW_ENV_VALUE:
766
 
                Curl_infof(data, " = ");
 
754
                infof(data, " = ");
767
755
                break;
768
756
              default:
769
 
                Curl_infof(data, "%c", pointer[i]);
 
757
                infof(data, "%c", pointer[i]);
770
758
                break;
771
759
            }
772
760
          }
774
762
        break;
775
763
      default:
776
764
        for (i = 2; i < length; i++)
777
 
          Curl_infof(data, " %.2x", pointer[i]);
 
765
          infof(data, " %.2x", pointer[i]);
778
766
        break;
779
767
    }
780
 
      
 
768
 
781
769
    if (direction)
782
770
    {
783
 
      Curl_infof(data, "\n");
 
771
      infof(data, "\n");
784
772
    }
785
773
  }
786
774
}
870
858
      snprintf((char *)temp, sizeof(temp),
871
859
               "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
872
860
               CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
873
 
      (void)swrite(conn->sock[FIRSTSOCKET], temp, len);
 
861
      (void)swrite(conn->sock[FIRSTSOCKET], (char *)temp, len);
874
862
      printsub(data, '>', &temp[2], len-2);
875
863
      break;
876
864
    case CURL_TELOPT_XDISPLOC:
878
866
      snprintf((char *)temp, sizeof(temp),
879
867
               "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
880
868
               CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
881
 
      (void)swrite(conn->sock[FIRSTSOCKET], temp, len);
 
869
      (void)swrite(conn->sock[FIRSTSOCKET], (char *)temp, len);
882
870
      printsub(data, '>', &temp[2], len-2);
883
871
      break;
884
872
    case CURL_TELOPT_NEW_ENVIRON:
891
879
        tmplen = (strlen(v->data) + 1);
892
880
        /* Add the variable only if it fits */
893
881
        if(len + tmplen < (int)sizeof(temp)-6) {
894
 
          sscanf(v->data, "%127[^,],%s", varname, varval);
 
882
          sscanf(v->data, "%127[^,],%127s", varname, varval);
895
883
          snprintf((char *)&temp[len], sizeof(temp) - len,
896
884
                   "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
897
885
                   CURL_NEW_ENV_VALUE, varval);
901
889
      snprintf((char *)&temp[len], sizeof(temp) - len,
902
890
               "%c%c", CURL_IAC, CURL_SE);
903
891
      len += 2;
904
 
      (void)swrite(conn->sock[FIRSTSOCKET], temp, len);
 
892
      (void)swrite(conn->sock[FIRSTSOCKET], (char *)temp, len);
905
893
      printsub(data, '>', &temp[2], len-2);
906
894
      break;
907
895
  }
910
898
 
911
899
static
912
900
void telrcv(struct connectdata *conn,
913
 
            unsigned char *inbuf,       /* Data received from socket */
914
 
            int count)                  /* Number of bytes received */
 
901
            unsigned char *inbuf,       /* Data received from socket */
 
902
            ssize_t count)              /* Number of bytes received */
915
903
{
916
904
  unsigned char c;
917
905
  int in = 0;
987
975
        rec_will(conn, c);
988
976
        tn->telrcv_state = CURL_TS_DATA;
989
977
        continue;
990
 
      
 
978
 
991
979
      case CURL_TS_WONT:
992
980
        printoption(data, "RCVD", CURL_WONT, c);
993
981
        tn->please_negotiate = 1;
994
982
        rec_wont(conn, c);
995
983
        tn->telrcv_state = CURL_TS_DATA;
996
984
        continue;
997
 
      
 
985
 
998
986
      case CURL_TS_DO:
999
987
        printoption(data, "RCVD", CURL_DO, c);
1000
988
        tn->please_negotiate = 1;
1001
989
        rec_do(conn, c);
1002
990
        tn->telrcv_state = CURL_TS_DATA;
1003
991
        continue;
1004
 
      
 
992
 
1005
993
      case CURL_TS_DONT:
1006
994
        printoption(data, "RCVD", CURL_DONT, c);
1007
995
        tn->please_negotiate = 1;
1041
1029
            CURL_SB_ACCUM(tn, c);
1042
1030
            tn->subpointer -= 2;
1043
1031
            CURL_SB_TERM(tn);
1044
 
            
 
1032
 
1045
1033
            printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
1046
1034
            suboption(conn);   /* handle sub-option */
1047
1035
            tn->telrcv_state = CURL_TS_IAC;
1064
1052
  }
1065
1053
}
1066
1054
 
1067
 
CURLcode Curl_telnet_done(struct connectdata *conn)
 
1055
CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status)
1068
1056
{
1069
1057
  struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
 
1058
  (void)status; /* unused */
 
1059
 
1070
1060
  curl_slist_free_all(tn->telnet_vars);
1071
1061
 
1072
1062
  free(conn->proto.telnet);
1090
1080
  WSANETWORKEVENTS events;
1091
1081
  HANDLE stdin_handle;
1092
1082
  HANDLE objs[2];
 
1083
  DWORD  obj_count;
 
1084
  DWORD  wait_timeout;
1093
1085
  DWORD waitret;
1094
1086
  DWORD readfile_read;
1095
1087
#else
1096
 
  fd_set readfd;
1097
 
  fd_set keepfd;
 
1088
  int interval_ms;
 
1089
  struct pollfd pfd[2];
1098
1090
#endif
1099
 
  ssize_t nread;  
 
1091
  ssize_t nread;
1100
1092
  bool keepon = TRUE;
1101
1093
  char *buf = data->state.buffer;
1102
1094
  struct TELNET *tn;
1132
1124
  create_event_func = GetProcAddress(wsock2,"WSACreateEvent");
1133
1125
  if (create_event_func == NULL) {
1134
1126
    failf(data,"failed to find WSACreateEvent function (%d)",
1135
 
          GetLastError());
 
1127
          GetLastError());
1136
1128
    FreeLibrary(wsock2);
1137
1129
    return CURLE_FAILED_INIT;
1138
1130
  }
1141
1133
  close_event_func = GetProcAddress(wsock2,"WSACloseEvent");
1142
1134
  if (create_event_func == NULL) {
1143
1135
    failf(data,"failed to find WSACloseEvent function (%d)",
1144
 
          GetLastError());
 
1136
          GetLastError());
1145
1137
    FreeLibrary(wsock2);
1146
1138
    return CURLE_FAILED_INIT;
1147
1139
  }
1150
1142
  event_select_func = GetProcAddress(wsock2,"WSAEventSelect");
1151
1143
  if (event_select_func == NULL) {
1152
1144
    failf(data,"failed to find WSAEventSelect function (%d)",
1153
 
          GetLastError());
 
1145
          GetLastError());
1154
1146
    FreeLibrary(wsock2);
1155
1147
    return CURLE_FAILED_INIT;
1156
1148
  }
1159
1151
  enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents");
1160
1152
  if (enum_netevents_func == NULL) {
1161
1153
    failf(data,"failed to find WSAEnumNetworkEvents function (%d)",
1162
 
          GetLastError());
 
1154
          GetLastError());
1163
1155
    FreeLibrary(wsock2);
1164
1156
    return CURLE_FAILED_INIT;
1165
1157
  }
1181
1173
  stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
1182
1174
 
1183
1175
  /* Create the list of objects to wait for */
1184
 
  objs[0] = stdin_handle;
1185
 
  objs[1] = event_handle;
 
1176
  objs[0] = event_handle;
 
1177
  objs[1] = stdin_handle;
1186
1178
 
1187
1179
  /* Tell winsock what events we want to listen to */
1188
1180
  if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
1191
1183
    return 0;
1192
1184
  }
1193
1185
 
 
1186
  /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
 
1187
     else use the old WaitForMultipleObjects() way */
 
1188
  if(GetFileType(stdin_handle) == FILE_TYPE_PIPE) {
 
1189
    /* Don't wait for stdin_handle, just wait for event_handle */
 
1190
    obj_count = 1;
 
1191
    /* Check stdin_handle per 100 milliseconds */
 
1192
    wait_timeout = 100;
 
1193
  } else {
 
1194
    obj_count = 2;
 
1195
    wait_timeout = INFINITE;
 
1196
  }
 
1197
 
1194
1198
  /* Keep on listening and act on events */
1195
1199
  while(keepon) {
1196
 
    waitret = WaitForMultipleObjects(2, objs, FALSE, INFINITE);
1197
 
    switch(waitret - WAIT_OBJECT_0) {
1198
 
    case 0:
1199
 
    {
1200
 
      unsigned char outbuf[2];
1201
 
      int out_count = 0;
1202
 
      ssize_t bytes_written;
1203
 
      char *buffer = buf;
1204
 
              
 
1200
    waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
 
1201
    switch(waitret) {
 
1202
    case WAIT_TIMEOUT:
 
1203
    {
 
1204
      unsigned char outbuf[2];
 
1205
      int out_count = 0;
 
1206
      ssize_t bytes_written;
 
1207
      char *buffer = buf;
 
1208
 
 
1209
      for(;;) {
 
1210
        if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
 
1211
          keepon = FALSE;
 
1212
          break;
 
1213
        }
 
1214
        nread = readfile_read;
 
1215
 
 
1216
        if(!nread)
 
1217
          break;
 
1218
 
 
1219
        if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
 
1220
                     &readfile_read, NULL)) {
 
1221
          keepon = FALSE;
 
1222
          break;
 
1223
        }
 
1224
        nread = readfile_read;
 
1225
 
 
1226
        while(nread--) {
 
1227
          outbuf[0] = *buffer++;
 
1228
          out_count = 1;
 
1229
          if(outbuf[0] == CURL_IAC)
 
1230
            outbuf[out_count++] = CURL_IAC;
 
1231
 
 
1232
          Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
 
1233
                     out_count, &bytes_written);
 
1234
        }
 
1235
      }
 
1236
    }
 
1237
    break;
 
1238
 
 
1239
    case WAIT_OBJECT_0 + 1:
 
1240
    {
 
1241
      unsigned char outbuf[2];
 
1242
      int out_count = 0;
 
1243
      ssize_t bytes_written;
 
1244
      char *buffer = buf;
 
1245
 
1205
1246
      if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
1206
1247
                   &readfile_read, NULL)) {
1207
1248
        keepon = FALSE;
1208
1249
        break;
1209
1250
      }
1210
1251
      nread = readfile_read;
1211
 
        
 
1252
 
1212
1253
      while(nread--) {
1213
1254
        outbuf[0] = *buffer++;
1214
1255
        out_count = 1;
1215
1256
        if(outbuf[0] == CURL_IAC)
1216
1257
          outbuf[out_count++] = CURL_IAC;
1217
 
          
 
1258
 
1218
1259
        Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
1219
1260
                   out_count, &bytes_written);
1220
1261
      }
1221
1262
    }
1222
1263
    break;
1223
 
      
1224
 
    case 1:
 
1264
 
 
1265
    case WAIT_OBJECT_0:
1225
1266
      if(enum_netevents_func(sockfd, event_handle, &events)
1226
1267
         != SOCKET_ERROR) {
1227
1268
        if(events.lNetworkEvents & FD_READ) {
1228
1269
          /* This reallu OUGHT to check its return code. */
1229
1270
          (void)Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
1230
 
            
 
1271
 
1231
1272
          telrcv(conn, (unsigned char *)buf, nread);
1232
 
          
 
1273
 
1233
1274
          fflush(stdout);
1234
 
            
 
1275
 
1235
1276
          /* Negotiate if the peer has started negotiating,
1236
1277
             otherwise don't. We don't want to speak telnet with
1237
1278
             non-telnet servers, like POP or SMTP. */
1240
1281
            tn->already_negotiated = 1;
1241
1282
          }
1242
1283
        }
1243
 
          
 
1284
 
1244
1285
        if(events.lNetworkEvents & FD_CLOSE) {
1245
1286
          keepon = FALSE;
1246
1287
        }
1264
1305
  if (!FreeLibrary(wsock2))
1265
1306
    infof(data,"FreeLibrary(wsock2) failed (%d)",GetLastError());
1266
1307
#else
1267
 
  FD_ZERO (&readfd);            /* clear it */
1268
 
  FD_SET (sockfd, &readfd);
1269
 
  FD_SET (0, &readfd);
1270
 
 
1271
 
  keepfd = readfd;
 
1308
  pfd[0].fd = sockfd;
 
1309
  pfd[0].events = POLLIN;
 
1310
  pfd[1].fd = 0;
 
1311
  pfd[1].events = POLLIN;
 
1312
  interval_ms = 1 * 1000;
1272
1313
 
1273
1314
  while (keepon) {
1274
 
    struct timeval interval;
1275
 
 
1276
 
    readfd = keepfd;            /* set this every lap in the loop */
1277
 
    interval.tv_sec = 1;
1278
 
    interval.tv_usec = 0;
1279
 
 
1280
 
    switch (select (sockfd + 1, &readfd, NULL, NULL, &interval)) {
1281
 
    case -1:                    /* error, stop reading */
 
1315
    switch (Curl_poll(pfd, 2, interval_ms)) {
 
1316
    case -1:                    /* error, stop reading */
1282
1317
      keepon = FALSE;
1283
1318
      continue;
1284
 
    case 0:                     /* timeout */
 
1319
    case 0:                     /* timeout */
1285
1320
      break;
1286
 
    default:                    /* read! */
1287
 
      if(FD_ISSET(0, &readfd)) { /* read from stdin */
 
1321
    default:                    /* read! */
 
1322
      if(pfd[1].revents & POLLIN) { /* read from stdin */
1288
1323
        unsigned char outbuf[2];
1289
1324
        int out_count = 0;
1290
1325
        ssize_t bytes_written;
1291
1326
        char *buffer = buf;
1292
 
        
 
1327
 
1293
1328
        nread = read(0, buf, 255);
1294
1329
 
1295
1330
        while(nread--) {
1297
1332
          out_count = 1;
1298
1333
          if(outbuf[0] == CURL_IAC)
1299
1334
            outbuf[out_count++] = CURL_IAC;
1300
 
      
 
1335
 
1301
1336
          Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
1302
1337
                     out_count, &bytes_written);
1303
1338
        }
1304
1339
      }
1305
1340
 
1306
 
      if(FD_ISSET(sockfd, &readfd)) {
 
1341
      if(pfd[0].revents & POLLIN) {
1307
1342
        /* This OUGHT to check the return code... */
1308
1343
        (void)Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
1309
1344