telnet.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:55k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /* Copyright (c) 1988, 1990, 1993                                            */
  2. /* The Regents of the University of California.  All rights reserved.        */
  3. /*                                                                           */
  4. /* Redistribution and use in source and binary forms, with or without        */
  5. /* modification, are permitted provided that the following conditions        */
  6. /* are met:                                                                  */
  7. /* 1. Redistributions of source code must retain the above copyright         */
  8. /* notice, this list of conditions and the following disclaimer.             */
  9. /* 2. Redistributions in binary form must reproduce the above copyright      */
  10. /* notice, this list of conditions and the following disclaimer in the       */
  11. /* documentation and/or other materials provided with the distribution.      */
  12. /* 3. All advertising materials mentioning features or use of this           */
  13. /* software must display the following acknowledgement:                      */
  14. /*   This product includes software developed by the University of           */
  15. /*   California, Berkeley and its contributors.                              */
  16. /* 4. Neither the name of the University nor the names of its contributors   */
  17. /* may be used to endorse or promote products derived from this software     */
  18. /* without specific prior written permission.                                */
  19. /*                                                                           */
  20. /* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   */
  21. /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE     */
  22. /* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        */
  23. /* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE */
  24. /* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR       */
  25. /* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF      */
  26. /* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
  27. /* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   */
  28. /* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   */
  29. /* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF    */
  30. /* THE POSSIBILITY OF SUCH DAMAGE.                                           */
  31. #ifdef SHOW_SCCSIDS
  32. static char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95";
  33. #endif
  34. #include <sys/types.h>
  35. #include <signal.h>
  36. #include <arpa/telnet.h>
  37. #include <ctype.h>
  38. #include "ring.h"
  39. #include "defines.h"
  40. #include "externs.h"
  41. #include "types.h"
  42. #include "general.h"
  43. #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
  44. static unsigned char subbuffer[SUBBUFSIZE],
  45. *subpointer, *subend;  /* buffer for sub-options */
  46. #define SB_CLEAR() subpointer = subbuffer;
  47. #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
  48. #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { 
  49. *subpointer++ = (c); 
  50. }
  51. #define SB_GET() ((*subpointer++)&0xff)
  52. #define SB_PEEK() ((*subpointer)&0xff)
  53. #define SB_EOF() (subpointer >= subend)
  54. #define SB_LEN() (subend - subpointer)
  55. char options[256]; /* The combined options */
  56. char do_dont_resp[256];
  57. char will_wont_resp[256];
  58. int
  59. eight = 0,
  60. autologin = 0, /* Autologin anyone? */
  61. skiprc = 0,
  62. connected,
  63. showoptions,
  64. In3270, /* Are we in 3270 mode? */
  65. ISend, /* trying to send network data in */
  66. debug = 0,
  67. crmod,
  68. netdata, /* Print out network data flow */
  69. crlf, /* Should 'r' be mapped to <CR><LF> (or <CR><NUL>)? */
  70. #ifdef TN3270
  71. noasynchtty = 0,/* User specified "-noasynch" on command line */
  72. noasynchnet = 0,/* User specified "-noasynch" on command line */
  73. askedSGA = 0, /* We have talked about suppress go ahead */
  74. #endif /* defined(TN3270) */
  75. telnetport,
  76. SYNCHing, /* we are in TELNET SYNCH mode */
  77. flushout, /* flush output */
  78. autoflush = 0, /* flush output when interrupting? */
  79. autosynch, /* send interrupt characters with SYNCH? */
  80. localflow, /* we handle flow control locally */
  81. restartany, /* if flow control enabled, restart on any character */
  82. localchars, /* we recognize interrupt/quit */
  83. donelclchars, /* the user has set "localchars" */
  84. donebinarytoggle, /* the user has put us in binary */
  85. dontlecho, /* do we suppress local echoing right now? */
  86. globalmode;
  87. char *prompt = 0;
  88. cc_t escape;
  89. cc_t rlogin;
  90. #ifdef KLUDGELINEMODE
  91. cc_t echoc;
  92. #endif
  93. /*
  94.  * Telnet receiver states for fsm
  95.  */
  96. #define TS_DATA 0
  97. #define TS_IAC 1
  98. #define TS_WILL 2
  99. #define TS_WONT 3
  100. #define TS_DO 4
  101. #define TS_DONT 5
  102. #define TS_CR 6
  103. #define TS_SB 7 /* sub-option collection */
  104. #define TS_SE 8 /* looking for sub-option end */
  105. static int telrcv_state;
  106. #ifdef OLD_ENVIRON
  107. unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
  108. #else
  109. # define telopt_environ TELOPT_NEW_ENVIRON
  110. #endif
  111. jmp_buf toplevel, peerdied;
  112. int flushline;
  113. int linemode;
  114. #ifdef KLUDGELINEMODE
  115. int kludgelinemode = 1;
  116. #endif
  117. /*
  118.  * The following are some clocks used to decide how to interpret
  119.  * the relationship between various variables.
  120.  */
  121. Clocks clocks;
  122. #ifdef notdef
  123. Modelist modelist[] = {
  124. { "telnet command mode", COMMAND_LINE },
  125. { "character-at-a-time mode", 0 },
  126. { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
  127. { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
  128. { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
  129. { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
  130. { "3270 mode", 0 },
  131. };
  132. #endif
  133. /*
  134.  * Initialize telnet environment.
  135.  */
  136. void init_telnet() {
  137.     env_init();
  138.     SB_CLEAR();
  139.     ClearArray(options);
  140.     connected = In3270 = ISend = localflow = donebinarytoggle = 0;
  141.     restartany = -1;
  142.     SYNCHing = 0;
  143.     /* Don't change NetTrace */
  144.     escape = CONTROL(']');
  145.     rlogin = _POSIX_VDISABLE;
  146. #ifdef KLUDGELINEMODE
  147.     echoc = CONTROL('E');
  148. #endif
  149.     flushline = 1;
  150.     telrcv_state = TS_DATA;
  151. }
  152. #ifdef notdef
  153. #include <varargs.h>
  154. /*VARARGS*/
  155. static void printring(va_alist) va_dcl {
  156.     char buffer[100], char *ptr, char *format, char *string;
  157.     Ring *ring;
  158.     va_list ap;
  159.     int i;
  160.     va_start(ap);
  161.     ring   = va_arg(ap, Ring *);
  162.     format = va_arg(ap, char *);
  163.     ptr    = buffer;
  164.     while ((i = *format++) != 0) {
  165. if (i == '%') {
  166.     i = *format++;
  167.     switch (i) {
  168.     case 'c':
  169. *ptr++ = va_arg(ap, int);
  170. break;
  171.     case 's':
  172. string = va_arg(ap, char *);
  173. ring_supply_data(ring, buffer, ptr-buffer);
  174. ring_supply_data(ring, string, strlen(string));
  175. ptr = buffer;
  176. break;
  177.     case 0:
  178. ExitString("printring: trailing %%.n", 1);
  179. /*NOTREACHED*/
  180.     default:
  181. ExitString("printring: unknown format character.n", 1);
  182. /*NOTREACHED*/
  183.     }
  184. } else {
  185.     *ptr++ = i;
  186. }
  187.     }
  188.     ring_supply_data(ring, buffer, ptr-buffer);
  189. }
  190. #endif
  191. /* These routines are in charge of sending option negotiations               */
  192. /* to the other side.                                                        */
  193. /*                                                                           */
  194. /* The basic idea is that we send the negotiation if either side             */
  195. /* is in disagreement as to what the current state should be.                */
  196. void send_do(register int c, register int init) {
  197.     if (init) {
  198. if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || my_want_state_is_do(c)) return;
  199. set_my_want_state_do(c);
  200. do_dont_resp[c]++;
  201.     }
  202.     NET2ADD(IAC, DO);
  203.     NETADD(c);
  204.     printoption("SENT", DO, c);
  205. }
  206. void send_dont(register int c, register int init) {
  207.     if (init) {
  208. if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || my_want_state_is_dont(c)) return;
  209. set_my_want_state_dont(c);
  210. do_dont_resp[c]++;
  211.     }
  212.     NET2ADD(IAC, DONT);
  213.     NETADD(c);
  214.     printoption("SENT", DONT, c);
  215. }
  216. void send_will(register int c, register int init) {
  217.     if (init) {
  218. if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || my_want_state_is_will(c)) return;
  219. set_my_want_state_will(c);
  220. will_wont_resp[c]++;
  221.     }
  222.     NET2ADD(IAC, WILL);
  223.     NETADD(c);
  224.     printoption("SENT", WILL, c);
  225. }
  226. void send_wont(register int c, register int init) {
  227.     if (init) {
  228. if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || my_want_state_is_wont(c)) return;
  229. set_my_want_state_wont(c);
  230. will_wont_resp[c]++;
  231.     }
  232.     NET2ADD(IAC, WONT);
  233.     NETADD(c);
  234.     printoption("SENT", WONT, c);
  235. }
  236. void willoption(int option) {
  237.     int new_state_ok = 0;
  238.     if (do_dont_resp[option]) {
  239. --do_dont_resp[option];
  240. if (do_dont_resp[option] && my_state_is_do(option))
  241.     --do_dont_resp[option];
  242.     }
  243.     
  244.     if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
  245. switch (option) {
  246.     case TELOPT_ECHO:
  247. #ifdef TN3270
  248. /* The following is a pain in the rear-end.  Various IBM     */
  249. /* servers (some versions of Wiscnet, possibly Fibronics     */
  250. /* Spartacus, and who knows who else) will NOT allow us to   */
  251. /* send "DO SGA" too early in the setup proceedings.  On the */
  252. /* other hand, 4.2 servers (telnetd) won't set SGA           */
  253. /* correctly. So, we are stuck.  Empirically (but, based on  */
  254. /* a VERY small sample), the IBM servers don't send out      */
  255. /* anything about ECHO, so we postpone our sending "DO SGA"  */
  256. /* until we see "WILL ECHO" (which 4.2 servers DO send).     */
  257. {
  258.     if (askedSGA == 0) {
  259. askedSGA = 1;
  260. if (my_want_state_is_dont(TELOPT_SGA))
  261.     send_do(TELOPT_SGA, 1);
  262.     }
  263. }
  264.         /* Fall through */
  265.     case TELOPT_EOR:
  266. #endif
  267.     case TELOPT_BINARY:
  268.     case TELOPT_SGA:
  269. settimer(modenegotiated);
  270. /* FALL THROUGH */
  271.     case TELOPT_STATUS:
  272. new_state_ok = 1;
  273. break;
  274.     case TELOPT_TM:
  275. if (flushout) flushout = 0;
  276. /* Special case for TM.  If we get back a WILL, pretend we   */
  277. /* got back a WONT.                                          */
  278. set_my_want_state_dont(option);
  279. set_my_state_dont(option);
  280. return; /* Never reply to TM will's/wont's   */
  281.     case TELOPT_LINEMODE:
  282.     default:
  283. break;
  284. }
  285. if (new_state_ok) {
  286.     set_my_want_state_do(option);
  287.     send_do(option, 0);
  288.     setconnmode(0); /* possibly set new tty mode         */
  289. } else {
  290.     do_dont_resp[option]++;
  291.     send_dont(option, 0);
  292. }
  293.     }
  294.     set_my_state_do(option);
  295. }
  296. void wontoption(int option) {
  297.     if (do_dont_resp[option]) {
  298. --do_dont_resp[option];
  299. if (do_dont_resp[option] && my_state_is_dont(option))
  300.     --do_dont_resp[option];
  301.     }
  302.     if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
  303.     switch (option) {
  304. #ifdef KLUDGELINEMODE
  305. case TELOPT_SGA:
  306.     if (!kludgelinemode) break;
  307.     /* FALL THROUGH */
  308. #endif
  309. case TELOPT_ECHO:
  310.     settimer(modenegotiated);
  311.     break;
  312. case TELOPT_TM:
  313.     if (flushout) flushout = 0;
  314.     set_my_want_state_dont(option);
  315.     set_my_state_dont(option);
  316.     return; /* Never reply to TM will's/wont's   */
  317. default:
  318.     break;
  319.     }
  320.     set_my_want_state_dont(option);
  321.     if (my_state_is_do(option)) send_dont(option, 0);
  322.     setconnmode(0); /* Set new tty mode                  */
  323.     } else if (option == TELOPT_TM) {
  324. /* Special case for TM.  */
  325. if (flushout) flushout = 0;
  326. set_my_want_state_dont(option);
  327.     }
  328.     set_my_state_dont(option);
  329. }
  330. static void dooption(int option) {
  331.     int new_state_ok = 0;
  332.     if (will_wont_resp[option]) {
  333. --will_wont_resp[option];
  334. if (will_wont_resp[option] && my_state_is_will(option))
  335.     --will_wont_resp[option];
  336.     }
  337.     if (will_wont_resp[option] == 0) {
  338. if (my_want_state_is_wont(option)) {
  339.     switch (option) {
  340. case TELOPT_TM:
  341.     /* Special case for TM.  We send a WILL, but pretend we  */
  342.     /* sent WONT.                                            */
  343.     send_will(option, 0);
  344.     set_my_want_state_wont(TELOPT_TM);
  345.     set_my_state_wont(TELOPT_TM);
  346.     return;
  347. #ifdef TN3270
  348. case TELOPT_EOR: /* end of record */
  349. #endif
  350. case TELOPT_BINARY: /* binary mode */
  351. case TELOPT_NAWS: /* window size */
  352. case TELOPT_TSPEED: /* terminal speed */
  353. case TELOPT_LFLOW: /* local flow control */
  354. case TELOPT_TTYPE: /* terminal type option */
  355. case TELOPT_SGA: /* no big deal */
  356.     new_state_ok = 1;
  357.     break;
  358. case TELOPT_NEW_ENVIRON: /* New environment variable option */
  359. #ifdef OLD_ENVIRON
  360.     if (my_state_is_will(TELOPT_OLD_ENVIRON)) send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
  361.     goto env_common;
  362. case TELOPT_OLD_ENVIRON: /* Old environment variable option */
  363.     if (my_state_is_will(TELOPT_NEW_ENVIRON)) break; /* Don't enable if new one is in use! */
  364.     env_common:
  365.     telopt_environ = option;
  366. #endif
  367.     new_state_ok = 1;
  368.     break;
  369. case TELOPT_XDISPLOC: /* X Display location */
  370.     if (env_getvalue((unsigned char *)"DISPLAY")) new_state_ok = 1;
  371.     break;
  372. case TELOPT_LINEMODE:
  373. #ifdef KLUDGELINEMODE
  374.     kludgelinemode = 0;
  375.     send_do(TELOPT_SGA, 1);
  376. #endif
  377.     set_my_want_state_will(TELOPT_LINEMODE);
  378.     send_will(option, 0);
  379.     set_my_state_will(TELOPT_LINEMODE);
  380.     slc_init();
  381.     return;
  382. case TELOPT_ECHO: /* We're never going to echo... */
  383. default:
  384.     break;
  385.     }
  386.     if (new_state_ok) {
  387. set_my_want_state_will(option);
  388. send_will(option, 0);
  389. setconnmode(0); /* Set new tty mode */
  390.     } else {
  391. will_wont_resp[option]++;
  392. send_wont(option, 0);
  393.     }
  394. } else {
  395.     /* Handle options that need more things done after the other     */
  396.     /* side has acknowledged the option.                             */
  397.     switch (option) {
  398. case TELOPT_LINEMODE:
  399. #ifdef KLUDGELINEMODE
  400.     kludgelinemode = 0;
  401.     send_do(TELOPT_SGA, 1);
  402. #endif
  403.     set_my_state_will(option);
  404.     slc_init();
  405.     send_do(TELOPT_SGA, 0);
  406.     return;
  407.     }
  408. }
  409.     }
  410.     set_my_state_will(option);
  411. }
  412. static void dontoption(int option) {
  413.     if (will_wont_resp[option]) {
  414. --will_wont_resp[option];
  415. if (will_wont_resp[option] && my_state_is_wont(option))
  416.     --will_wont_resp[option];
  417.     }
  418.     if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
  419. switch (option) {
  420.     case TELOPT_LINEMODE:
  421. linemode = 0; /* put us back to the default state */
  422. break;
  423. #ifdef OLD_ENVIRON
  424.     case TELOPT_NEW_ENVIRON:
  425. /* The new environ option wasn't recognized, try the old     */
  426. send_will(TELOPT_OLD_ENVIRON, 1);
  427. telopt_environ = TELOPT_OLD_ENVIRON;
  428. break;
  429. #endif
  430. }
  431. /* we always accept a DONT */
  432. set_my_want_state_wont(option);
  433. if (my_state_is_will(option)) send_wont(option, 0);
  434. setconnmode(0); /* Set new tty mode */
  435.     }
  436.     set_my_state_wont(option);
  437. }
  438. static int is_unique(register char *name, register char **as, register char **ae) {
  439.     register char **ap;
  440.     register int n;
  441.     n = strlen(name) + 1;
  442.     for (ap = as; ap < ae; ap++)
  443. if (strncasecmp(*ap, name, n) == 0)
  444.     return 0;
  445.     return 1;
  446. }
  447. /* Given a buffer returned by tgetent(), this routine will turn              */
  448. /* the pipe seperated list of names in the buffer into an array              */
  449. /* of pointers to null terminated names.  We toss out any bad,               */
  450. /* duplicate, or verbose names (names with spaces).                          */
  451. /*                                                                           */
  452. static char *name_unknown = "UNKNOWN";
  453. static char *unknown[] = { 0, 0 };
  454. char ** mklist(char *buf, char *name) {
  455.     register char c, *cp, **argvp, *cp2, **argv, **avt;
  456.     register int n;
  457.     if (name) {
  458. if ((int)strlen(name) > 40) {
  459.     name = 0;
  460.     unknown[0] = name_unknown;
  461. } else {
  462.     unknown[0] = name;
  463.     upcase(name);
  464. }
  465.     } else {
  466. unknown[0] = name_unknown;
  467.     }
  468.     /* Count up the number of names.                                         */
  469.     for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
  470. if (*cp == '|') n++;
  471.     }
  472.     /* Allocate an array to put the name pointers into                       */
  473.     argv = (char **)malloc((n+3)*sizeof(char *));
  474.     if (argv == 0) return(unknown);
  475.     /* Fill up the array of pointers to names.                               */
  476.     *argv = 0;
  477.     argvp = argv+1;
  478.     n = 0;
  479.     for (cp = cp2 = buf; (c = *cp);  cp++) {
  480. if (c == '|' || c == ':') {
  481.     *cp++ = '';
  482.     /* Skip entries that have spaces or are over 40 characters long. */
  483.     /* If this is our environment name, then put it up front.        */
  484.     /* Otherwise, as long as this is not a duplicate name (case      */
  485.     /* insensitive) add it to the list.                              */
  486.     if (n || (cp - cp2 > 41)) ;
  487.     else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) *argv = cp2;
  488.     else if (is_unique(cp2, argv+1, argvp)) *argvp++ = cp2;
  489.     if (c == ':') break;
  490.     /* Skip multiple delimiters. Reset cp2 to the beginning of the   */
  491.     /* next name. Reset n, the flag for names with spaces.           */
  492.     while ((c = *cp) == '|') cp++;
  493.     cp2 = cp;
  494.     n = 0;
  495. }
  496. /* Skip entries with spaces or non-ascii values.  Convert lower case */
  497. /* letters to upper case.                                            */
  498. if ((c == ' ') || !isascii(c)) n = 1;
  499. else if (islower(c)) *cp = toupper(c);
  500.     }
  501.     /* Check for an old V6 2 character name.  If the second name points to   */
  502.     /* the beginning of the buffer, and is only 2 characters long, move it   */
  503.     /* to the end of the array.                                              */
  504.     if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
  505. for (--argvp, avt = &argv[1]; avt < argvp; avt++) *avt = *(avt+1);
  506. *argvp++ = buf;
  507.     }
  508.     /* Duplicate last name, for TTYPE option, and null terminate the array.  */
  509.     /* If we didn't find a match on our terminal name, put that name at the  */
  510.     /* beginning.                                                                    */
  511.     cp = *(argvp-1);
  512.     *argvp++ = cp;
  513.     *argvp = 0;
  514.     
  515.     if (*argv == 0) {
  516. if (name) *argv = name;
  517. else for (--argvp, avt = argv; avt < argvp; avt++) *avt = *(avt+1);
  518.     }
  519.     if (*argv) return(argv);
  520.     else return(unknown);
  521. }
  522. #ifndef HAVE_SETUPTERM
  523. extern int tgetent(char *, char *);
  524. char termbuf[1024];
  525. /*ARGSUSED*/
  526. int setupterm(char *tname, int fd, int *errp) {
  527.     if (tgetent(termbuf, tname) == 1) {
  528. termbuf[1023] = '';
  529. if (errp) *errp = 1;
  530. return(0);
  531.     }
  532.     if (errp) *errp = 0;
  533.     return(-1);
  534. }
  535. #else
  536. #define termbuf ttytype
  537. extern char ttytype[];
  538. #endif
  539. int resettermname = 1;
  540. char *gettermname() {
  541.     static char **tnamep = 0;
  542.     static char **next;
  543.     char *tname;
  544.     int err;
  545.     if (resettermname) {
  546. resettermname = 0;
  547. if (tnamep && tnamep != unknown) free(tnamep);
  548. if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && (setupterm(tname, 1, &err) == 0)) {
  549.     tnamep = mklist(termbuf, tname);
  550. } else {
  551.     if (tname && ((int)strlen(tname) <= 40)) {
  552. unknown[0] = tname;
  553. upcase(tname);
  554.     } else {
  555. unknown[0] = name_unknown;
  556.     }
  557.     tnamep = unknown;
  558. }
  559. next = tnamep;
  560.     }
  561.     if (*next == 0) next = tnamep;
  562.     return(*next++);
  563. }
  564. /* suboption()                                                               */
  565. /*                                                                           */
  566. /* Look at the sub-option buffer, and try to be helpful to the other         */
  567. /* side.                                                                     */
  568. /*                                                                           */
  569. /* Currently we recognize:                                                   */
  570. /*                                                                           */
  571. /* Terminal type, send request.                                              */
  572. /* Terminal speed (send request).                                            */
  573. /* Local flow control (is request).                                          */
  574. /* Linemode                                                                  */
  575. static void suboption() {
  576.     unsigned char subchar;
  577.     printsub('<', subbuffer, SB_LEN()+2);
  578.     switch (subchar = SB_GET()) {
  579. case TELOPT_TTYPE:
  580.     if (my_want_state_is_wont(TELOPT_TTYPE))
  581. return;
  582.     if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
  583. return;
  584.     } else {
  585. unsigned char temp[50];
  586. char *name;
  587. int len;
  588. #ifdef TN3270
  589. if (tn3270_ttype()) {
  590.     return;
  591. }
  592. #endif
  593. name = gettermname();
  594. len = strlen(name) + 4 + 2;
  595. if (len < NETROOM()) {
  596.     sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE);
  597.     ring_supply_data(&netoring, temp, len);
  598.     printsub('>', &temp[2], len-2);
  599. } else {
  600.     ExitString("No room in buffer for terminal type.n", 1);
  601.     /*NOTREACHED*/
  602. }
  603.     }
  604.     break;
  605. case TELOPT_TSPEED:
  606.     if (my_want_state_is_wont(TELOPT_TSPEED)) return;
  607.     if (SB_EOF()) return;
  608.     if (SB_GET() == TELQUAL_SEND) {
  609. long ospeed, ispeed;
  610. unsigned char temp[50];
  611. int len;
  612. TerminalSpeeds(&ispeed, &ospeed);
  613. sprintf((char *)temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED, TELQUAL_IS, (int)ospeed, (int)ispeed, IAC, SE);
  614. len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
  615. if (len < NETROOM()) {
  616.     ring_supply_data(&netoring, temp, len);
  617.     printsub('>', temp+2, len - 2);
  618. }
  619. /*@*/     else printf("lm_will: not enough room in buffern");
  620.     }
  621.     break;
  622. case TELOPT_LFLOW:
  623.     if (my_want_state_is_wont(TELOPT_LFLOW)) return;
  624.     if (SB_EOF()) return;
  625.     switch(SB_GET()) {
  626. case LFLOW_RESTART_ANY:
  627.     restartany = 1;
  628.     break;
  629. case LFLOW_RESTART_XON:
  630.     restartany = 0;
  631.     break;
  632. case LFLOW_ON:
  633.     localflow = 1;
  634.     break;
  635. case LFLOW_OFF:
  636.     localflow = 0;
  637.     break;
  638. default:
  639.     return;
  640.     }
  641.     setcommandmode();
  642.     setconnmode(0);
  643.     break;
  644. case TELOPT_LINEMODE:
  645.     if (my_want_state_is_wont(TELOPT_LINEMODE)) return;
  646.     if (SB_EOF()) return;
  647.     switch (SB_GET()) {
  648. case WILL:
  649.     lm_will(subpointer, SB_LEN());
  650.     break;
  651. case WONT:
  652.     lm_wont(subpointer, SB_LEN());
  653.     break;
  654. case DO:
  655.     lm_do(subpointer, SB_LEN());
  656.     break;
  657. case DONT:
  658.     lm_dont(subpointer, SB_LEN());
  659.     break;
  660. case LM_SLC:
  661.     slc(subpointer, SB_LEN());
  662.     break;
  663. case LM_MODE:
  664.     lm_mode(subpointer, SB_LEN(), 0);
  665.     break;
  666. default:
  667.     break;
  668.     }
  669.     break;
  670. #ifdef OLD_ENVIRON
  671. case TELOPT_OLD_ENVIRON:
  672. #endif
  673. case TELOPT_NEW_ENVIRON:
  674.     if (SB_EOF()) return;
  675.     switch(SB_PEEK()) {
  676. case TELQUAL_IS:
  677. case TELQUAL_INFO:
  678.     if (my_want_state_is_dont(subchar)) return;
  679.     break;
  680. case TELQUAL_SEND:
  681.     if (my_want_state_is_wont(subchar)) return;
  682.     break;
  683. default:
  684.     return;
  685.     }
  686.     env_opt(subpointer, SB_LEN());
  687.     break;
  688. case TELOPT_XDISPLOC:
  689.     if (my_want_state_is_wont(TELOPT_XDISPLOC)) return;
  690.     if (SB_EOF()) return;
  691.     if (SB_GET() == TELQUAL_SEND) {
  692. unsigned char temp[50], *dp;
  693. int len;
  694. if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
  695.     /* Something happened, we no longer have a DISPLAY       */
  696.     /* variable.  So, turn off the option.                   */
  697.     send_wont(TELOPT_XDISPLOC, 1);
  698.     break;
  699. }
  700. sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE);
  701. len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
  702. if (len < NETROOM()) {
  703.     ring_supply_data(&netoring, temp, len);
  704.     printsub('>', temp+2, len - 2);
  705. }
  706. /*@*/     else printf("lm_will: not enough room in buffern");
  707.     }
  708.     break;
  709. default:
  710.     break;
  711.     }
  712. }
  713. static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
  714.     void
  715. lm_will(cmd, len)
  716.     unsigned char *cmd;
  717.     int len;
  718. {
  719.     if (len < 1) {
  720. /*@*/ printf("lm_will: no command!!!n"); /* Should not happen... */
  721. return;
  722.     }
  723.     switch(cmd[0]) {
  724.     case LM_FORWARDMASK: /* We shouldn't ever get this... */
  725.     default:
  726. str_lm[3] = DONT;
  727. str_lm[4] = cmd[0];
  728. if (NETROOM() > sizeof(str_lm)) {
  729.     ring_supply_data(&netoring, str_lm, sizeof(str_lm));
  730.     printsub('>', &str_lm[2], sizeof(str_lm)-2);
  731. }
  732. /*@*/ else printf("lm_will: not enough room in buffern");
  733. break;
  734.     }
  735. }
  736.     void
  737. lm_wont(cmd, len)
  738.     unsigned char *cmd;
  739.     int len;
  740. {
  741.     if (len < 1) {
  742. /*@*/ printf("lm_wont: no command!!!n"); /* Should not happen... */
  743. return;
  744.     }
  745.     switch(cmd[0]) {
  746.     case LM_FORWARDMASK: /* We shouldn't ever get this... */
  747.     default:
  748. /* We are always DONT, so don't respond */
  749. return;
  750.     }
  751. }
  752.     void
  753. lm_do(cmd, len)
  754.     unsigned char *cmd;
  755.     int len;
  756. {
  757.     if (len < 1) {
  758. /*@*/ printf("lm_do: no command!!!n"); /* Should not happen... */
  759. return;
  760.     }
  761.     switch(cmd[0]) {
  762.     case LM_FORWARDMASK:
  763.     default:
  764. str_lm[3] = WONT;
  765. str_lm[4] = cmd[0];
  766. if (NETROOM() > sizeof(str_lm)) {
  767.     ring_supply_data(&netoring, str_lm, sizeof(str_lm));
  768.     printsub('>', &str_lm[2], sizeof(str_lm)-2);
  769. }
  770. /*@*/ else printf("lm_do: not enough room in buffern");
  771. break;
  772.     }
  773. }
  774.     void
  775. lm_dont(cmd, len)
  776.     unsigned char *cmd;
  777.     int len;
  778. {
  779.     if (len < 1) {
  780. /*@*/ printf("lm_dont: no command!!!n"); /* Should not happen... */
  781. return;
  782.     }
  783.     switch(cmd[0]) {
  784.     case LM_FORWARDMASK:
  785.     default:
  786. /* we are always WONT, so don't respond */
  787. break;
  788.     }
  789. }
  790. static unsigned char str_lm_mode[] = {
  791. IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
  792. };
  793. void
  794. lm_mode(cmd, len, init)
  795. unsigned char *cmd;
  796. int len, init;
  797. {
  798. if (len != 1)
  799. return;
  800. if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
  801. return;
  802. if (*cmd&MODE_ACK)
  803. return;
  804. linemode = *cmd&(MODE_MASK&~MODE_ACK);
  805. str_lm_mode[4] = linemode;
  806. if (!init)
  807.     str_lm_mode[4] |= MODE_ACK;
  808. if (NETROOM() > sizeof(str_lm_mode)) {
  809.     ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
  810.     printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
  811. }
  812. /*@*/ else printf("lm_mode: not enough room in buffern");
  813. setconnmode(0); /* set changed mode */
  814. }
  815. /*
  816.  * slc()
  817.  * Handle special character suboption of LINEMODE.
  818.  */
  819. struct spc {
  820. cc_t val;
  821. cc_t *valp;
  822. char flags; /* Current flags & level */
  823. char mylevel; /* Maximum level & flags */
  824. } spc_data[NSLC+1];
  825. #define SLC_IMPORT 0
  826. #define SLC_EXPORT 1
  827. #define SLC_RVALUE 2
  828. static int slc_mode = SLC_EXPORT;
  829. void
  830. slc_init()
  831. {
  832. register struct spc *spcp;
  833. localchars = 1;
  834. for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
  835. spcp->val = 0;
  836. spcp->valp = 0;
  837. spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
  838. }
  839. #define initfunc(func, flags) { 
  840. spcp = &spc_data[func]; 
  841. if ((spcp->valp = tcval(func))) { 
  842.     spcp->val = *spcp->valp; 
  843.     spcp->mylevel = SLC_VARIABLE|flags; 
  844. } else { 
  845.     spcp->val = 0; 
  846.     spcp->mylevel = SLC_DEFAULT; 
  847.     }
  848. initfunc(SLC_SYNCH, 0);
  849. /* No BRK */
  850. initfunc(SLC_AO, 0);
  851. initfunc(SLC_AYT, 0);
  852. /* No EOR */
  853. initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
  854. initfunc(SLC_EOF, 0);
  855. #ifndef SYSV_TERMIO
  856. initfunc(SLC_SUSP, SLC_FLUSHIN);
  857. #endif
  858. initfunc(SLC_EC, 0);
  859. initfunc(SLC_EL, 0);
  860. #ifndef SYSV_TERMIO
  861. initfunc(SLC_EW, 0);
  862. initfunc(SLC_RP, 0);
  863. initfunc(SLC_LNEXT, 0);
  864. #endif
  865. initfunc(SLC_XON, 0);
  866. initfunc(SLC_XOFF, 0);
  867. #ifdef SYSV_TERMIO
  868. spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
  869. spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
  870. #endif
  871. initfunc(SLC_FORW1, 0);
  872. #ifdef USE_TERMIO
  873. initfunc(SLC_FORW2, 0);
  874. /* No FORW2 */
  875. #endif
  876. initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
  877. #undef initfunc
  878. if (slc_mode == SLC_EXPORT)
  879. slc_export();
  880. else
  881. slc_import(1);
  882. }
  883.     void
  884. slcstate()
  885. {
  886.     printf("Special characters are %s valuesn",
  887. slc_mode == SLC_IMPORT ? "remote default" :
  888. slc_mode == SLC_EXPORT ? "local" :
  889.  "remote");
  890. }
  891.     void
  892. slc_mode_export()
  893. {
  894.     slc_mode = SLC_EXPORT;
  895.     if (my_state_is_will(TELOPT_LINEMODE))
  896. slc_export();
  897. }
  898.     void
  899. slc_mode_import(def)
  900.     int def;
  901. {
  902.     slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
  903.     if (my_state_is_will(TELOPT_LINEMODE))
  904. slc_import(def);
  905. }
  906. unsigned char slc_import_val[] = {
  907. IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
  908. };
  909. unsigned char slc_import_def[] = {
  910. IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
  911. };
  912.     void
  913. slc_import(def)
  914.     int def;
  915. {
  916.     if (NETROOM() > sizeof(slc_import_val)) {
  917. if (def) {
  918.     ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
  919.     printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
  920. } else {
  921.     ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
  922.     printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
  923. }
  924.     }
  925. /*@*/ else printf("slc_import: not enough roomn");
  926. }
  927.     void
  928. slc_export()
  929. {
  930.     register struct spc *spcp;
  931.     TerminalDefaultChars();
  932.     slc_start_reply();
  933.     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
  934. if (spcp->mylevel != SLC_NOSUPPORT) {
  935.     if (spcp->val == (cc_t)(_POSIX_VDISABLE))
  936. spcp->flags = SLC_NOSUPPORT;
  937.     else
  938. spcp->flags = spcp->mylevel;
  939.     if (spcp->valp)
  940. spcp->val = *spcp->valp;
  941.     slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
  942. }
  943.     }
  944.     slc_end_reply();
  945.     (void)slc_update();
  946.     setconnmode(1); /* Make sure the character values are set */
  947. }
  948. void
  949. slc(cp, len)
  950. register unsigned char *cp;
  951. int len;
  952. {
  953. register struct spc *spcp;
  954. register int func,level;
  955. slc_start_reply();
  956. for (; len >= 3; len -=3, cp +=3) {
  957. func = cp[SLC_FUNC];
  958. if (func == 0) {
  959. /*
  960.  * Client side: always ignore 0 function.
  961.  */
  962. continue;
  963. }
  964. if (func > NSLC) {
  965. if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
  966. slc_add_reply(func, SLC_NOSUPPORT, 0);
  967. continue;
  968. }
  969. spcp = &spc_data[func];
  970. level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
  971. if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
  972.     ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
  973. continue;
  974. }
  975. if (level == (SLC_DEFAULT|SLC_ACK)) {
  976. /*
  977.  * This is an error condition, the SLC_ACK
  978.  * bit should never be set for the SLC_DEFAULT
  979.  * level.  Our best guess to recover is to
  980.  * ignore the SLC_ACK bit.
  981.  */
  982. cp[SLC_FLAGS] &= ~SLC_ACK;
  983. }
  984. if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
  985. spcp->val = (cc_t)cp[SLC_VALUE];
  986. spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
  987. continue;
  988. }
  989. level &= ~SLC_ACK;
  990. if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
  991. spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
  992. spcp->val = (cc_t)cp[SLC_VALUE];
  993. }
  994. if (level == SLC_DEFAULT) {
  995. if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
  996. spcp->flags = spcp->mylevel;
  997. else
  998. spcp->flags = SLC_NOSUPPORT;
  999. }
  1000. slc_add_reply(func, spcp->flags, spcp->val);
  1001. }
  1002. slc_end_reply();
  1003. if (slc_update())
  1004. setconnmode(1); /* set the  new character values */
  1005. }
  1006.     void
  1007. slc_check()
  1008. {
  1009.     register struct spc *spcp;
  1010.     slc_start_reply();
  1011.     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
  1012. if (spcp->valp && spcp->val != *spcp->valp) {
  1013.     spcp->val = *spcp->valp;
  1014.     if (spcp->val == (cc_t)(_POSIX_VDISABLE))
  1015. spcp->flags = SLC_NOSUPPORT;
  1016.     else
  1017. spcp->flags = spcp->mylevel;
  1018.     slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
  1019. }
  1020.     }
  1021.     slc_end_reply();
  1022.     setconnmode(1);
  1023. }
  1024. unsigned char slc_reply[128];
  1025. unsigned char *slc_replyp;
  1026. void
  1027. slc_start_reply()
  1028. {
  1029. slc_replyp = slc_reply;
  1030. *slc_replyp++ = IAC;
  1031. *slc_replyp++ = SB;
  1032. *slc_replyp++ = TELOPT_LINEMODE;
  1033. *slc_replyp++ = LM_SLC;
  1034. }
  1035. void
  1036. slc_add_reply(func, flags, value)
  1037. unsigned char func;
  1038. unsigned char flags;
  1039. cc_t value;
  1040. {
  1041. if ((*slc_replyp++ = func) == IAC)
  1042. *slc_replyp++ = IAC;
  1043. if ((*slc_replyp++ = flags) == IAC)
  1044. *slc_replyp++ = IAC;
  1045. if ((*slc_replyp++ = (unsigned char)value) == IAC)
  1046. *slc_replyp++ = IAC;
  1047. }
  1048.     void
  1049. slc_end_reply()
  1050. {
  1051.     register int len;
  1052.     *slc_replyp++ = IAC;
  1053.     *slc_replyp++ = SE;
  1054.     len = slc_replyp - slc_reply;
  1055.     if (len <= 6)
  1056. return;
  1057.     if (NETROOM() > len) {
  1058. ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
  1059. printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
  1060.     }
  1061. /*@*/else printf("slc_end_reply: not enough roomn");
  1062. }
  1063. int
  1064. slc_update()
  1065. {
  1066. register struct spc *spcp;
  1067. int need_update = 0;
  1068. for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
  1069. if (!(spcp->flags&SLC_ACK))
  1070. continue;
  1071. spcp->flags &= ~SLC_ACK;
  1072. if (spcp->valp && (*spcp->valp != spcp->val)) {
  1073. *spcp->valp = spcp->val;
  1074. need_update = 1;
  1075. }
  1076. }
  1077. return(need_update);
  1078. }
  1079. #ifdef OLD_ENVIRON
  1080. # ifdef ENV_HACK
  1081. /*
  1082.  * Earlier version of telnet/telnetd from the BSD code had
  1083.  * the definitions of VALUE and VAR reversed.  To ensure
  1084.  * maximum interoperability, we assume that the server is
  1085.  * an older BSD server, until proven otherwise.  The newer
  1086.  * BSD servers should be able to handle either definition,
  1087.  * so it is better to use the wrong values if we don't
  1088.  * know what type of server it is.
  1089.  */
  1090. int env_auto = 1;
  1091. int old_env_var = OLD_ENV_VAR;
  1092. int old_env_value = OLD_ENV_VALUE;
  1093. # else
  1094. #  define old_env_var OLD_ENV_VAR
  1095. #  define old_env_value OLD_ENV_VALUE
  1096. # endif
  1097. #endif
  1098. void
  1099. env_opt(buf, len)
  1100. register unsigned char *buf;
  1101. register int len;
  1102. {
  1103. register unsigned char *ep = 0, *epc = 0;
  1104. register int i;
  1105. switch(buf[0]&0xff) {
  1106. case TELQUAL_SEND:
  1107. env_opt_start();
  1108. if (len == 1) {
  1109. env_opt_add(NULL);
  1110. } else for (i = 1; i < len; i++) {
  1111. switch (buf[i]&0xff) {
  1112. #ifdef OLD_ENVIRON
  1113. case OLD_ENV_VAR:
  1114. # ifdef ENV_HACK
  1115. if (telopt_environ == TELOPT_OLD_ENVIRON
  1116.     && env_auto) {
  1117. /* Server has the same definitions */
  1118. old_env_var = OLD_ENV_VAR;
  1119. old_env_value = OLD_ENV_VALUE;
  1120. }
  1121. /* FALL THROUGH */
  1122. # endif
  1123. case OLD_ENV_VALUE:
  1124. /*
  1125.  * Although OLD_ENV_VALUE is not legal, we will
  1126.  * still recognize it, just in case it is an
  1127.  * old server that has VAR & VALUE mixed up...
  1128.  */
  1129. /* FALL THROUGH */
  1130. #else
  1131. case NEW_ENV_VAR:
  1132. #endif
  1133. case ENV_USERVAR:
  1134. if (ep) {
  1135. *epc = 0;
  1136. env_opt_add(ep);
  1137. }
  1138. ep = epc = &buf[i+1];
  1139. break;
  1140. case ENV_ESC:
  1141. i++;
  1142. /*FALL THROUGH*/
  1143. default:
  1144. if (epc)
  1145. *epc++ = buf[i];
  1146. break;
  1147. }
  1148. }
  1149. if (ep) {
  1150. *epc = 0;
  1151. env_opt_add(ep);
  1152. }
  1153. env_opt_end(1);
  1154. break;
  1155. case TELQUAL_IS:
  1156. case TELQUAL_INFO:
  1157. /* Ignore for now.  We shouldn't get it anyway. */
  1158. break;
  1159. default:
  1160. break;
  1161. }
  1162. }
  1163. #define OPT_REPLY_SIZE 256
  1164. unsigned char *opt_reply;
  1165. unsigned char *opt_replyp;
  1166. unsigned char *opt_replyend;
  1167. void
  1168. env_opt_start()
  1169. {
  1170. if (opt_reply)
  1171. opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
  1172. else
  1173. opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE);
  1174. if (opt_reply == NULL) {
  1175. /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!n");
  1176. opt_reply = opt_replyp = opt_replyend = NULL;
  1177. return;
  1178. }
  1179. opt_replyp = opt_reply;
  1180. opt_replyend = opt_reply + OPT_REPLY_SIZE;
  1181. *opt_replyp++ = IAC;
  1182. *opt_replyp++ = SB;
  1183. *opt_replyp++ = telopt_environ;
  1184. *opt_replyp++ = TELQUAL_IS;
  1185. }
  1186. void
  1187. env_opt_start_info()
  1188. {
  1189. env_opt_start();
  1190. if (opt_replyp)
  1191.     opt_replyp[-1] = TELQUAL_INFO;
  1192. }
  1193. void
  1194. env_opt_add(ep)
  1195. register unsigned char *ep;
  1196. {
  1197. register unsigned char *vp, c;
  1198. if (opt_reply == NULL) /*XXX*/
  1199. return; /*XXX*/
  1200. if (ep == NULL || *ep == '') {
  1201. /* Send user defined variables first. */
  1202. env_default(1, 0);
  1203. while ((ep = env_default(0, 0)))
  1204. env_opt_add(ep);
  1205. /* Now add the list of well know variables.  */
  1206. env_default(1, 1);
  1207. while ((ep = env_default(0, 1)))
  1208. env_opt_add(ep);
  1209. return;
  1210. }
  1211. vp = env_getvalue(ep);
  1212. if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
  1213. strlen((char *)ep) + 6 > opt_replyend)
  1214. {
  1215. register int len;
  1216. opt_replyend += OPT_REPLY_SIZE;
  1217. len = opt_replyend - opt_reply;
  1218. opt_reply = (unsigned char *)realloc(opt_reply, len);
  1219. if (opt_reply == NULL) {
  1220. /*@*/ printf("env_opt_add: realloc() failed!!!n");
  1221. opt_reply = opt_replyp = opt_replyend = NULL;
  1222. return;
  1223. }
  1224. opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
  1225. opt_replyend = opt_reply + len;
  1226. }
  1227. if (opt_welldefined((char *)ep))
  1228. #ifdef OLD_ENVIRON
  1229. if (telopt_environ == TELOPT_OLD_ENVIRON)
  1230. *opt_replyp++ = old_env_var;
  1231. else
  1232. #endif
  1233. *opt_replyp++ = NEW_ENV_VAR;
  1234. else
  1235. *opt_replyp++ = ENV_USERVAR;
  1236. for (;;) {
  1237.     while ((c = *ep++)) {
  1238. switch(c&0xff) {
  1239. case IAC:
  1240. *opt_replyp++ = IAC;
  1241. break;
  1242. case NEW_ENV_VAR:
  1243. case NEW_ENV_VALUE:
  1244. case ENV_ESC:
  1245. case ENV_USERVAR:
  1246. *opt_replyp++ = ENV_ESC;
  1247. break;
  1248. }
  1249. *opt_replyp++ = c;
  1250. }
  1251.     if ((ep = vp)) {
  1252. #ifdef OLD_ENVIRON
  1253. if (telopt_environ == TELOPT_OLD_ENVIRON)
  1254. *opt_replyp++ = old_env_value;
  1255. else
  1256. #endif
  1257. *opt_replyp++ = NEW_ENV_VALUE;
  1258. vp = NULL;
  1259. } else
  1260. break;
  1261. }
  1262. }
  1263. int
  1264. opt_welldefined(ep)
  1265. char *ep;
  1266. {
  1267. if ((strcmp(ep, "USER") == 0) ||
  1268.     (strcmp(ep, "DISPLAY") == 0) ||
  1269.     (strcmp(ep, "PRINTER") == 0) ||
  1270.     (strcmp(ep, "SYSTEMTYPE") == 0) ||
  1271.     (strcmp(ep, "JOB") == 0) ||
  1272.     (strcmp(ep, "ACCT") == 0))
  1273. return(1);
  1274. return(0);
  1275. }
  1276. void
  1277. env_opt_end(emptyok)
  1278. register int emptyok;
  1279. {
  1280. register int len;
  1281. len = opt_replyp - opt_reply + 2;
  1282. if (emptyok || len > 6) {
  1283. *opt_replyp++ = IAC;
  1284. *opt_replyp++ = SE;
  1285. if (NETROOM() > len) {
  1286. ring_supply_data(&netoring, opt_reply, len);
  1287. printsub('>', &opt_reply[2], len - 2);
  1288. }
  1289. /*@*/ else printf("slc_end_reply: not enough roomn");
  1290. }
  1291. if (opt_reply) {
  1292. free(opt_reply);
  1293. opt_reply = opt_replyp = opt_replyend = NULL;
  1294. }
  1295. }
  1296.     int
  1297. telrcv()
  1298. {
  1299.     register int c;
  1300.     register int scc;
  1301.     register unsigned char *sbp;
  1302.     int count;
  1303.     int returnValue = 0;
  1304.     scc = 0;
  1305.     count = 0;
  1306.     while (TTYROOM() > 2) {
  1307. if (scc == 0) {
  1308.     if (count) {
  1309. ring_consumed(&netiring, count);
  1310. returnValue = 1;
  1311. count = 0;
  1312.     }
  1313.     sbp = netiring.consume;
  1314.     scc = ring_full_consecutive(&netiring);
  1315.     if (scc == 0) {
  1316. /* No more data coming in */
  1317. break;
  1318.     }
  1319. }
  1320. c = *sbp++ & 0xff, scc--; count++;
  1321. switch (telrcv_state) {
  1322. case TS_CR:
  1323.     telrcv_state = TS_DATA;
  1324.     if (c == '') {
  1325. break; /* Ignore  after CR */
  1326.     }
  1327.     else if ((c == 'n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
  1328. TTYADD(c);
  1329. break;
  1330.     }
  1331.     /* Else, fall through */
  1332. case TS_DATA:
  1333.     if (c == IAC) {
  1334. telrcv_state = TS_IAC;
  1335. break;
  1336.     }
  1337. #ifdef TN3270
  1338.     if (In3270) {
  1339. *Ifrontp++ = c;
  1340. while (scc > 0) {
  1341.     c = *sbp++ & 0377, scc--; count++;
  1342.     if (c == IAC) {
  1343. telrcv_state = TS_IAC;
  1344. break;
  1345.     }
  1346.     *Ifrontp++ = c;
  1347. }
  1348.     } else
  1349. #     endif /* defined(TN3270) */
  1350.     /*
  1351.      * The 'crmod' hack (see following) is needed
  1352.      * since we can't * set CRMOD on output only.
  1353.      * Machines like MULTICS like to send r without
  1354.      * n; since we must turn off CRMOD to get proper
  1355.      * input, the mapping is done here (sigh).
  1356.      */
  1357.     if ((c == 'r') && my_want_state_is_dont(TELOPT_BINARY)) {
  1358. if (scc > 0) {
  1359.     c = *sbp&0xff;
  1360.     if (c == 0) {
  1361. sbp++, scc--; count++;
  1362. /* a "true" CR */
  1363. TTYADD('r');
  1364.     } else if (my_want_state_is_dont(TELOPT_ECHO) &&
  1365. (c == 'n')) {
  1366. sbp++, scc--; count++;
  1367. TTYADD('n');
  1368.     } else {
  1369. TTYADD('r');
  1370. if (crmod) {
  1371. TTYADD('n');
  1372. }
  1373.     }
  1374. } else {
  1375.     telrcv_state = TS_CR;
  1376.     TTYADD('r');
  1377.     if (crmod) {
  1378.     TTYADD('n');
  1379.     }
  1380. }
  1381.     } else {
  1382. TTYADD(c);
  1383.     }
  1384.     continue;
  1385. case TS_IAC:
  1386. process_iac:
  1387.     switch (c) {
  1388.     case WILL:
  1389. telrcv_state = TS_WILL;
  1390. continue;
  1391.     case WONT:
  1392. telrcv_state = TS_WONT;
  1393. continue;
  1394.     case DO:
  1395. telrcv_state = TS_DO;
  1396. continue;
  1397.     case DONT:
  1398. telrcv_state = TS_DONT;
  1399. continue;
  1400.     case DM:
  1401.     /*
  1402.      * We may have missed an urgent notification,
  1403.      * so make sure we flush whatever is in the
  1404.      * buffer currently.
  1405.      */
  1406. printoption("RCVD", IAC, DM);
  1407. SYNCHing = 1;
  1408. (void) ttyflush(1);
  1409. SYNCHing = stilloob();
  1410. settimer(gotDM);
  1411. break;
  1412.     case SB:
  1413. SB_CLEAR();
  1414. telrcv_state = TS_SB;
  1415. continue;
  1416. #ifdef TN3270
  1417.     case EOR:
  1418. if (In3270) {
  1419.     if (Ibackp == Ifrontp) {
  1420. Ibackp = Ifrontp = Ibuf;
  1421. ISend = 0; /* should have been! */
  1422.     } else {
  1423. Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
  1424. ISend = 1;
  1425.     }
  1426. }
  1427. printoption("RCVD", IAC, EOR);
  1428. break;
  1429. #     endif /* defined(TN3270) */
  1430.     case IAC:
  1431. #ifndef TN3270
  1432. TTYADD(IAC);
  1433. #     else /* !defined(TN3270) */
  1434. if (In3270) {
  1435.     *Ifrontp++ = IAC;
  1436. } else {
  1437.     TTYADD(IAC);
  1438. }
  1439. #     endif /* !defined(TN3270) */
  1440. break;
  1441.     case NOP:
  1442.     case GA:
  1443.     default:
  1444. printoption("RCVD", IAC, c);
  1445. break;
  1446.     }
  1447.     telrcv_state = TS_DATA;
  1448.     continue;
  1449. case TS_WILL:
  1450.     printoption("RCVD", WILL, c);
  1451.     willoption(c);
  1452.     SetIn3270();
  1453.     telrcv_state = TS_DATA;
  1454.     continue;
  1455. case TS_WONT:
  1456.     printoption("RCVD", WONT, c);
  1457.     wontoption(c);
  1458.     SetIn3270();
  1459.     telrcv_state = TS_DATA;
  1460.     continue;
  1461. case TS_DO:
  1462.     printoption("RCVD", DO, c);
  1463.     dooption(c);
  1464.     SetIn3270();
  1465.     if (c == TELOPT_NAWS) {
  1466. sendnaws();
  1467.     } else if (c == TELOPT_LFLOW) {
  1468. localflow = 1;
  1469. setcommandmode();
  1470. setconnmode(0);
  1471.     }
  1472.     telrcv_state = TS_DATA;
  1473.     continue;
  1474. case TS_DONT:
  1475.     printoption("RCVD", DONT, c);
  1476.     dontoption(c);
  1477.     flushline = 1;
  1478.     setconnmode(0); /* set new tty mode (maybe) */
  1479.     SetIn3270();
  1480.     telrcv_state = TS_DATA;
  1481.     continue;
  1482. case TS_SB:
  1483.     if (c == IAC) {
  1484. telrcv_state = TS_SE;
  1485.     } else {
  1486. SB_ACCUM(c);
  1487.     }
  1488.     continue;
  1489. case TS_SE:
  1490.     if (c != SE) {
  1491. if (c != IAC) {
  1492.     /*
  1493.      * This is an error.  We only expect to get
  1494.      * "IAC IAC" or "IAC SE".  Several things may
  1495.      * have happend.  An IAC was not doubled, the
  1496.      * IAC SE was left off, or another option got
  1497.      * inserted into the suboption are all possibilities.
  1498.      * If we assume that the IAC was not doubled,
  1499.      * and really the IAC SE was left off, we could
  1500.      * get into an infinate loop here.  So, instead,
  1501.      * we terminate the suboption, and process the
  1502.      * partial suboption if we can.
  1503.      */
  1504.     SB_ACCUM(IAC);
  1505.     SB_ACCUM(c);
  1506.     subpointer -= 2;
  1507.     SB_TERM();
  1508.     printoption("In SUBOPTION processing, RCVD", IAC, c);
  1509.     suboption(); /* handle sub-option */
  1510.     SetIn3270();
  1511.     telrcv_state = TS_IAC;
  1512.     goto process_iac;
  1513. }
  1514. SB_ACCUM(c);
  1515. telrcv_state = TS_SB;
  1516.     } else {
  1517. SB_ACCUM(IAC);
  1518. SB_ACCUM(SE);
  1519. subpointer -= 2;
  1520. SB_TERM();
  1521. suboption(); /* handle sub-option */
  1522. SetIn3270();
  1523. telrcv_state = TS_DATA;
  1524.     }
  1525. }
  1526.     }
  1527.     if (count)
  1528. ring_consumed(&netiring, count);
  1529.     return returnValue||count;
  1530. }
  1531. static int bol = 1, local = 0;
  1532.     int
  1533. rlogin_susp()
  1534. {
  1535.     if (local) {
  1536. local = 0;
  1537. bol = 1;
  1538. command(0, "zn", 2);
  1539. return(1);
  1540.     }
  1541.     return(0);
  1542. }
  1543.     static int
  1544. telsnd()
  1545. {
  1546.     int tcc;
  1547.     int count;
  1548.     int returnValue = 0;
  1549.     unsigned char *tbp;
  1550.     tcc = 0;
  1551.     count = 0;
  1552.     while (NETROOM() > 2) {
  1553. register int sc;
  1554. register int c;
  1555. if (tcc == 0) {
  1556.     if (count) {
  1557. ring_consumed(&ttyiring, count);
  1558. returnValue = 1;
  1559. count = 0;
  1560.     }
  1561.     tbp = ttyiring.consume;
  1562.     tcc = ring_full_consecutive(&ttyiring);
  1563.     if (tcc == 0) {
  1564. break;
  1565.     }
  1566. }
  1567. c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
  1568. if (rlogin != _POSIX_VDISABLE) {
  1569. if (bol) {
  1570. bol = 0;
  1571. if (sc == rlogin) {
  1572. local = 1;
  1573. continue;
  1574. }
  1575. } else if (local) {
  1576. local = 0;
  1577. if (sc == '.' || c == termEofChar) {
  1578. bol = 1;
  1579. command(0, "closen", 6);
  1580. continue;
  1581. }
  1582. if (sc == termSuspChar) {
  1583. bol = 1;
  1584. command(0, "zn", 2);
  1585. continue;
  1586. }
  1587. if (sc == escape) {
  1588. command(0, (char *)tbp, tcc);
  1589. bol = 1;
  1590. count += tcc;
  1591. tcc = 0;
  1592. flushline = 1;
  1593. break;
  1594. }
  1595. if (sc != rlogin) {
  1596. ++tcc;
  1597. --tbp;
  1598. --count;
  1599. c = sc = rlogin;
  1600. }
  1601. }
  1602. if ((sc == 'n') || (sc == 'r'))
  1603. bol = 1;
  1604. } else if (sc == escape) {
  1605.     /*
  1606.      * Double escape is a pass through of a single escape character.
  1607.      */
  1608.     if (tcc && strip(*tbp) == escape) {
  1609. tbp++;
  1610. tcc--;
  1611. count++;
  1612. bol = 0;
  1613.     } else {
  1614. command(0, (char *)tbp, tcc);
  1615. bol = 1;
  1616. count += tcc;
  1617. tcc = 0;
  1618. flushline = 1;
  1619. break;
  1620.     }
  1621. } else
  1622.     bol = 0;
  1623. #ifdef KLUDGELINEMODE
  1624. if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
  1625.     if (tcc > 0 && strip(*tbp) == echoc) {
  1626. tcc--; tbp++; count++;
  1627.     } else {
  1628. dontlecho = !dontlecho;
  1629. settimer(echotoggle);
  1630. setconnmode(0);
  1631. flushline = 1;
  1632. break;
  1633.     }
  1634. }
  1635. #endif
  1636. if (MODE_LOCAL_CHARS(globalmode)) {
  1637.     if (TerminalSpecialChars(sc) == 0) {
  1638. bol = 1;
  1639. break;
  1640.     }
  1641. }
  1642. if (my_want_state_is_wont(TELOPT_BINARY)) {
  1643.     switch (c) {
  1644.     case 'n':
  1645.     /*
  1646.      * If we are in CRMOD mode (r ==> n)
  1647.      * on our local machine, then probably
  1648.      * a newline (unix) is CRLF (TELNET).
  1649.      */
  1650. if (MODE_LOCAL_CHARS(globalmode)) {
  1651.     NETADD('r');
  1652. }
  1653. NETADD('n');
  1654. bol = flushline = 1;
  1655. break;
  1656.     case 'r':
  1657. if (!crlf) {
  1658.     NET2ADD('r', '');
  1659. } else {
  1660.     NET2ADD('r', 'n');
  1661. }
  1662. bol = flushline = 1;
  1663. break;
  1664.     case IAC:
  1665. NET2ADD(IAC, IAC);
  1666. break;
  1667.     default:
  1668. NETADD(c);
  1669. break;
  1670.     }
  1671. } else if (c == IAC) {
  1672.     NET2ADD(IAC, IAC);
  1673. } else {
  1674.     NETADD(c);
  1675. }
  1676.     }
  1677.     if (count)
  1678. ring_consumed(&ttyiring, count);
  1679.     return returnValue||count; /* Non-zero if we did anything */
  1680. }
  1681. /*
  1682.  * Scheduler()
  1683.  *
  1684.  * Try to do something.
  1685.  *
  1686.  * If we do something useful, return 1; else return 0.
  1687.  *
  1688.  */
  1689.     int
  1690. Scheduler(block)
  1691.     int block; /* should we block in the select ? */
  1692. {
  1693. /* One wants to be a bit careful about setting returnValue
  1694.  * to one, since a one implies we did some useful work,
  1695.  * and therefore probably won't be called to block next
  1696.  * time (TN3270 mode only).
  1697.  */
  1698.     int returnValue;
  1699.     int netin, netout, netex, ttyin, ttyout;
  1700.     /* Decide which rings should be processed */
  1701.     netout = ring_full_count(&netoring) &&
  1702.     (flushline ||
  1703. (my_want_state_is_wont(TELOPT_LINEMODE)
  1704. #ifdef KLUDGELINEMODE
  1705. && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
  1706. #endif
  1707. ) ||
  1708. my_want_state_is_will(TELOPT_BINARY));
  1709.     ttyout = ring_full_count(&ttyoring);
  1710. #ifdef TN3270
  1711.     ttyin = ring_empty_count(&ttyiring) && (shell_active == 0);
  1712. #else /* defined(TN3270) */
  1713.     ttyin = ring_empty_count(&ttyiring);
  1714. #endif /* defined(TN3270) */
  1715. #ifdef TN3270
  1716.     netin = ring_empty_count(&netiring);
  1717. #   else /* !defined(TN3270) */
  1718.     netin = !ISend && ring_empty_count(&netiring);
  1719. #   endif /* !defined(TN3270) */
  1720.     netex = !SYNCHing;
  1721.     /* If we have seen a signal recently, reset things */
  1722. #ifdef TN3270 
  1723.     if (HaveInput) {
  1724. HaveInput = 0;
  1725. (void) signal(SIGIO, inputAvailable);
  1726.     }
  1727. #endif /* defined(TN3270) */
  1728.     /* Call to system code to process rings */
  1729.     returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
  1730.     /* Now, look at the input rings, looking for work to do. */
  1731.     if (ring_full_count(&ttyiring)) {
  1732. #ifdef TN3270
  1733. if (In3270) {
  1734.     int c;
  1735.     c = DataFromTerminal(ttyiring.consume,
  1736. ring_full_consecutive(&ttyiring));
  1737.     if (c) {
  1738. returnValue = 1;
  1739. ring_consumed(&ttyiring, c);
  1740.     }
  1741. } else {
  1742. #   endif /* defined(TN3270) */
  1743.     returnValue |= telsnd();
  1744. #ifdef TN3270
  1745. }
  1746. #   endif /* defined(TN3270) */
  1747.     }
  1748.     if (ring_full_count(&netiring)) {
  1749. #ifndef TN3270
  1750. returnValue |= telrcv();
  1751. # else /* !defined(TN3270) */
  1752. returnValue = Push3270();
  1753. # endif /* !defined(TN3270) */
  1754.     }
  1755.     return returnValue;
  1756. }
  1757. /*
  1758.  * Select from tty and network...
  1759.  */
  1760.     void
  1761. telnet(user)
  1762.     char *user;
  1763. {
  1764.     sys_telnet_init();
  1765. #ifndef TN3270
  1766.     if (telnetport) {
  1767. send_do(TELOPT_SGA, 1);
  1768. send_will(TELOPT_TTYPE, 1);
  1769. send_will(TELOPT_NAWS, 1);
  1770. send_will(TELOPT_TSPEED, 1);
  1771. send_will(TELOPT_LFLOW, 1);
  1772. send_will(TELOPT_LINEMODE, 1);
  1773. send_will(TELOPT_NEW_ENVIRON, 1);
  1774. send_do(TELOPT_STATUS, 1);
  1775. if (env_getvalue((unsigned char *)"DISPLAY"))
  1776.     send_will(TELOPT_XDISPLOC, 1);
  1777. if (eight)
  1778.     tel_enter_binary(eight);
  1779.     }
  1780. #   endif /* !defined(TN3270) */
  1781. #ifndef TN3270
  1782.     for (;;) {
  1783. int schedValue;
  1784. while ((schedValue = Scheduler(0)) != 0) {
  1785.     if (schedValue == -1) {
  1786. setcommandmode();
  1787. return;
  1788.     }
  1789. }
  1790. if (Scheduler(1) == -1) {
  1791.     setcommandmode();
  1792.     return;
  1793. }
  1794.     }
  1795. #   else /* !defined(TN3270) */
  1796.     for (;;) {
  1797. int schedValue;
  1798. while (!In3270 && !shell_active) {
  1799.     if (Scheduler(1) == -1) {
  1800. setcommandmode();
  1801. return;
  1802.     }
  1803. }
  1804. while ((schedValue = Scheduler(0)) != 0) {
  1805.     if (schedValue == -1) {
  1806. setcommandmode();
  1807. return;
  1808.     }
  1809. }
  1810. /* If there is data waiting to go out to terminal, don't
  1811.  * schedule any more data for the terminal.
  1812.  */
  1813. if (ring_full_count(&ttyoring)) {
  1814.     schedValue = 1;
  1815. } else {
  1816.     if (shell_active) {
  1817. if (shell_continue() == 0) {
  1818.     ConnectScreen();
  1819. }
  1820.     } else if (In3270) {
  1821. schedValue = DoTerminalOutput();
  1822.     }
  1823. }
  1824. if (schedValue && (shell_active == 0)) {
  1825.     if (Scheduler(1) == -1) {
  1826. setcommandmode();
  1827. return;
  1828.     }
  1829. }
  1830.     }
  1831. #   endif /* !defined(TN3270) */
  1832. }
  1833. #if 0 /* XXX - this not being in is a bug */
  1834. /*
  1835.  * nextitem()
  1836.  *
  1837.  * Return the address of the next "item" in the TELNET data
  1838.  * stream.  This will be the address of the next character if
  1839.  * the current address is a user data character, or it will
  1840.  * be the address of the character following the TELNET command
  1841.  * if the current address is a TELNET IAC ("I Am a Command")
  1842.  * character.
  1843.  */
  1844.     static char *
  1845. nextitem(current)
  1846.     char *current;
  1847. {
  1848.     if ((*current&0xff) != IAC) {
  1849. return current+1;
  1850.     }
  1851.     switch (*(current+1)&0xff) {
  1852.     case DO:
  1853.     case DONT:
  1854.     case WILL:
  1855.     case WONT:
  1856. return current+3;
  1857.     case SB: /* loop forever looking for the SE */
  1858. {
  1859.     register char *look = current+2;
  1860.     for (;;) {
  1861. if ((*look++&0xff) == IAC) {
  1862.     if ((*look++&0xff) == SE) {
  1863. return look;
  1864.     }
  1865. }
  1866.     }
  1867. }
  1868.     default:
  1869. return current+2;
  1870.     }
  1871. }
  1872. #endif /* 0 */
  1873. /*
  1874.  * netclear()
  1875.  *
  1876.  * We are about to do a TELNET SYNCH operation.  Clear
  1877.  * the path to the network.
  1878.  *
  1879.  * Things are a bit tricky since we may have sent the first
  1880.  * byte or so of a previous TELNET command into the network.
  1881.  * So, we have to scan the network buffer from the beginning
  1882.  * until we are up to where we want to be.
  1883.  *
  1884.  * A side effect of what we do, just to keep things
  1885.  * simple, is to clear the urgent data pointer.  The principal
  1886.  * caller should be setting the urgent data pointer AFTER calling
  1887.  * us in any case.
  1888.  */
  1889.     static void
  1890. netclear()
  1891. {
  1892. #if 0 /* XXX */
  1893.     register char *thisitem, *next;
  1894.     char *good;
  1895. #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && 
  1896. ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
  1897.     thisitem = netobuf;
  1898.     while ((next = nextitem(thisitem)) <= netobuf.send) {
  1899. thisitem = next;
  1900.     }
  1901.     /* Now, thisitem is first before/at boundary. */
  1902.     good = netobuf; /* where the good bytes go */
  1903.     while (netoring.add > thisitem) {
  1904. if (wewant(thisitem)) {
  1905.     int length;
  1906.     next = thisitem;
  1907.     do {
  1908. next = nextitem(next);
  1909.     } while (wewant(next) && (nfrontp > next));
  1910.     length = next-thisitem;
  1911.     memmove(good, thisitem, length);
  1912.     good += length;
  1913.     thisitem = next;
  1914. } else {
  1915.     thisitem = nextitem(thisitem);
  1916. }
  1917.     }
  1918. #endif /* 0 */
  1919. }
  1920. /*
  1921.  * These routines add various telnet commands to the data stream.
  1922.  */
  1923.     static void
  1924. doflush()
  1925. {
  1926.     NET2ADD(IAC, DO);
  1927.     NETADD(TELOPT_TM);
  1928.     flushline = 1;
  1929.     flushout = 1;
  1930.     (void) ttyflush(1); /* Flush/drop output */
  1931.     /* do printoption AFTER flush, otherwise the output gets tossed... */
  1932.     printoption("SENT", DO, TELOPT_TM);
  1933. }
  1934.     void
  1935. xmitAO()
  1936. {
  1937.     NET2ADD(IAC, AO);
  1938.     printoption("SENT", IAC, AO);
  1939.     if (autoflush) {
  1940. doflush();
  1941.     }
  1942. }
  1943.     void
  1944. xmitEL()
  1945. {
  1946.     NET2ADD(IAC, EL);
  1947.     printoption("SENT", IAC, EL);
  1948. }
  1949.     void
  1950. xmitEC()
  1951. {
  1952.     NET2ADD(IAC, EC);
  1953.     printoption("SENT", IAC, EC);
  1954. }
  1955.     int
  1956. dosynch()
  1957. {
  1958.     netclear(); /* clear the path to the network */
  1959.     NETADD(IAC);
  1960.     setneturg();
  1961.     NETADD(DM);
  1962.     printoption("SENT", IAC, DM);
  1963.     return 1;
  1964. }
  1965. int want_status_response = 0;
  1966.     int
  1967. get_status()
  1968. {
  1969.     unsigned char tmp[16];
  1970.     register unsigned char *cp;
  1971.     if (my_want_state_is_dont(TELOPT_STATUS)) {
  1972. printf("Remote side does not support STATUS optionn");
  1973. return 0;
  1974.     }
  1975.     cp = tmp;
  1976.     *cp++ = IAC;
  1977.     *cp++ = SB;
  1978.     *cp++ = TELOPT_STATUS;
  1979.     *cp++ = TELQUAL_SEND;
  1980.     *cp++ = IAC;
  1981.     *cp++ = SE;
  1982.     if (NETROOM() >= cp - tmp) {
  1983. ring_supply_data(&netoring, tmp, cp-tmp);
  1984. printsub('>', tmp+2, cp - tmp - 2);
  1985.     }
  1986.     ++want_status_response;
  1987.     return 1;
  1988. }
  1989.     void
  1990. intp()
  1991. {
  1992.     NET2ADD(IAC, IP);
  1993.     printoption("SENT", IAC, IP);
  1994.     flushline = 1;
  1995.     if (autoflush) {
  1996. doflush();
  1997.     }
  1998.     if (autosynch) {
  1999. dosynch();
  2000.     }
  2001. }
  2002.     void
  2003. sendbrk()
  2004. {
  2005.     NET2ADD(IAC, BREAK);
  2006.     printoption("SENT", IAC, BREAK);
  2007.     flushline = 1;
  2008.     if (autoflush) {
  2009. doflush();
  2010.     }
  2011.     if (autosynch) {
  2012. dosynch();
  2013.     }
  2014. }
  2015.     void
  2016. sendabort()
  2017. {
  2018.     NET2ADD(IAC, ABORT);
  2019.     printoption("SENT", IAC, ABORT);
  2020.     flushline = 1;
  2021.     if (autoflush) {
  2022. doflush();
  2023.     }
  2024.     if (autosynch) {
  2025. dosynch();
  2026.     }
  2027. }
  2028.     void
  2029. sendsusp()
  2030. {
  2031.     NET2ADD(IAC, SUSP);
  2032.     printoption("SENT", IAC, SUSP);
  2033.     flushline = 1;
  2034.     if (autoflush) {
  2035. doflush();
  2036.     }
  2037.     if (autosynch) {
  2038. dosynch();
  2039.     }
  2040. }
  2041.     void
  2042. sendeof()
  2043. {
  2044.     NET2ADD(IAC, xEOF);
  2045.     printoption("SENT", IAC, xEOF);
  2046. }
  2047.     void
  2048. sendayt()
  2049. {
  2050.     NET2ADD(IAC, AYT);
  2051.     printoption("SENT", IAC, AYT);
  2052. }
  2053. /*
  2054.  * Send a window size update to the remote system.
  2055.  */
  2056.     void
  2057. sendnaws()
  2058. {
  2059.     long rows, cols;
  2060.     unsigned char tmp[16];
  2061.     register unsigned char *cp;
  2062.     if (my_state_is_wont(TELOPT_NAWS))
  2063. return;
  2064. #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; 
  2065.     if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
  2066.     if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
  2067. return;
  2068.     }
  2069.     cp = tmp;
  2070.     *cp++ = IAC;
  2071.     *cp++ = SB;
  2072.     *cp++ = TELOPT_NAWS;
  2073.     PUTSHORT(cp, cols);
  2074.     PUTSHORT(cp, rows);
  2075.     *cp++ = IAC;
  2076.     *cp++ = SE;
  2077.     if (NETROOM() >= cp - tmp) {
  2078. ring_supply_data(&netoring, tmp, cp-tmp);
  2079. printsub('>', tmp+2, cp - tmp - 2);
  2080.     }
  2081. }
  2082.     void
  2083. tel_enter_binary(rw)
  2084.     int rw;
  2085. {
  2086.     if (rw&1)
  2087. send_do(TELOPT_BINARY, 1);
  2088.     if (rw&2)
  2089. send_will(TELOPT_BINARY, 1);
  2090. }
  2091.     void
  2092. tel_leave_binary(rw)
  2093.     int rw;
  2094. {
  2095.     if (rw&1)
  2096. send_dont(TELOPT_BINARY, 1);
  2097.     if (rw&2)
  2098. send_wont(TELOPT_BINARY, 1);
  2099. }