00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifndef CURL_DISABLE_TELNET
00026
00027 #ifdef HAVE_NETINET_IN_H
00028 #include <netinet/in.h>
00029 #endif
00030 #ifdef HAVE_NETDB_H
00031 #include <netdb.h>
00032 #endif
00033 #ifdef HAVE_ARPA_INET_H
00034 #include <arpa/inet.h>
00035 #endif
00036 #ifdef HAVE_NET_IF_H
00037 #include <net/if.h>
00038 #endif
00039 #ifdef HAVE_SYS_IOCTL_H
00040 #include <sys/ioctl.h>
00041 #endif
00042
00043 #ifdef HAVE_SYS_PARAM_H
00044 #include <sys/param.h>
00045 #endif
00046
00047 #include "urldata.h"
00048 #include <curl/curl.h>
00049 #include "transfer.h"
00050 #include "sendf.h"
00051 #include "telnet.h"
00052 #include "connect.h"
00053 #include "progress.h"
00054 #include "system_win32.h"
00055
00056 #define TELOPTS
00057 #define TELCMDS
00058
00059 #include "arpa_telnet.h"
00060 #include "select.h"
00061 #include "strcase.h"
00062 #include "warnless.h"
00063
00064
00065 #include "curl_printf.h"
00066 #include "curl_memory.h"
00067 #include "memdebug.h"
00068
00069 #define SUBBUFSIZE 512
00070
00071 #define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer
00072 #define CURL_SB_TERM(x) \
00073 do { \
00074 x->subend = x->subpointer; \
00075 CURL_SB_CLEAR(x); \
00076 } WHILE_FALSE
00077 #define CURL_SB_ACCUM(x,c) \
00078 do { \
00079 if(x->subpointer < (x->subbuffer+sizeof x->subbuffer)) \
00080 *x->subpointer++ = (c); \
00081 } WHILE_FALSE
00082
00083 #define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
00084 #define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
00085 #define CURL_SB_EOF(x) (x->subpointer >= x->subend)
00086 #define CURL_SB_LEN(x) (x->subend - x->subpointer)
00087
00088 #ifdef CURL_DISABLE_VERBOSE_STRINGS
00089 #define printoption(a,b,c,d) Curl_nop_stmt
00090 #endif
00091
00092 #ifdef USE_WINSOCK
00093 typedef FARPROC WSOCK2_FUNC;
00094 static CURLcode check_wsock2(struct Curl_easy *data);
00095 #endif
00096
00097 static
00098 CURLcode telrcv(struct connectdata *,
00099 const unsigned char *inbuf,
00100 ssize_t count);
00101
00102 #ifndef CURL_DISABLE_VERBOSE_STRINGS
00103 static void printoption(struct Curl_easy *data,
00104 const char *direction,
00105 int cmd, int option);
00106 #endif
00107
00108 static void negotiate(struct connectdata *);
00109 static void send_negotiation(struct connectdata *, int cmd, int option);
00110 static void set_local_option(struct connectdata *, int cmd, int option);
00111 static void set_remote_option(struct connectdata *, int cmd, int option);
00112
00113 static void printsub(struct Curl_easy *data,
00114 int direction, unsigned char *pointer,
00115 size_t length);
00116 static void suboption(struct connectdata *);
00117 static void sendsuboption(struct connectdata *conn, int option);
00118
00119 static CURLcode telnet_do(struct connectdata *conn, bool *done);
00120 static CURLcode telnet_done(struct connectdata *conn,
00121 CURLcode, bool premature);
00122 static CURLcode send_telnet_data(struct connectdata *conn,
00123 char *buffer, ssize_t nread);
00124
00125
00126 #define CURL_NO 0
00127 #define CURL_YES 1
00128 #define CURL_WANTYES 2
00129 #define CURL_WANTNO 3
00130
00131 #define CURL_EMPTY 0
00132 #define CURL_OPPOSITE 1
00133
00134
00135
00136
00137 typedef enum
00138 {
00139 CURL_TS_DATA = 0,
00140 CURL_TS_IAC,
00141 CURL_TS_WILL,
00142 CURL_TS_WONT,
00143 CURL_TS_DO,
00144 CURL_TS_DONT,
00145 CURL_TS_CR,
00146 CURL_TS_SB,
00147 CURL_TS_SE
00148 } TelnetReceive;
00149
00150 struct TELNET {
00151 int please_negotiate;
00152 int already_negotiated;
00153 int us[256];
00154 int usq[256];
00155 int us_preferred[256];
00156 int him[256];
00157 int himq[256];
00158 int him_preferred[256];
00159 int subnegotiation[256];
00160 char subopt_ttype[32];
00161 char subopt_xdisploc[128];
00162 unsigned short subopt_wsx;
00163 unsigned short subopt_wsy;
00164 struct curl_slist *telnet_vars;
00165
00166
00167 unsigned char subbuffer[SUBBUFSIZE];
00168 unsigned char *subpointer, *subend;
00169
00170 TelnetReceive telrcv_state;
00171 };
00172
00173
00174
00175
00176
00177
00178 const struct Curl_handler Curl_handler_telnet = {
00179 "TELNET",
00180 ZERO_NULL,
00181 telnet_do,
00182 telnet_done,
00183 ZERO_NULL,
00184 ZERO_NULL,
00185 ZERO_NULL,
00186 ZERO_NULL,
00187 ZERO_NULL,
00188 ZERO_NULL,
00189 ZERO_NULL,
00190 ZERO_NULL,
00191 ZERO_NULL,
00192 ZERO_NULL,
00193 PORT_TELNET,
00194 CURLPROTO_TELNET,
00195 PROTOPT_NONE | PROTOPT_NOURLQUERY
00196 };
00197
00198
00199 #ifdef USE_WINSOCK
00200 static CURLcode
00201 check_wsock2(struct Curl_easy *data)
00202 {
00203 int err;
00204 WORD wVersionRequested;
00205 WSADATA wsaData;
00206
00207 DEBUGASSERT(data);
00208
00209
00210 wVersionRequested = MAKEWORD(2, 0);
00211
00212 err = WSAStartup(wVersionRequested, &wsaData);
00213
00214
00215
00216 if(err != 0) {
00217 failf(data,"WSAStartup failed (%d)",err);
00218 return CURLE_FAILED_INIT;
00219 }
00220
00221
00222
00223 WSACleanup();
00224
00225
00226 if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
00227 HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) {
00228
00229 failf(data, "insufficient winsock version to support "
00230 "telnet");
00231 return CURLE_FAILED_INIT;
00232 }
00233
00234
00235 return CURLE_OK;
00236 }
00237 #endif
00238
00239 static
00240 CURLcode init_telnet(struct connectdata *conn)
00241 {
00242 struct TELNET *tn;
00243
00244 tn = calloc(1, sizeof(struct TELNET));
00245 if(!tn)
00246 return CURLE_OUT_OF_MEMORY;
00247
00248 conn->data->req.protop = tn;
00249
00250 tn->telrcv_state = CURL_TS_DATA;
00251
00252
00253 CURL_SB_CLEAR(tn);
00254
00255
00256 tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES;
00257 tn->him_preferred[CURL_TELOPT_SGA] = CURL_YES;
00258
00259
00260
00261
00262
00263
00264 tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES;
00265 tn->him_preferred[CURL_TELOPT_BINARY] = CURL_YES;
00266
00267
00268
00269
00270
00271
00272
00273 tn->him_preferred[CURL_TELOPT_ECHO] = CURL_YES;
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES;
00287 return CURLE_OK;
00288 }
00289
00290 static void negotiate(struct connectdata *conn)
00291 {
00292 int i;
00293 struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
00294
00295 for(i = 0;i < CURL_NTELOPTS;i++) {
00296 if(i==CURL_TELOPT_ECHO)
00297 continue;
00298
00299 if(tn->us_preferred[i] == CURL_YES)
00300 set_local_option(conn, i, CURL_YES);
00301
00302 if(tn->him_preferred[i] == CURL_YES)
00303 set_remote_option(conn, i, CURL_YES);
00304 }
00305 }
00306
00307 #ifndef CURL_DISABLE_VERBOSE_STRINGS
00308 static void printoption(struct Curl_easy *data,
00309 const char *direction, int cmd, int option)
00310 {
00311 const char *fmt;
00312 const char *opt;
00313
00314 if(data->set.verbose) {
00315 if(cmd == CURL_IAC) {
00316 if(CURL_TELCMD_OK(option))
00317 infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
00318 else
00319 infof(data, "%s IAC %d\n", direction, option);
00320 }
00321 else {
00322 fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
00323 (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
00324 if(fmt) {
00325 if(CURL_TELOPT_OK(option))
00326 opt = CURL_TELOPT(option);
00327 else if(option == CURL_TELOPT_EXOPL)
00328 opt = "EXOPL";
00329 else
00330 opt = NULL;
00331
00332 if(opt)
00333 infof(data, "%s %s %s\n", direction, fmt, opt);
00334 else
00335 infof(data, "%s %s %d\n", direction, fmt, option);
00336 }
00337 else
00338 infof(data, "%s %d %d\n", direction, cmd, option);
00339 }
00340 }
00341 }
00342 #endif
00343
00344 static void send_negotiation(struct connectdata *conn, int cmd, int option)
00345 {
00346 unsigned char buf[3];
00347 ssize_t bytes_written;
00348 int err;
00349 struct Curl_easy *data = conn->data;
00350
00351 buf[0] = CURL_IAC;
00352 buf[1] = (unsigned char)cmd;
00353 buf[2] = (unsigned char)option;
00354
00355 bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
00356 if(bytes_written < 0) {
00357 err = SOCKERRNO;
00358 failf(data,"Sending data failed (%d)",err);
00359 }
00360
00361 printoption(conn->data, "SENT", cmd, option);
00362 }
00363
00364 static
00365 void set_remote_option(struct connectdata *conn, int option, int newstate)
00366 {
00367 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
00368 if(newstate == CURL_YES) {
00369 switch(tn->him[option]) {
00370 case CURL_NO:
00371 tn->him[option] = CURL_WANTYES;
00372 send_negotiation(conn, CURL_DO, option);
00373 break;
00374
00375 case CURL_YES:
00376
00377 break;
00378
00379 case CURL_WANTNO:
00380 switch(tn->himq[option]) {
00381 case CURL_EMPTY:
00382
00383 tn->himq[option] = CURL_OPPOSITE;
00384 break;
00385 case CURL_OPPOSITE:
00386
00387 break;
00388 }
00389 break;
00390
00391 case CURL_WANTYES:
00392 switch(tn->himq[option]) {
00393 case CURL_EMPTY:
00394
00395 break;
00396 case CURL_OPPOSITE:
00397 tn->himq[option] = CURL_EMPTY;
00398 break;
00399 }
00400 break;
00401 }
00402 }
00403 else {
00404 switch(tn->him[option]) {
00405 case CURL_NO:
00406
00407 break;
00408
00409 case CURL_YES:
00410 tn->him[option] = CURL_WANTNO;
00411 send_negotiation(conn, CURL_DONT, option);
00412 break;
00413
00414 case CURL_WANTNO:
00415 switch(tn->himq[option]) {
00416 case CURL_EMPTY:
00417
00418 break;
00419 case CURL_OPPOSITE:
00420 tn->himq[option] = CURL_EMPTY;
00421 break;
00422 }
00423 break;
00424
00425 case CURL_WANTYES:
00426 switch(tn->himq[option]) {
00427 case CURL_EMPTY:
00428 tn->himq[option] = CURL_OPPOSITE;
00429 break;
00430 case CURL_OPPOSITE:
00431 break;
00432 }
00433 break;
00434 }
00435 }
00436 }
00437
00438 static
00439 void rec_will(struct connectdata *conn, int option)
00440 {
00441 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
00442 switch(tn->him[option]) {
00443 case CURL_NO:
00444 if(tn->him_preferred[option] == CURL_YES) {
00445 tn->him[option] = CURL_YES;
00446 send_negotiation(conn, CURL_DO, option);
00447 }
00448 else
00449 send_negotiation(conn, CURL_DONT, option);
00450
00451 break;
00452
00453 case CURL_YES:
00454
00455 break;
00456
00457 case CURL_WANTNO:
00458 switch(tn->himq[option]) {
00459 case CURL_EMPTY:
00460
00461 tn->him[option] = CURL_NO;
00462 break;
00463 case CURL_OPPOSITE:
00464
00465 tn->him[option] = CURL_YES;
00466 tn->himq[option] = CURL_EMPTY;
00467 break;
00468 }
00469 break;
00470
00471 case CURL_WANTYES:
00472 switch(tn->himq[option]) {
00473 case CURL_EMPTY:
00474 tn->him[option] = CURL_YES;
00475 break;
00476 case CURL_OPPOSITE:
00477 tn->him[option] = CURL_WANTNO;
00478 tn->himq[option] = CURL_EMPTY;
00479 send_negotiation(conn, CURL_DONT, option);
00480 break;
00481 }
00482 break;
00483 }
00484 }
00485
00486 static
00487 void rec_wont(struct connectdata *conn, int option)
00488 {
00489 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
00490 switch(tn->him[option]) {
00491 case CURL_NO:
00492
00493 break;
00494
00495 case CURL_YES:
00496 tn->him[option] = CURL_NO;
00497 send_negotiation(conn, CURL_DONT, option);
00498 break;
00499
00500 case CURL_WANTNO:
00501 switch(tn->himq[option]) {
00502 case CURL_EMPTY:
00503 tn->him[option] = CURL_NO;
00504 break;
00505
00506 case CURL_OPPOSITE:
00507 tn->him[option] = CURL_WANTYES;
00508 tn->himq[option] = CURL_EMPTY;
00509 send_negotiation(conn, CURL_DO, option);
00510 break;
00511 }
00512 break;
00513
00514 case CURL_WANTYES:
00515 switch(tn->himq[option]) {
00516 case CURL_EMPTY:
00517 tn->him[option] = CURL_NO;
00518 break;
00519 case CURL_OPPOSITE:
00520 tn->him[option] = CURL_NO;
00521 tn->himq[option] = CURL_EMPTY;
00522 break;
00523 }
00524 break;
00525 }
00526 }
00527
00528 static void
00529 set_local_option(struct connectdata *conn, int option, int newstate)
00530 {
00531 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
00532 if(newstate == CURL_YES) {
00533 switch(tn->us[option]) {
00534 case CURL_NO:
00535 tn->us[option] = CURL_WANTYES;
00536 send_negotiation(conn, CURL_WILL, option);
00537 break;
00538
00539 case CURL_YES:
00540
00541 break;
00542
00543 case CURL_WANTNO:
00544 switch(tn->usq[option]) {
00545 case CURL_EMPTY:
00546
00547 tn->usq[option] = CURL_OPPOSITE;
00548 break;
00549 case CURL_OPPOSITE:
00550
00551 break;
00552 }
00553 break;
00554
00555 case CURL_WANTYES:
00556 switch(tn->usq[option]) {
00557 case CURL_EMPTY:
00558
00559 break;
00560 case CURL_OPPOSITE:
00561 tn->usq[option] = CURL_EMPTY;
00562 break;
00563 }
00564 break;
00565 }
00566 }
00567 else {
00568 switch(tn->us[option]) {
00569 case CURL_NO:
00570
00571 break;
00572
00573 case CURL_YES:
00574 tn->us[option] = CURL_WANTNO;
00575 send_negotiation(conn, CURL_WONT, option);
00576 break;
00577
00578 case CURL_WANTNO:
00579 switch(tn->usq[option]) {
00580 case CURL_EMPTY:
00581
00582 break;
00583 case CURL_OPPOSITE:
00584 tn->usq[option] = CURL_EMPTY;
00585 break;
00586 }
00587 break;
00588
00589 case CURL_WANTYES:
00590 switch(tn->usq[option]) {
00591 case CURL_EMPTY:
00592 tn->usq[option] = CURL_OPPOSITE;
00593 break;
00594 case CURL_OPPOSITE:
00595 break;
00596 }
00597 break;
00598 }
00599 }
00600 }
00601
00602 static
00603 void rec_do(struct connectdata *conn, int option)
00604 {
00605 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
00606 switch(tn->us[option]) {
00607 case CURL_NO:
00608 if(tn->us_preferred[option] == CURL_YES) {
00609 tn->us[option] = CURL_YES;
00610 send_negotiation(conn, CURL_WILL, option);
00611 if(tn->subnegotiation[option] == CURL_YES)
00612
00613 sendsuboption(conn, option);
00614 }
00615 else if(tn->subnegotiation[option] == CURL_YES) {
00616
00617 tn->us[option] = CURL_YES;
00618 send_negotiation(conn, CURL_WILL, option);
00619 sendsuboption(conn, option);
00620 }
00621 else
00622 send_negotiation(conn, CURL_WONT, option);
00623 break;
00624
00625 case CURL_YES:
00626
00627 break;
00628
00629 case CURL_WANTNO:
00630 switch(tn->usq[option]) {
00631 case CURL_EMPTY:
00632
00633 tn->us[option] = CURL_NO;
00634 break;
00635 case CURL_OPPOSITE:
00636
00637 tn->us[option] = CURL_YES;
00638 tn->usq[option] = CURL_EMPTY;
00639 break;
00640 }
00641 break;
00642
00643 case CURL_WANTYES:
00644 switch(tn->usq[option]) {
00645 case CURL_EMPTY:
00646 tn->us[option] = CURL_YES;
00647 if(tn->subnegotiation[option] == CURL_YES) {
00648
00649 sendsuboption(conn, option);
00650 }
00651 break;
00652 case CURL_OPPOSITE:
00653 tn->us[option] = CURL_WANTNO;
00654 tn->himq[option] = CURL_EMPTY;
00655 send_negotiation(conn, CURL_WONT, option);
00656 break;
00657 }
00658 break;
00659 }
00660 }
00661
00662 static
00663 void rec_dont(struct connectdata *conn, int option)
00664 {
00665 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
00666 switch(tn->us[option]) {
00667 case CURL_NO:
00668
00669 break;
00670
00671 case CURL_YES:
00672 tn->us[option] = CURL_NO;
00673 send_negotiation(conn, CURL_WONT, option);
00674 break;
00675
00676 case CURL_WANTNO:
00677 switch(tn->usq[option]) {
00678 case CURL_EMPTY:
00679 tn->us[option] = CURL_NO;
00680 break;
00681
00682 case CURL_OPPOSITE:
00683 tn->us[option] = CURL_WANTYES;
00684 tn->usq[option] = CURL_EMPTY;
00685 send_negotiation(conn, CURL_WILL, option);
00686 break;
00687 }
00688 break;
00689
00690 case CURL_WANTYES:
00691 switch(tn->usq[option]) {
00692 case CURL_EMPTY:
00693 tn->us[option] = CURL_NO;
00694 break;
00695 case CURL_OPPOSITE:
00696 tn->us[option] = CURL_NO;
00697 tn->usq[option] = CURL_EMPTY;
00698 break;
00699 }
00700 break;
00701 }
00702 }
00703
00704
00705 static void printsub(struct Curl_easy *data,
00706 int direction,
00707 unsigned char *pointer,
00708 size_t length)
00709 {
00710 unsigned int i = 0;
00711
00712 if(data->set.verbose) {
00713 if(direction) {
00714 infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
00715 if(length >= 3) {
00716 int j;
00717
00718 i = pointer[length-2];
00719 j = pointer[length-1];
00720
00721 if(i != CURL_IAC || j != CURL_SE) {
00722 infof(data, "(terminated by ");
00723 if(CURL_TELOPT_OK(i))
00724 infof(data, "%s ", CURL_TELOPT(i));
00725 else if(CURL_TELCMD_OK(i))
00726 infof(data, "%s ", CURL_TELCMD(i));
00727 else
00728 infof(data, "%u ", i);
00729 if(CURL_TELOPT_OK(j))
00730 infof(data, "%s", CURL_TELOPT(j));
00731 else if(CURL_TELCMD_OK(j))
00732 infof(data, "%s", CURL_TELCMD(j));
00733 else
00734 infof(data, "%d", j);
00735 infof(data, ", not IAC SE!) ");
00736 }
00737 }
00738 length -= 2;
00739 }
00740 if(length < 1) {
00741 infof(data, "(Empty suboption?)");
00742 return;
00743 }
00744
00745 if(CURL_TELOPT_OK(pointer[0])) {
00746 switch(pointer[0]) {
00747 case CURL_TELOPT_TTYPE:
00748 case CURL_TELOPT_XDISPLOC:
00749 case CURL_TELOPT_NEW_ENVIRON:
00750 case CURL_TELOPT_NAWS:
00751 infof(data, "%s", CURL_TELOPT(pointer[0]));
00752 break;
00753 default:
00754 infof(data, "%s (unsupported)", CURL_TELOPT(pointer[0]));
00755 break;
00756 }
00757 }
00758 else
00759 infof(data, "%d (unknown)", pointer[i]);
00760
00761 switch(pointer[0]) {
00762 case CURL_TELOPT_NAWS:
00763 if(length > 4)
00764 infof(data, "Width: %hu ; Height: %hu", (pointer[1]<<8) | pointer[2],
00765 (pointer[3]<<8) | pointer[4]);
00766 break;
00767 default:
00768 switch(pointer[1]) {
00769 case CURL_TELQUAL_IS:
00770 infof(data, " IS");
00771 break;
00772 case CURL_TELQUAL_SEND:
00773 infof(data, " SEND");
00774 break;
00775 case CURL_TELQUAL_INFO:
00776 infof(data, " INFO/REPLY");
00777 break;
00778 case CURL_TELQUAL_NAME:
00779 infof(data, " NAME");
00780 break;
00781 }
00782
00783 switch(pointer[0]) {
00784 case CURL_TELOPT_TTYPE:
00785 case CURL_TELOPT_XDISPLOC:
00786 pointer[length] = 0;
00787 infof(data, " \"%s\"", &pointer[2]);
00788 break;
00789 case CURL_TELOPT_NEW_ENVIRON:
00790 if(pointer[1] == CURL_TELQUAL_IS) {
00791 infof(data, " ");
00792 for(i = 3;i < length;i++) {
00793 switch(pointer[i]) {
00794 case CURL_NEW_ENV_VAR:
00795 infof(data, ", ");
00796 break;
00797 case CURL_NEW_ENV_VALUE:
00798 infof(data, " = ");
00799 break;
00800 default:
00801 infof(data, "%c", pointer[i]);
00802 break;
00803 }
00804 }
00805 }
00806 break;
00807 default:
00808 for(i = 2; i < length; i++)
00809 infof(data, " %.2x", pointer[i]);
00810 break;
00811 }
00812 }
00813 if(direction)
00814 infof(data, "\n");
00815 }
00816 }
00817
00818 static CURLcode check_telnet_options(struct connectdata *conn)
00819 {
00820 struct curl_slist *head;
00821 struct curl_slist *beg;
00822 char option_keyword[128] = "";
00823 char option_arg[256] = "";
00824 struct Curl_easy *data = conn->data;
00825 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
00826 CURLcode result = CURLE_OK;
00827 int binary_option;
00828
00829
00830
00831 if(conn->bits.user_passwd) {
00832 snprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
00833 beg = curl_slist_append(tn->telnet_vars, option_arg);
00834 if(!beg) {
00835 curl_slist_free_all(tn->telnet_vars);
00836 tn->telnet_vars = NULL;
00837 return CURLE_OUT_OF_MEMORY;
00838 }
00839 tn->telnet_vars = beg;
00840 tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
00841 }
00842
00843 for(head = data->set.telnet_options; head; head=head->next) {
00844 if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
00845 option_keyword, option_arg) == 2) {
00846
00847
00848 if(strcasecompare(option_keyword, "TTYPE")) {
00849 strncpy(tn->subopt_ttype, option_arg, 31);
00850 tn->subopt_ttype[31] = 0;
00851 tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
00852 continue;
00853 }
00854
00855
00856 if(strcasecompare(option_keyword, "XDISPLOC")) {
00857 strncpy(tn->subopt_xdisploc, option_arg, 127);
00858 tn->subopt_xdisploc[127] = 0;
00859 tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
00860 continue;
00861 }
00862
00863
00864 if(strcasecompare(option_keyword, "NEW_ENV")) {
00865 beg = curl_slist_append(tn->telnet_vars, option_arg);
00866 if(!beg) {
00867 result = CURLE_OUT_OF_MEMORY;
00868 break;
00869 }
00870 tn->telnet_vars = beg;
00871 tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
00872 continue;
00873 }
00874
00875
00876 if(strcasecompare(option_keyword, "WS")) {
00877 if(sscanf(option_arg, "%hu%*[xX]%hu",
00878 &tn->subopt_wsx, &tn->subopt_wsy) == 2)
00879 tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
00880 else {
00881 failf(data, "Syntax error in telnet option: %s", head->data);
00882 result = CURLE_TELNET_OPTION_SYNTAX;
00883 break;
00884 }
00885 continue;
00886 }
00887
00888
00889 if(strcasecompare(option_keyword, "BINARY")) {
00890 binary_option=atoi(option_arg);
00891 if(binary_option!=1) {
00892 tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
00893 tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
00894 }
00895 continue;
00896 }
00897
00898 failf(data, "Unknown telnet option %s", head->data);
00899 result = CURLE_UNKNOWN_TELNET_OPTION;
00900 break;
00901 }
00902 else {
00903 failf(data, "Syntax error in telnet option: %s", head->data);
00904 result = CURLE_TELNET_OPTION_SYNTAX;
00905 break;
00906 }
00907 }
00908
00909 if(result) {
00910 curl_slist_free_all(tn->telnet_vars);
00911 tn->telnet_vars = NULL;
00912 }
00913
00914 return result;
00915 }
00916
00917
00918
00919
00920
00921
00922
00923
00924 static void suboption(struct connectdata *conn)
00925 {
00926 struct curl_slist *v;
00927 unsigned char temp[2048];
00928 ssize_t bytes_written;
00929 size_t len;
00930 size_t tmplen;
00931 int err;
00932 char varname[128] = "";
00933 char varval[128] = "";
00934 struct Curl_easy *data = conn->data;
00935 struct TELNET *tn = (struct TELNET *)data->req.protop;
00936
00937 printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
00938 switch(CURL_SB_GET(tn)) {
00939 case CURL_TELOPT_TTYPE:
00940 len = strlen(tn->subopt_ttype) + 4 + 2;
00941 snprintf((char *)temp, sizeof(temp),
00942 "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE,
00943 CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, CURL_SE);
00944 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
00945 if(bytes_written < 0) {
00946 err = SOCKERRNO;
00947 failf(data,"Sending data failed (%d)",err);
00948 }
00949 printsub(data, '>', &temp[2], len-2);
00950 break;
00951 case CURL_TELOPT_XDISPLOC:
00952 len = strlen(tn->subopt_xdisploc) + 4 + 2;
00953 snprintf((char *)temp, sizeof(temp),
00954 "%c%c%c%c%s%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC,
00955 CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, CURL_SE);
00956 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
00957 if(bytes_written < 0) {
00958 err = SOCKERRNO;
00959 failf(data,"Sending data failed (%d)",err);
00960 }
00961 printsub(data, '>', &temp[2], len-2);
00962 break;
00963 case CURL_TELOPT_NEW_ENVIRON:
00964 snprintf((char *)temp, sizeof(temp),
00965 "%c%c%c%c", CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON,
00966 CURL_TELQUAL_IS);
00967 len = 4;
00968
00969 for(v = tn->telnet_vars;v;v = v->next) {
00970 tmplen = (strlen(v->data) + 1);
00971
00972 if(len + tmplen < (int)sizeof(temp)-6) {
00973 if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
00974 snprintf((char *)&temp[len], sizeof(temp) - len,
00975 "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
00976 CURL_NEW_ENV_VALUE, varval);
00977 len += tmplen;
00978 }
00979 }
00980 }
00981 snprintf((char *)&temp[len], sizeof(temp) - len,
00982 "%c%c", CURL_IAC, CURL_SE);
00983 len += 2;
00984 bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len);
00985 if(bytes_written < 0) {
00986 err = SOCKERRNO;
00987 failf(data,"Sending data failed (%d)",err);
00988 }
00989 printsub(data, '>', &temp[2], len-2);
00990 break;
00991 }
00992 return;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002 static void sendsuboption(struct connectdata *conn, int option)
01003 {
01004 ssize_t bytes_written;
01005 int err;
01006 unsigned short x, y;
01007 unsigned char *uc1, *uc2;
01008
01009 struct Curl_easy *data = conn->data;
01010 struct TELNET *tn = (struct TELNET *)data->req.protop;
01011
01012 switch(option) {
01013 case CURL_TELOPT_NAWS:
01014
01015 CURL_SB_CLEAR(tn);
01016 CURL_SB_ACCUM(tn, CURL_IAC);
01017 CURL_SB_ACCUM(tn, CURL_SB);
01018 CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
01019
01020
01021 x=htons(tn->subopt_wsx);
01022 y=htons(tn->subopt_wsy);
01023 uc1 = (unsigned char *)&x;
01024 uc2 = (unsigned char *)&y;
01025 CURL_SB_ACCUM(tn, uc1[0]);
01026 CURL_SB_ACCUM(tn, uc1[1]);
01027 CURL_SB_ACCUM(tn, uc2[0]);
01028 CURL_SB_ACCUM(tn, uc2[1]);
01029
01030 CURL_SB_ACCUM(tn, CURL_IAC);
01031 CURL_SB_ACCUM(tn, CURL_SE);
01032 CURL_SB_TERM(tn);
01033
01034
01035 printsub(data, '>', (unsigned char *)tn->subbuffer+2,
01036 CURL_SB_LEN(tn)-2);
01037
01038
01039 bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3);
01040 if(bytes_written < 0) {
01041 err = SOCKERRNO;
01042 failf(data, "Sending data failed (%d)", err);
01043 }
01044
01045
01046 send_telnet_data(conn, (char *)tn->subbuffer+3, 4);
01047
01048 bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer+7, 2);
01049 if(bytes_written < 0) {
01050 err = SOCKERRNO;
01051 failf(data, "Sending data failed (%d)", err);
01052 }
01053 break;
01054 }
01055 }
01056
01057
01058 static
01059 CURLcode telrcv(struct connectdata *conn,
01060 const unsigned char *inbuf,
01061 ssize_t count)
01062 {
01063 unsigned char c;
01064 CURLcode result;
01065 int in = 0;
01066 int startwrite=-1;
01067 struct Curl_easy *data = conn->data;
01068 struct TELNET *tn = (struct TELNET *)data->req.protop;
01069
01070 #define startskipping() \
01071 if(startwrite >= 0) { \
01072 result = Curl_client_write(conn, \
01073 CLIENTWRITE_BODY, \
01074 (char *)&inbuf[startwrite], \
01075 in-startwrite); \
01076 if(result) \
01077 return result; \
01078 } \
01079 startwrite = -1
01080
01081 #define writebyte() \
01082 if(startwrite < 0) \
01083 startwrite = in
01084
01085 #define bufferflush() startskipping()
01086
01087 while(count--) {
01088 c = inbuf[in];
01089
01090 switch(tn->telrcv_state) {
01091 case CURL_TS_CR:
01092 tn->telrcv_state = CURL_TS_DATA;
01093 if(c == '\0') {
01094 startskipping();
01095 break;
01096 }
01097 writebyte();
01098 break;
01099
01100 case CURL_TS_DATA:
01101 if(c == CURL_IAC) {
01102 tn->telrcv_state = CURL_TS_IAC;
01103 startskipping();
01104 break;
01105 }
01106 else if(c == '\r')
01107 tn->telrcv_state = CURL_TS_CR;
01108 writebyte();
01109 break;
01110
01111 case CURL_TS_IAC:
01112 process_iac:
01113 DEBUGASSERT(startwrite < 0);
01114 switch(c) {
01115 case CURL_WILL:
01116 tn->telrcv_state = CURL_TS_WILL;
01117 break;
01118 case CURL_WONT:
01119 tn->telrcv_state = CURL_TS_WONT;
01120 break;
01121 case CURL_DO:
01122 tn->telrcv_state = CURL_TS_DO;
01123 break;
01124 case CURL_DONT:
01125 tn->telrcv_state = CURL_TS_DONT;
01126 break;
01127 case CURL_SB:
01128 CURL_SB_CLEAR(tn);
01129 tn->telrcv_state = CURL_TS_SB;
01130 break;
01131 case CURL_IAC:
01132 tn->telrcv_state = CURL_TS_DATA;
01133 writebyte();
01134 break;
01135 case CURL_DM:
01136 case CURL_NOP:
01137 case CURL_GA:
01138 default:
01139 tn->telrcv_state = CURL_TS_DATA;
01140 printoption(data, "RCVD", CURL_IAC, c);
01141 break;
01142 }
01143 break;
01144
01145 case CURL_TS_WILL:
01146 printoption(data, "RCVD", CURL_WILL, c);
01147 tn->please_negotiate = 1;
01148 rec_will(conn, c);
01149 tn->telrcv_state = CURL_TS_DATA;
01150 break;
01151
01152 case CURL_TS_WONT:
01153 printoption(data, "RCVD", CURL_WONT, c);
01154 tn->please_negotiate = 1;
01155 rec_wont(conn, c);
01156 tn->telrcv_state = CURL_TS_DATA;
01157 break;
01158
01159 case CURL_TS_DO:
01160 printoption(data, "RCVD", CURL_DO, c);
01161 tn->please_negotiate = 1;
01162 rec_do(conn, c);
01163 tn->telrcv_state = CURL_TS_DATA;
01164 break;
01165
01166 case CURL_TS_DONT:
01167 printoption(data, "RCVD", CURL_DONT, c);
01168 tn->please_negotiate = 1;
01169 rec_dont(conn, c);
01170 tn->telrcv_state = CURL_TS_DATA;
01171 break;
01172
01173 case CURL_TS_SB:
01174 if(c == CURL_IAC)
01175 tn->telrcv_state = CURL_TS_SE;
01176 else
01177 CURL_SB_ACCUM(tn, c);
01178 break;
01179
01180 case CURL_TS_SE:
01181 if(c != CURL_SE) {
01182 if(c != CURL_IAC) {
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 CURL_SB_ACCUM(tn, CURL_IAC);
01193 CURL_SB_ACCUM(tn, c);
01194 tn->subpointer -= 2;
01195 CURL_SB_TERM(tn);
01196
01197 printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
01198 suboption(conn);
01199 tn->telrcv_state = CURL_TS_IAC;
01200 goto process_iac;
01201 }
01202 CURL_SB_ACCUM(tn, c);
01203 tn->telrcv_state = CURL_TS_SB;
01204 }
01205 else
01206 {
01207 CURL_SB_ACCUM(tn, CURL_IAC);
01208 CURL_SB_ACCUM(tn, CURL_SE);
01209 tn->subpointer -= 2;
01210 CURL_SB_TERM(tn);
01211 suboption(conn);
01212 tn->telrcv_state = CURL_TS_DATA;
01213 }
01214 break;
01215 }
01216 ++in;
01217 }
01218 bufferflush();
01219 return CURLE_OK;
01220 }
01221
01222
01223
01224 static CURLcode send_telnet_data(struct connectdata *conn,
01225 char *buffer, ssize_t nread)
01226 {
01227 unsigned char outbuf[2];
01228 ssize_t bytes_written, total_written;
01229 int out_count;
01230 CURLcode result = CURLE_OK;
01231
01232 while(!result && nread--) {
01233 outbuf[0] = *buffer++;
01234 out_count = 1;
01235 if(outbuf[0] == CURL_IAC)
01236 outbuf[out_count++] = CURL_IAC;
01237
01238 total_written = 0;
01239 do {
01240
01241 struct pollfd pfd[1];
01242 pfd[0].fd = conn->sock[FIRSTSOCKET];
01243 pfd[0].events = POLLOUT;
01244 switch(Curl_poll(pfd, 1, -1)) {
01245 case -1:
01246 case 0:
01247 result = CURLE_SEND_ERROR;
01248 break;
01249 default:
01250 bytes_written = 0;
01251 result = Curl_write(conn, conn->sock[FIRSTSOCKET],
01252 outbuf+total_written, out_count-total_written,
01253 &bytes_written);
01254 total_written += bytes_written;
01255 break;
01256 }
01257
01258 } while(!result && total_written < out_count);
01259 }
01260 return result;
01261 }
01262
01263 static CURLcode telnet_done(struct connectdata *conn,
01264 CURLcode status, bool premature)
01265 {
01266 struct TELNET *tn = (struct TELNET *)conn->data->req.protop;
01267 (void)status;
01268 (void)premature;
01269
01270 if(!tn)
01271 return CURLE_OK;
01272
01273 curl_slist_free_all(tn->telnet_vars);
01274 tn->telnet_vars = NULL;
01275
01276 Curl_safefree(conn->data->req.protop);
01277
01278 return CURLE_OK;
01279 }
01280
01281 static CURLcode telnet_do(struct connectdata *conn, bool *done)
01282 {
01283 CURLcode result;
01284 struct Curl_easy *data = conn->data;
01285 curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
01286 #ifdef USE_WINSOCK
01287 HMODULE wsock2;
01288 WSOCK2_FUNC close_event_func;
01289 WSOCK2_FUNC create_event_func;
01290 WSOCK2_FUNC event_select_func;
01291 WSOCK2_FUNC enum_netevents_func;
01292 WSAEVENT event_handle;
01293 WSANETWORKEVENTS events;
01294 HANDLE stdin_handle;
01295 HANDLE objs[2];
01296 DWORD obj_count;
01297 DWORD wait_timeout;
01298 DWORD waitret;
01299 DWORD readfile_read;
01300 int err;
01301 #else
01302 int interval_ms;
01303 struct pollfd pfd[2];
01304 int poll_cnt;
01305 curl_off_t total_dl = 0;
01306 curl_off_t total_ul = 0;
01307 #endif
01308 ssize_t nread;
01309 struct timeval now;
01310 bool keepon = TRUE;
01311 char *buf = data->state.buffer;
01312 struct TELNET *tn;
01313
01314 *done = TRUE;
01315
01316 result = init_telnet(conn);
01317 if(result)
01318 return result;
01319
01320 tn = (struct TELNET *)data->req.protop;
01321
01322 result = check_telnet_options(conn);
01323 if(result)
01324 return result;
01325
01326 #ifdef USE_WINSOCK
01327
01328
01329
01330
01331 result = check_wsock2(data);
01332 if(result)
01333 return result;
01334
01335
01336
01337 wsock2 = Curl_load_library(TEXT("WS2_32.DLL"));
01338 if(wsock2 == NULL) {
01339 failf(data, "failed to load WS2_32.DLL (%d)", ERRNO);
01340 return CURLE_FAILED_INIT;
01341 }
01342
01343
01344 create_event_func = GetProcAddress(wsock2, "WSACreateEvent");
01345 if(create_event_func == NULL) {
01346 failf(data, "failed to find WSACreateEvent function (%d)", ERRNO);
01347 FreeLibrary(wsock2);
01348 return CURLE_FAILED_INIT;
01349 }
01350
01351
01352 close_event_func = GetProcAddress(wsock2, "WSACloseEvent");
01353 if(close_event_func == NULL) {
01354 failf(data, "failed to find WSACloseEvent function (%d)", ERRNO);
01355 FreeLibrary(wsock2);
01356 return CURLE_FAILED_INIT;
01357 }
01358
01359
01360 event_select_func = GetProcAddress(wsock2, "WSAEventSelect");
01361 if(event_select_func == NULL) {
01362 failf(data, "failed to find WSAEventSelect function (%d)", ERRNO);
01363 FreeLibrary(wsock2);
01364 return CURLE_FAILED_INIT;
01365 }
01366
01367
01368 enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents");
01369 if(enum_netevents_func == NULL) {
01370 failf(data, "failed to find WSAEnumNetworkEvents function (%d)", ERRNO);
01371 FreeLibrary(wsock2);
01372 return CURLE_FAILED_INIT;
01373 }
01374
01375
01376
01377
01378
01379
01380
01381 event_handle = (WSAEVENT)create_event_func();
01382 if(event_handle == WSA_INVALID_EVENT) {
01383 failf(data, "WSACreateEvent failed (%d)", SOCKERRNO);
01384 FreeLibrary(wsock2);
01385 return CURLE_FAILED_INIT;
01386 }
01387
01388
01389 if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) ==
01390 SOCKET_ERROR) {
01391 close_event_func(event_handle);
01392 FreeLibrary(wsock2);
01393 return CURLE_OK;
01394 }
01395
01396
01397 stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
01398
01399
01400 objs[0] = event_handle;
01401 objs[1] = stdin_handle;
01402
01403
01404
01405 if(GetFileType(stdin_handle) == FILE_TYPE_PIPE ||
01406 data->set.is_fread_set) {
01407
01408 obj_count = 1;
01409
01410 wait_timeout = 100;
01411 }
01412 else {
01413 obj_count = 2;
01414 wait_timeout = 1000;
01415 }
01416
01417
01418 while(keepon) {
01419 waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
01420 switch(waitret) {
01421 case WAIT_TIMEOUT:
01422 {
01423 for(;;) {
01424 if(data->set.is_fread_set) {
01425
01426 result = (int)data->state.fread_func(buf, 1, BUFSIZE - 1,
01427 data->state.in);
01428 if(result == CURL_READFUNC_ABORT) {
01429 keepon = FALSE;
01430 result = CURLE_READ_ERROR;
01431 break;
01432 }
01433
01434 if(result == CURL_READFUNC_PAUSE)
01435 break;
01436
01437 if(result == 0)
01438 break;
01439
01440 readfile_read = result;
01441 }
01442 else {
01443
01444 if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL,
01445 &readfile_read, NULL)) {
01446 keepon = FALSE;
01447 result = CURLE_READ_ERROR;
01448 break;
01449 }
01450
01451 if(!readfile_read)
01452 break;
01453
01454 if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
01455 &readfile_read, NULL)) {
01456 keepon = FALSE;
01457 result = CURLE_READ_ERROR;
01458 break;
01459 }
01460 }
01461
01462 result = send_telnet_data(conn, buf, readfile_read);
01463 if(result) {
01464 keepon = FALSE;
01465 break;
01466 }
01467 }
01468 }
01469 break;
01470
01471 case WAIT_OBJECT_0 + 1:
01472 {
01473 if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
01474 &readfile_read, NULL)) {
01475 keepon = FALSE;
01476 result = CURLE_READ_ERROR;
01477 break;
01478 }
01479
01480 result = send_telnet_data(conn, buf, readfile_read);
01481 if(result) {
01482 keepon = FALSE;
01483 break;
01484 }
01485 }
01486 break;
01487
01488 case WAIT_OBJECT_0:
01489
01490 events.lNetworkEvents = 0;
01491 if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
01492 err = SOCKERRNO;
01493 if(err != EINPROGRESS) {
01494 infof(data, "WSAEnumNetworkEvents failed (%d)", err);
01495 keepon = FALSE;
01496 result = CURLE_READ_ERROR;
01497 }
01498 break;
01499 }
01500 if(events.lNetworkEvents & FD_READ) {
01501
01502 result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
01503
01504 if(result == CURLE_AGAIN)
01505 break;
01506
01507 else if(result) {
01508 keepon = FALSE;
01509 break;
01510 }
01511
01512
01513 else if(nread <= 0) {
01514 keepon = FALSE;
01515 break;
01516 }
01517
01518 result = telrcv(conn, (unsigned char *) buf, nread);
01519 if(result) {
01520 keepon = FALSE;
01521 break;
01522 }
01523
01524
01525
01526
01527 if(tn->please_negotiate && !tn->already_negotiated) {
01528 negotiate(conn);
01529 tn->already_negotiated = 1;
01530 }
01531 }
01532 if(events.lNetworkEvents & FD_CLOSE) {
01533 keepon = FALSE;
01534 }
01535 break;
01536
01537 }
01538
01539 if(data->set.timeout) {
01540 now = Curl_tvnow();
01541 if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
01542 failf(data, "Time-out");
01543 result = CURLE_OPERATION_TIMEDOUT;
01544 keepon = FALSE;
01545 }
01546 }
01547 }
01548
01549
01550 if(!close_event_func(event_handle)) {
01551 infof(data, "WSACloseEvent failed (%d)", SOCKERRNO);
01552 }
01553
01554
01555 create_event_func = NULL;
01556 close_event_func = NULL;
01557 event_select_func = NULL;
01558 enum_netevents_func = NULL;
01559
01560
01561 if(!FreeLibrary(wsock2))
01562 infof(data, "FreeLibrary(wsock2) failed (%d)", ERRNO);
01563 #else
01564 pfd[0].fd = sockfd;
01565 pfd[0].events = POLLIN;
01566
01567 if(data->set.is_fread_set) {
01568 poll_cnt = 1;
01569 interval_ms = 100;
01570 }
01571 else {
01572
01573 pfd[1].fd = fileno((FILE *)data->state.in);
01574 pfd[1].events = POLLIN;
01575 poll_cnt = 2;
01576 interval_ms = 1 * 1000;
01577 }
01578
01579 while(keepon) {
01580 switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
01581 case -1:
01582 keepon = FALSE;
01583 continue;
01584 case 0:
01585 pfd[0].revents = 0;
01586 pfd[1].revents = 0;
01587
01588 default:
01589 if(pfd[0].revents & POLLIN) {
01590
01591 result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
01592
01593 if(result == CURLE_AGAIN)
01594 break;
01595
01596 else if(result) {
01597 keepon = FALSE;
01598 break;
01599 }
01600
01601
01602 else if(nread <= 0) {
01603 keepon = FALSE;
01604 break;
01605 }
01606
01607 total_dl += nread;
01608 Curl_pgrsSetDownloadCounter(data, total_dl);
01609 result = telrcv(conn, (unsigned char *)buf, nread);
01610 if(result) {
01611 keepon = FALSE;
01612 break;
01613 }
01614
01615
01616
01617
01618 if(tn->please_negotiate && !tn->already_negotiated) {
01619 negotiate(conn);
01620 tn->already_negotiated = 1;
01621 }
01622 }
01623
01624 nread = 0;
01625 if(poll_cnt == 2) {
01626 if(pfd[1].revents & POLLIN) {
01627 nread = read(pfd[1].fd, buf, BUFSIZE - 1);
01628 }
01629 }
01630 else {
01631
01632 nread = (int)data->state.fread_func(buf, 1, BUFSIZE - 1,
01633 data->state.in);
01634 if(nread == CURL_READFUNC_ABORT) {
01635 keepon = FALSE;
01636 break;
01637 }
01638 if(nread == CURL_READFUNC_PAUSE)
01639 break;
01640 }
01641
01642 if(nread > 0) {
01643 result = send_telnet_data(conn, buf, nread);
01644 if(result) {
01645 keepon = FALSE;
01646 break;
01647 }
01648 total_ul += nread;
01649 Curl_pgrsSetUploadCounter(data, total_ul);
01650 }
01651 else if(nread < 0)
01652 keepon = FALSE;
01653
01654 break;
01655 }
01656
01657 if(data->set.timeout) {
01658 now = Curl_tvnow();
01659 if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
01660 failf(data, "Time-out");
01661 result = CURLE_OPERATION_TIMEDOUT;
01662 keepon = FALSE;
01663 }
01664 }
01665
01666 if(Curl_pgrsUpdate(conn)) {
01667 result = CURLE_ABORTED_BY_CALLBACK;
01668 break;
01669 }
01670 }
01671 #endif
01672
01673 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
01674
01675 return result;
01676 }
01677 #endif