Line data Source code
1 : /*
2 : Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 : 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
4 : 2015 Free Software Foundation, Inc.
5 :
6 : This file is part of GNU Inetutils.
7 :
8 : GNU Inetutils is free software: you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation, either version 3 of the License, or (at
11 : your option) any later version.
12 :
13 : GNU Inetutils is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see `http://www.gnu.org/licenses/'. */
20 :
21 : /*
22 : * Copyright (c) 1988, 1990, 1993
23 : * The Regents of the University of California. All rights reserved.
24 : *
25 : * Redistribution and use in source and binary forms, with or without
26 : * modification, are permitted provided that the following conditions
27 : * are met:
28 : * 1. Redistributions of source code must retain the above copyright
29 : * notice, this list of conditions and the following disclaimer.
30 : * 2. Redistributions in binary form must reproduce the above copyright
31 : * notice, this list of conditions and the following disclaimer in the
32 : * documentation and/or other materials provided with the distribution.
33 : * 3. Neither the name of the University nor the names of its contributors
34 : * may be used to endorse or promote products derived from this software
35 : * without specific prior written permission.
36 : *
37 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 : * SUCH DAMAGE.
48 : */
49 :
50 : #include <config.h>
51 :
52 : #include <sys/types.h>
53 :
54 : #if defined unix || defined __unix || defined __unix__
55 : # include <signal.h>
56 : /* By the way, we need to include curses.h before telnet.h since,
57 : * among other things, telnet.h #defines 'DO', which is a variable
58 : * declared in curses.h.
59 : */
60 : #endif /* unix || __unix || __unix__ */
61 :
62 : #include <arpa/telnet.h>
63 :
64 : #include <ctype.h>
65 : #include <stdlib.h>
66 :
67 : #include <libinetutils.h>
68 :
69 : #include "ring.h"
70 :
71 : #include "defines.h"
72 : #include "externs.h"
73 : #include "types.h"
74 : #include "general.h"
75 :
76 : #ifdef HAVE_TERMCAP_TGETENT
77 : # include <termcap.h>
78 : #elif defined HAVE_CURSES_TGETENT
79 : # include <curses.h>
80 : # include <term.h>
81 : #endif
82 :
83 : #ifdef AUTHENTICATION
84 : # include <libtelnet/auth.h>
85 : #endif
86 : #ifdef ENCRYPTION
87 : # include <libtelnet/encrypt.h>
88 : #endif
89 : #if defined AUTHENTICATION || defined ENCRYPTION
90 : # include <libtelnet/misc.h>
91 : #endif
92 :
93 :
94 : #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
95 :
96 : static unsigned char subbuffer[SUBBUFSIZE], *subpointer, *subend; /* buffer for sub-options */
97 : #define SB_CLEAR() subpointer = subbuffer;
98 : #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
99 : #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
100 : *subpointer++ = (c); \
101 : }
102 :
103 : #define SB_GET() ((*subpointer++)&0xff)
104 : #define SB_PEEK() ((*subpointer)&0xff)
105 : #define SB_EOF() (subpointer >= subend)
106 : #define SB_LEN() (subend - subpointer)
107 :
108 : char options[256] = { 0 }; /* The combined options */
109 : char do_dont_resp[256] = { 0 };
110 : char will_wont_resp[256] = { 0 };
111 :
112 : int eight = 0, autologin = 0, /* Autologin anyone? */
113 : skiprc = 0, connected, showoptions, In3270, /* Are we in 3270 mode? */
114 : ISend, /* trying to send network data in */
115 : debug = 0, crmod, netdata, /* Print out network data flow */
116 : crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
117 : #if defined TN3270
118 : noasynchtty = 0, /* User specified "-noasynch" on command line */
119 : noasynchnet = 0, /* User specified "-noasynch" on command line */
120 : askedSGA = 0, /* We have talked about suppress go ahead */
121 : #endif
122 : /* defined(TN3270) */
123 : telnetport, SYNCHing, /* we are in TELNET SYNCH mode */
124 : flushout, /* flush output */
125 : autoflush = 0, /* flush output when interrupting? */
126 : autosynch, /* send interrupt characters with SYNCH? */
127 : localflow, /* we handle flow control locally */
128 : restartany, /* if flow control enabled, restart on any character */
129 : localchars, /* we recognize interrupt/quit */
130 : donelclchars, /* the user has set "localchars" */
131 : donebinarytoggle, /* the user has put us in binary */
132 : dontlecho, /* do we suppress local echoing right now? */
133 : globalmode;
134 :
135 : char *prompt = 0;
136 :
137 : cc_t escape;
138 : cc_t rlogin;
139 : #ifdef KLUDGELINEMODE
140 : cc_t echoc;
141 : #endif
142 :
143 : /*
144 : * Telnet receiver states for fsm
145 : */
146 : #define TS_DATA 0
147 : #define TS_IAC 1
148 : #define TS_WILL 2
149 : #define TS_WONT 3
150 : #define TS_DO 4
151 : #define TS_DONT 5
152 : #define TS_CR 6
153 : #define TS_SB 7 /* sub-option collection */
154 : #define TS_SE 8 /* looking for sub-option end */
155 :
156 : static int telrcv_state;
157 : #ifdef OLD_ENVIRON
158 : unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
159 : #else
160 : # define telopt_environ TELOPT_NEW_ENVIRON
161 : #endif
162 :
163 : jmp_buf toplevel;
164 : jmp_buf peerdied;
165 :
166 : int flushline;
167 : int linemode;
168 :
169 : #ifdef KLUDGELINEMODE
170 : int kludgelinemode = 1;
171 : #endif
172 :
173 : /*
174 : * The following are some clocks used to decide how to interpret
175 : * the relationship between various variables.
176 : */
177 :
178 : Clocks clocks;
179 :
180 :
181 :
182 : /*
183 : * Initialize telnet environment.
184 : */
185 :
186 : void
187 3 : init_telnet (void)
188 : {
189 3 : env_init ();
190 :
191 3 : SB_CLEAR ();
192 :
193 3 : connected = In3270 = ISend = localflow = donebinarytoggle = 0;
194 : #if defined AUTHENTICATION || defined ENCRYPTION
195 : auth_encrypt_connect (connected);
196 : #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
197 3 : restartany = -1;
198 :
199 3 : SYNCHing = 0;
200 :
201 : /* Don't change NetTrace */
202 :
203 3 : escape = CONTROL (']');
204 3 : rlogin = _POSIX_VDISABLE;
205 : #ifdef KLUDGELINEMODE
206 3 : echoc = CONTROL ('E');
207 : #endif
208 :
209 3 : flushline = 1;
210 3 : telrcv_state = TS_DATA;
211 3 : }
212 :
213 : /*
214 : * These routines are in charge of sending option negotiations
215 : * to the other side.
216 : *
217 : * The basic idea is that we send the negotiation if either side
218 : * is in disagreement as to what the current state should be.
219 : */
220 :
221 : void
222 0 : send_do (register int c, register int init)
223 : {
224 0 : if (init)
225 : {
226 0 : if (((do_dont_resp[c] == 0) && my_state_is_do (c)) ||
227 0 : my_want_state_is_do (c))
228 0 : return;
229 0 : set_my_want_state_do (c);
230 0 : do_dont_resp[c]++;
231 : }
232 0 : NET2ADD (IAC, DO);
233 0 : NETADD (c);
234 0 : printoption ("SENT", DO, c);
235 : }
236 :
237 : void
238 0 : send_dont (register int c, register int init)
239 : {
240 0 : if (init)
241 : {
242 0 : if (((do_dont_resp[c] == 0) && my_state_is_dont (c)) ||
243 0 : my_want_state_is_dont (c))
244 0 : return;
245 0 : set_my_want_state_dont (c);
246 0 : do_dont_resp[c]++;
247 : }
248 0 : NET2ADD (IAC, DONT);
249 0 : NETADD (c);
250 0 : printoption ("SENT", DONT, c);
251 : }
252 :
253 : void
254 0 : send_will (register int c, register int init)
255 : {
256 0 : if (init)
257 : {
258 0 : if (((will_wont_resp[c] == 0) && my_state_is_will (c)) ||
259 0 : my_want_state_is_will (c))
260 0 : return;
261 0 : set_my_want_state_will (c);
262 0 : will_wont_resp[c]++;
263 : }
264 0 : NET2ADD (IAC, WILL);
265 0 : NETADD (c);
266 0 : printoption ("SENT", WILL, c);
267 : }
268 :
269 : void
270 0 : send_wont (register int c, register int init)
271 : {
272 0 : if (init)
273 : {
274 0 : if (((will_wont_resp[c] == 0) && my_state_is_wont (c)) ||
275 0 : my_want_state_is_wont (c))
276 0 : return;
277 0 : set_my_want_state_wont (c);
278 0 : will_wont_resp[c]++;
279 : }
280 0 : NET2ADD (IAC, WONT);
281 0 : NETADD (c);
282 0 : printoption ("SENT", WONT, c);
283 : }
284 :
285 :
286 : void
287 0 : willoption (int option)
288 : {
289 0 : int new_state_ok = 0;
290 :
291 0 : if (do_dont_resp[option])
292 : {
293 0 : --do_dont_resp[option];
294 0 : if (do_dont_resp[option] && my_state_is_do (option))
295 0 : --do_dont_resp[option];
296 : }
297 :
298 0 : if ((do_dont_resp[option] == 0) && my_want_state_is_dont (option))
299 : {
300 :
301 0 : switch (option)
302 : {
303 :
304 : case TELOPT_ECHO:
305 : #if defined TN3270
306 : /*
307 : * The following is a pain in the rear-end.
308 : * Various IBM servers (some versions of Wiscnet,
309 : * possibly Fibronics/Spartacus, and who knows who
310 : * else) will NOT allow us to send "DO SGA" too early
311 : * in the setup proceedings. On the other hand,
312 : * 4.2 servers (telnetd) won't set SGA correctly.
313 : * So, we are stuck. Empirically (but, based on
314 : * a VERY small sample), the IBM servers don't send
315 : * out anything about ECHO, so we postpone our sending
316 : * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
317 : * DO send).
318 : */
319 : {
320 : if (askedSGA == 0)
321 : {
322 : askedSGA = 1;
323 : if (my_want_state_is_dont (TELOPT_SGA))
324 : send_do (TELOPT_SGA, 1);
325 : }
326 : }
327 : /* Fall through */
328 : case TELOPT_EOR:
329 : #endif /* defined(TN3270) */
330 : case TELOPT_BINARY:
331 : case TELOPT_SGA:
332 0 : settimer (modenegotiated);
333 : /* FALL THROUGH */
334 : case TELOPT_STATUS:
335 : #if defined AUTHENTICATION
336 : case TELOPT_AUTHENTICATION:
337 : #endif
338 : #ifdef ENCRYPTION
339 : case TELOPT_ENCRYPT:
340 : #endif /* ENCRYPTION */
341 0 : new_state_ok = 1;
342 0 : break;
343 :
344 : case TELOPT_TM:
345 0 : if (flushout)
346 0 : flushout = 0;
347 : /*
348 : * Special case for TM. If we get back a WILL,
349 : * pretend we got back a WONT.
350 : */
351 0 : set_my_want_state_dont (option);
352 0 : set_my_state_dont (option);
353 0 : return; /* Never reply to TM will's/wont's */
354 :
355 : case TELOPT_LINEMODE:
356 : default:
357 0 : break;
358 : }
359 :
360 0 : if (new_state_ok)
361 : {
362 0 : set_my_want_state_do (option);
363 0 : send_do (option, 0);
364 0 : setconnmode (0); /* possibly set new tty mode */
365 : }
366 : else
367 : {
368 0 : do_dont_resp[option]++;
369 0 : send_dont (option, 0);
370 : }
371 : }
372 0 : set_my_state_do (option);
373 : #ifdef ENCRYPTION
374 : if (option == TELOPT_ENCRYPT)
375 : encrypt_send_support ();
376 : #endif /* ENCRYPTION */
377 : }
378 :
379 : void
380 0 : wontoption (int option)
381 : {
382 0 : if (do_dont_resp[option])
383 : {
384 0 : --do_dont_resp[option];
385 0 : if (do_dont_resp[option] && my_state_is_dont (option))
386 0 : --do_dont_resp[option];
387 : }
388 :
389 0 : if ((do_dont_resp[option] == 0) && my_want_state_is_do (option))
390 : {
391 :
392 0 : switch (option)
393 : {
394 :
395 : #ifdef KLUDGELINEMODE
396 : case TELOPT_SGA:
397 0 : if (!kludgelinemode)
398 0 : break;
399 : /* FALL THROUGH */
400 : #endif
401 : case TELOPT_ECHO:
402 0 : settimer (modenegotiated);
403 0 : break;
404 :
405 : case TELOPT_TM:
406 0 : if (flushout)
407 0 : flushout = 0;
408 0 : set_my_want_state_dont (option);
409 0 : set_my_state_dont (option);
410 0 : return; /* Never reply to TM will's/wont's */
411 :
412 : default:
413 0 : break;
414 : }
415 0 : set_my_want_state_dont (option);
416 0 : if (my_state_is_do (option))
417 0 : send_dont (option, 0);
418 0 : setconnmode (0); /* Set new tty mode */
419 : }
420 0 : else if (option == TELOPT_TM)
421 : {
422 : /*
423 : * Special case for TM.
424 : */
425 0 : if (flushout)
426 0 : flushout = 0;
427 0 : set_my_want_state_dont (option);
428 : }
429 0 : set_my_state_dont (option);
430 : }
431 :
432 : static void
433 0 : dooption (int option)
434 : {
435 0 : int new_state_ok = 0;
436 :
437 0 : if (will_wont_resp[option])
438 : {
439 0 : --will_wont_resp[option];
440 0 : if (will_wont_resp[option] && my_state_is_will (option))
441 0 : --will_wont_resp[option];
442 : }
443 :
444 0 : if (will_wont_resp[option] == 0)
445 : {
446 0 : if (my_want_state_is_wont (option))
447 : {
448 :
449 0 : switch (option)
450 : {
451 :
452 : case TELOPT_TM:
453 : /*
454 : * Special case for TM. We send a WILL, but pretend
455 : * we sent WONT.
456 : */
457 0 : send_will (option, 0);
458 0 : set_my_want_state_wont (TELOPT_TM);
459 0 : set_my_state_wont (TELOPT_TM);
460 0 : return;
461 :
462 : #if defined TN3270
463 : case TELOPT_EOR: /* end of record */
464 : #endif /* defined(TN3270) */
465 : case TELOPT_BINARY: /* binary mode */
466 : case TELOPT_NAWS: /* window size */
467 : case TELOPT_TSPEED: /* terminal speed */
468 : case TELOPT_LFLOW: /* local flow control */
469 : case TELOPT_TTYPE: /* terminal type option */
470 : case TELOPT_SGA: /* no big deal */
471 : #ifdef ENCRYPTION
472 : case TELOPT_ENCRYPT: /* encryption variable option */
473 : #endif /* ENCRYPTION */
474 0 : new_state_ok = 1;
475 0 : break;
476 :
477 : case TELOPT_NEW_ENVIRON: /* New environment variable option */
478 : #ifdef OLD_ENVIRON
479 : if (my_state_is_will (TELOPT_OLD_ENVIRON))
480 : send_wont (TELOPT_OLD_ENVIRON, 1); /* turn off the old */
481 : goto env_common;
482 : case TELOPT_OLD_ENVIRON: /* Old environment variable option */
483 : if (my_state_is_will (TELOPT_NEW_ENVIRON))
484 : break; /* Don't enable if new one is in use! */
485 : env_common:
486 : telopt_environ = option;
487 : #endif
488 0 : new_state_ok = 1;
489 0 : break;
490 :
491 : #if defined AUTHENTICATION
492 : case TELOPT_AUTHENTICATION:
493 : if (autologin)
494 : new_state_ok = 1;
495 : break;
496 : #endif
497 :
498 : case TELOPT_XDISPLOC: /* X Display location */
499 0 : if (env_getvalue ("DISPLAY"))
500 0 : new_state_ok = 1;
501 0 : break;
502 :
503 : case TELOPT_LINEMODE:
504 : #ifdef KLUDGELINEMODE
505 0 : kludgelinemode = 0;
506 0 : send_do (TELOPT_SGA, 1);
507 : #endif
508 0 : set_my_want_state_will (TELOPT_LINEMODE);
509 0 : send_will (option, 0);
510 0 : set_my_state_will (TELOPT_LINEMODE);
511 0 : slc_init ();
512 0 : return;
513 :
514 : case TELOPT_ECHO: /* We're never going to echo... */
515 : default:
516 0 : break;
517 : }
518 :
519 0 : if (new_state_ok)
520 : {
521 0 : set_my_want_state_will (option);
522 0 : send_will (option, 0);
523 0 : setconnmode (0); /* Set new tty mode */
524 : }
525 : else
526 : {
527 0 : will_wont_resp[option]++;
528 0 : send_wont (option, 0);
529 : }
530 : }
531 : else
532 : {
533 : /*
534 : * Handle options that need more things done after the
535 : * other side has acknowledged the option.
536 : */
537 0 : switch (option)
538 : {
539 : case TELOPT_LINEMODE:
540 : #ifdef KLUDGELINEMODE
541 0 : kludgelinemode = 0;
542 0 : send_do (TELOPT_SGA, 1);
543 : #endif
544 0 : set_my_state_will (option);
545 0 : slc_init ();
546 0 : send_do (TELOPT_SGA, 0);
547 0 : return;
548 : }
549 : }
550 : }
551 0 : set_my_state_will (option);
552 : }
553 :
554 : static void
555 0 : dontoption (int option)
556 : {
557 :
558 0 : if (will_wont_resp[option])
559 : {
560 0 : --will_wont_resp[option];
561 0 : if (will_wont_resp[option] && my_state_is_wont (option))
562 0 : --will_wont_resp[option];
563 : }
564 :
565 0 : if ((will_wont_resp[option] == 0) && my_want_state_is_will (option))
566 : {
567 0 : switch (option)
568 : {
569 : case TELOPT_LINEMODE:
570 0 : linemode = 0; /* put us back to the default state */
571 0 : break;
572 : #ifdef OLD_ENVIRON
573 : case TELOPT_NEW_ENVIRON:
574 : /*
575 : * The new environ option wasn't recognized, try
576 : * the old one.
577 : */
578 : send_will (TELOPT_OLD_ENVIRON, 1);
579 : telopt_environ = TELOPT_OLD_ENVIRON;
580 : break;
581 : #endif
582 : }
583 : /* we always accept a DONT */
584 0 : set_my_want_state_wont (option);
585 0 : if (my_state_is_will (option))
586 0 : send_wont (option, 0);
587 0 : setconnmode (0); /* Set new tty mode */
588 : }
589 0 : set_my_state_wont (option);
590 0 : }
591 :
592 : int
593 0 : is_unique (register char *name, register char **as, register char **ae)
594 : {
595 : register char **ap;
596 : register int n;
597 :
598 0 : n = strlen (name) + 1;
599 0 : for (ap = as; ap < ae; ap++)
600 0 : if (strncasecmp (*ap, name, n) == 0)
601 0 : return (0);
602 0 : return (1);
603 : }
604 :
605 : /*
606 : * Given a buffer returned by tgetent(), this routine will turn
607 : * the pipe separated list of names in the buffer into an array
608 : * of pointers to null terminated names. We toss out any bad,
609 : * duplicate, or verbose names (names with spaces).
610 : */
611 :
612 : static char *name_unknown = "UNKNOWN";
613 : static char *unknown[] = { 0, 0 };
614 :
615 : char **
616 0 : mklist (char *buf, char *name)
617 : {
618 : register int n;
619 : register char c, *cp, **argvp, *cp2, **argv, **avt;
620 :
621 0 : if (name)
622 : {
623 0 : if ((int) strlen (name) > 40)
624 : {
625 0 : name = 0;
626 0 : unknown[0] = name_unknown;
627 : }
628 : else
629 : {
630 0 : unknown[0] = name;
631 0 : upcase (name);
632 : }
633 : }
634 : else
635 0 : unknown[0] = name_unknown;
636 :
637 : /*
638 : * An empty capability buffer finishes the analysis.
639 : */
640 0 : if (!buf || !*buf)
641 0 : return (unknown);
642 :
643 : /*
644 : * Count the number of alias names.
645 : * Stop at the first field separator, a colon.
646 : */
647 0 : for (n = 1, cp = buf; *cp && *cp != ':'; cp++)
648 : {
649 0 : if (*cp == '|')
650 0 : n++;
651 : }
652 :
653 : /*
654 : * Allocate an array to hold the name pointers.
655 : */
656 0 : argv = (char **) malloc ((n + 3) * sizeof (char *));
657 0 : if (argv == 0)
658 0 : return (unknown);
659 :
660 : /*
661 : * Fill the array of pointers with the established aliases.
662 : * Reserve the first slot for the preferred name.
663 : */
664 0 : argvp = argv + 1;
665 0 : *argv = *argvp = 0;
666 0 : n = 0; /* Positive: name uses white space. */
667 :
668 0 : for (cp = cp2 = buf; (c = *cp); cp++)
669 : {
670 0 : if (c == '|' || c == ':') /* Delimiters */
671 : {
672 0 : *cp++ = '\0';
673 : /*
674 : * Skip entries that have spaces or are over 40
675 : * characters long. If this is our environment
676 : * name, then put it up front. Otherwise, as
677 : * long as this is not a duplicate name (case
678 : * insensitive) add it to the list.
679 : */
680 0 : if (n || (cp - cp2 > 41))
681 : ; /* Ignore the just scanned name. */
682 0 : else if (name && (strncasecmp (name, cp2, cp - cp2) == 0))
683 0 : *argv = cp2; /* Preferred name, exact match. */
684 0 : else if (is_unique (cp2, argv + 1, argvp))
685 : {
686 0 : *argvp++ = cp2;
687 0 : *argvp = 0; /* Prevent looking forward. */
688 : }
689 :
690 : /* Abort parsing at first field delimiter. */
691 0 : if (c == ':')
692 0 : break;
693 :
694 : /*
695 : * Skip multiple delimiters. Reset CP2 to
696 : * the beginning of the next name. Reset N,
697 : * the flag for names with spaces.
698 : */
699 0 : while ((c = *cp) == '|')
700 0 : cp++;
701 :
702 0 : cp2 = cp; /* Proceed to next alias name. */
703 0 : n = 0;
704 : }
705 : /*
706 : * Skip entries with spaces or non-ascii values.
707 : * Convert lower case letters to upper case.
708 : */
709 0 : if ((c == ' ') || !isascii (c))
710 0 : n = 1;
711 0 : else if (islower (c))
712 0 : *cp = toupper (c);
713 : }
714 :
715 : /*
716 : * Check for an old V6 2 character name. If the second
717 : * name points to the beginning of the buffer, and is
718 : * only 2 characters long, move it to the end of the array.
719 : */
720 0 : if ((argv[1] == buf) && (strlen (argv[1]) == 2))
721 : {
722 0 : --argvp;
723 0 : for (avt = &argv[1]; avt < argvp; avt++)
724 0 : *avt = *(avt + 1);
725 0 : *argvp++ = buf;
726 : }
727 :
728 : /*
729 : * Duplicate last name, for TTYPE option, and null
730 : * terminate the array. If we didn't find a match on
731 : * our terminal name, put that name at the beginning.
732 : */
733 0 : cp = *(argvp - 1);
734 0 : *argvp++ = cp;
735 0 : *argvp = 0;
736 :
737 0 : if (*argv == 0)
738 : {
739 0 : if (name)
740 0 : *argv = name;
741 : else
742 : {
743 0 : --argvp;
744 0 : for (avt = argv; avt < argvp; avt++)
745 0 : *avt = *(avt + 1);
746 : }
747 : }
748 0 : if (*argv)
749 0 : return (argv);
750 : else
751 0 : return (unknown);
752 : }
753 :
754 : /* Claimed to be ignored by contemporary implementations,
755 : * but still modified by FreeBSD and NetBSD.
756 : * mklist will examine this buffer, so erase it
757 : * to cover corner cases.
758 : */
759 : char termbuf[2048] = { 0 };
760 :
761 : static int
762 0 : init_term (char *tname, int *errp)
763 : {
764 0 : int err = -1;
765 :
766 : #ifdef HAVE_TGETENT
767 0 : err = tgetent (termbuf, tname);
768 0 : if (err == 1)
769 : {
770 0 : termbuf[sizeof (termbuf) - 1] = '\0';
771 0 : if (errp)
772 0 : *errp = 1;
773 0 : return (0);
774 : }
775 : #endif /* HAVE_TGETENT */
776 0 : if (errp)
777 0 : *errp = 0;
778 0 : return (-1);
779 : }
780 :
781 : int resettermname = 1;
782 :
783 : char *
784 0 : gettermname (void)
785 : {
786 : char *tname;
787 : static char **tnamep = 0;
788 : static char **next;
789 : int err;
790 :
791 0 : if (resettermname)
792 : {
793 0 : resettermname = 0;
794 0 : if (tnamep && tnamep != unknown)
795 0 : free (tnamep);
796 0 : if ((tname = (char *) env_getvalue ("TERM")) &&
797 0 : (init_term (tname, &err) == 0))
798 : {
799 0 : tnamep = mklist (termbuf, tname);
800 : }
801 : else
802 : {
803 0 : if (tname && ((int) strlen (tname) <= 40))
804 : {
805 0 : unknown[0] = tname;
806 0 : upcase (tname);
807 : }
808 : else
809 0 : unknown[0] = name_unknown;
810 0 : tnamep = unknown;
811 : }
812 0 : next = tnamep;
813 : }
814 0 : if (*next == 0)
815 0 : next = tnamep;
816 0 : return (*next++);
817 : }
818 :
819 : /*
820 : * suboption()
821 : *
822 : * Look at the sub-option buffer, and try to be helpful to the other
823 : * side.
824 : *
825 : * Currently we recognize:
826 : *
827 : * Terminal type, send request.
828 : * Terminal speed (send request).
829 : * Local flow control (is request).
830 : * Linemode
831 : */
832 :
833 : static void
834 0 : suboption (void)
835 : {
836 : unsigned char subchar;
837 :
838 0 : printsub ('<', subbuffer, SB_LEN () + 2);
839 0 : switch (subchar = SB_GET ())
840 : {
841 : case TELOPT_TTYPE:
842 0 : if (my_want_state_is_wont (TELOPT_TTYPE))
843 0 : return;
844 0 : if (SB_EOF () || SB_GET () != TELQUAL_SEND)
845 : {
846 0 : return;
847 : }
848 : else
849 : {
850 : char *name;
851 : unsigned char temp[50];
852 : int len;
853 :
854 : #if defined TN3270
855 : if (tn3270_ttype ())
856 : {
857 : return;
858 : }
859 : #endif /* defined(TN3270) */
860 0 : name = gettermname ();
861 0 : len = strlen (name) + 4 + 2;
862 0 : if (len < NETROOM ())
863 : {
864 0 : sprintf ((char *) temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
865 : TELQUAL_IS, name, IAC, SE);
866 0 : ring_supply_data (&netoring, temp, len);
867 0 : printsub ('>', &temp[2], len - 2);
868 : }
869 : else
870 : {
871 0 : ExitString ("No room in buffer for terminal type.\n", 1);
872 : }
873 : }
874 0 : break;
875 : case TELOPT_TSPEED:
876 0 : if (my_want_state_is_wont (TELOPT_TSPEED))
877 0 : return;
878 0 : if (SB_EOF ())
879 0 : return;
880 0 : if (SB_GET () == TELQUAL_SEND)
881 : {
882 : long ospeed, ispeed;
883 : unsigned char temp[50];
884 : int len;
885 :
886 0 : TerminalSpeeds (&ispeed, &ospeed);
887 :
888 0 : sprintf ((char *) temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED,
889 : TELQUAL_IS, (int) ospeed, (int) ispeed, IAC, SE);
890 0 : len = strlen ((char *) temp + 4) + 4; /* temp[3] is 0 ... */
891 :
892 0 : if (len < NETROOM ())
893 : {
894 0 : ring_supply_data (&netoring, temp, len);
895 0 : printsub ('>', temp + 2, len - 2);
896 : }
897 : /*@*/
898 : else
899 0 : printf ("lm_will: not enough room in buffer\n");
900 : }
901 0 : break;
902 : case TELOPT_LFLOW:
903 0 : if (my_want_state_is_wont (TELOPT_LFLOW))
904 0 : return;
905 0 : if (SB_EOF ())
906 0 : return;
907 0 : switch (SB_GET ())
908 : {
909 : case LFLOW_RESTART_ANY:
910 0 : restartany = 1;
911 0 : break;
912 : case LFLOW_RESTART_XON:
913 0 : restartany = 0;
914 0 : break;
915 : case LFLOW_ON:
916 0 : localflow = 1;
917 0 : break;
918 : case LFLOW_OFF:
919 0 : localflow = 0;
920 0 : break;
921 : default:
922 0 : return;
923 : }
924 0 : setcommandmode ();
925 0 : setconnmode (0);
926 0 : break;
927 :
928 : case TELOPT_LINEMODE:
929 0 : if (my_want_state_is_wont (TELOPT_LINEMODE))
930 0 : return;
931 0 : if (SB_EOF ())
932 0 : return;
933 0 : switch (SB_GET ())
934 : {
935 : case WILL:
936 0 : lm_will (subpointer, SB_LEN ());
937 0 : break;
938 : case WONT:
939 0 : lm_wont (subpointer, SB_LEN ());
940 0 : break;
941 : case DO:
942 0 : lm_do (subpointer, SB_LEN ());
943 0 : break;
944 : case DONT:
945 0 : lm_dont (subpointer, SB_LEN ());
946 0 : break;
947 : case LM_SLC:
948 0 : slc (subpointer, SB_LEN ());
949 0 : break;
950 : case LM_MODE:
951 0 : lm_mode (subpointer, SB_LEN (), 0);
952 0 : break;
953 : default:
954 0 : break;
955 : }
956 0 : break;
957 :
958 : #ifdef OLD_ENVIRON
959 : case TELOPT_OLD_ENVIRON:
960 : #endif
961 : case TELOPT_NEW_ENVIRON:
962 0 : if (SB_EOF ())
963 0 : return;
964 0 : switch (SB_PEEK ())
965 : {
966 : case TELQUAL_IS:
967 : case TELQUAL_INFO:
968 0 : if (my_want_state_is_dont (subchar))
969 0 : return;
970 0 : break;
971 : case TELQUAL_SEND:
972 0 : if (my_want_state_is_wont (subchar))
973 : {
974 0 : return;
975 : }
976 0 : break;
977 : default:
978 0 : return;
979 : }
980 0 : env_opt (subpointer, SB_LEN ());
981 0 : break;
982 :
983 : case TELOPT_XDISPLOC:
984 0 : if (my_want_state_is_wont (TELOPT_XDISPLOC))
985 0 : return;
986 0 : if (SB_EOF ())
987 0 : return;
988 0 : if (SB_GET () == TELQUAL_SEND)
989 : {
990 : unsigned char temp[50], *dp;
991 : int len;
992 :
993 0 : if ((dp = env_getvalue ("DISPLAY")) == NULL)
994 : {
995 : /*
996 : * Something happened, we no longer have a DISPLAY
997 : * variable. So, turn off the option.
998 : */
999 0 : send_wont (TELOPT_XDISPLOC, 1);
1000 0 : break;
1001 : }
1002 0 : sprintf ((char *) temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
1003 : TELQUAL_IS, dp, IAC, SE);
1004 0 : len = strlen ((char *) temp + 4) + 4; /* temp[3] is 0 ... */
1005 :
1006 0 : if (len < NETROOM ())
1007 : {
1008 0 : ring_supply_data (&netoring, temp, len);
1009 0 : printsub ('>', temp + 2, len - 2);
1010 : }
1011 : /*@*/
1012 : else
1013 0 : printf ("lm_will: not enough room in buffer\n");
1014 : }
1015 0 : break;
1016 :
1017 : #if defined AUTHENTICATION
1018 : case TELOPT_AUTHENTICATION:
1019 : {
1020 : if (!autologin)
1021 : break;
1022 : if (SB_EOF ())
1023 : return;
1024 : switch (SB_GET ())
1025 : {
1026 : case TELQUAL_IS:
1027 : if (my_want_state_is_dont (TELOPT_AUTHENTICATION))
1028 : return;
1029 : auth_is (subpointer, SB_LEN ());
1030 : break;
1031 : case TELQUAL_SEND:
1032 : if (my_want_state_is_wont (TELOPT_AUTHENTICATION))
1033 : return;
1034 : auth_send (subpointer, SB_LEN ());
1035 : break;
1036 : case TELQUAL_REPLY:
1037 : if (my_want_state_is_wont (TELOPT_AUTHENTICATION))
1038 : return;
1039 : auth_reply (subpointer, SB_LEN ());
1040 : break;
1041 : case TELQUAL_NAME:
1042 : if (my_want_state_is_dont (TELOPT_AUTHENTICATION))
1043 : return;
1044 : auth_name (subpointer, SB_LEN ());
1045 : break;
1046 : }
1047 : }
1048 : break;
1049 : #endif
1050 : #ifdef ENCRYPTION
1051 : case TELOPT_ENCRYPT:
1052 : if (SB_EOF ())
1053 : return;
1054 : switch (SB_GET ())
1055 : {
1056 : case ENCRYPT_START:
1057 : if (my_want_state_is_dont (TELOPT_ENCRYPT))
1058 : return;
1059 : encrypt_start (subpointer, SB_LEN ());
1060 : break;
1061 : case ENCRYPT_END:
1062 : if (my_want_state_is_dont (TELOPT_ENCRYPT))
1063 : return;
1064 : encrypt_end ();
1065 : break;
1066 : case ENCRYPT_SUPPORT:
1067 : if (my_want_state_is_wont (TELOPT_ENCRYPT))
1068 : return;
1069 : encrypt_support (subpointer, SB_LEN ());
1070 : break;
1071 : case ENCRYPT_REQSTART:
1072 : if (my_want_state_is_wont (TELOPT_ENCRYPT))
1073 : return;
1074 : encrypt_request_start (subpointer, SB_LEN ());
1075 : break;
1076 : case ENCRYPT_REQEND:
1077 : if (my_want_state_is_wont (TELOPT_ENCRYPT))
1078 : return;
1079 : /*
1080 : * We can always send an REQEND so that we cannot
1081 : * get stuck encrypting. We should only get this
1082 : * if we have been able to get in the correct mode
1083 : * anyhow.
1084 : */
1085 : encrypt_request_end ();
1086 : break;
1087 : case ENCRYPT_IS:
1088 : if (my_want_state_is_dont (TELOPT_ENCRYPT))
1089 : return;
1090 : encrypt_is (subpointer, SB_LEN ());
1091 : break;
1092 : case ENCRYPT_REPLY:
1093 : if (my_want_state_is_wont (TELOPT_ENCRYPT))
1094 : return;
1095 : encrypt_reply (subpointer, SB_LEN ());
1096 : break;
1097 : case ENCRYPT_ENC_KEYID:
1098 : if (my_want_state_is_dont (TELOPT_ENCRYPT))
1099 : return;
1100 : encrypt_enc_keyid (subpointer, SB_LEN ());
1101 : break;
1102 : case ENCRYPT_DEC_KEYID:
1103 : if (my_want_state_is_wont (TELOPT_ENCRYPT))
1104 : return;
1105 : encrypt_dec_keyid (subpointer, SB_LEN ());
1106 : break;
1107 : default:
1108 : break;
1109 : }
1110 : break;
1111 : #endif /* ENCRYPTION */
1112 : default:
1113 0 : break;
1114 : }
1115 : }
1116 :
1117 : static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
1118 :
1119 : void
1120 0 : lm_will (unsigned char *cmd, int len)
1121 : {
1122 0 : if (len < 1)
1123 : {
1124 0 : /*@ */ printf ("lm_will: no command!!!\n");
1125 : /* Should not happen... */
1126 0 : return;
1127 : }
1128 0 : switch (cmd[0])
1129 : {
1130 : case LM_FORWARDMASK: /* We shouldn't ever get this... */
1131 : default:
1132 0 : str_lm[3] = DONT;
1133 0 : str_lm[4] = cmd[0];
1134 0 : if (NETROOM () > (int) sizeof (str_lm))
1135 : {
1136 0 : ring_supply_data (&netoring, str_lm, sizeof (str_lm));
1137 0 : printsub ('>', &str_lm[2], sizeof (str_lm) - 2);
1138 : }
1139 : /*@*/
1140 : else
1141 0 : printf ("lm_will: not enough room in buffer\n");
1142 0 : break;
1143 : }
1144 : }
1145 :
1146 : void
1147 0 : lm_wont (unsigned char *cmd, int len)
1148 : {
1149 0 : if (len < 1)
1150 : {
1151 0 : /*@ */ printf ("lm_wont: no command!!!\n");
1152 : /* Should not happen... */
1153 0 : return;
1154 : }
1155 0 : switch (cmd[0])
1156 : {
1157 : case LM_FORWARDMASK: /* We shouldn't ever get this... */
1158 : default:
1159 : /* We are always DONT, so don't respond */
1160 0 : return;
1161 : }
1162 : }
1163 :
1164 : void
1165 0 : lm_do (unsigned char *cmd, int len)
1166 : {
1167 0 : if (len < 1)
1168 : {
1169 0 : /*@ */ printf ("lm_do: no command!!!\n");
1170 : /* Should not happen... */
1171 0 : return;
1172 : }
1173 0 : switch (cmd[0])
1174 : {
1175 : case LM_FORWARDMASK:
1176 : default:
1177 0 : str_lm[3] = WONT;
1178 0 : str_lm[4] = cmd[0];
1179 0 : if (NETROOM () > (int) sizeof (str_lm))
1180 : {
1181 0 : ring_supply_data (&netoring, str_lm, sizeof (str_lm));
1182 0 : printsub ('>', &str_lm[2], sizeof (str_lm) - 2);
1183 : }
1184 : /*@*/
1185 : else
1186 0 : printf ("lm_do: not enough room in buffer\n");
1187 0 : break;
1188 : }
1189 : }
1190 :
1191 : void
1192 0 : lm_dont (unsigned char *cmd, int len)
1193 : {
1194 0 : if (len < 1)
1195 : {
1196 0 : /*@ */ printf ("lm_dont: no command!!!\n");
1197 : /* Should not happen... */
1198 0 : return;
1199 : }
1200 0 : switch (cmd[0])
1201 : {
1202 : case LM_FORWARDMASK:
1203 : default:
1204 : /* we are always WONT, so don't respond */
1205 0 : break;
1206 : }
1207 : }
1208 :
1209 : static unsigned char str_lm_mode[] = {
1210 : IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
1211 : };
1212 :
1213 : void
1214 0 : lm_mode (unsigned char *cmd, int len, int init)
1215 : {
1216 0 : if (len != 1)
1217 0 : return;
1218 0 : if ((linemode & MODE_MASK & ~MODE_ACK) == *cmd)
1219 0 : return;
1220 0 : if (*cmd & MODE_ACK)
1221 0 : return;
1222 0 : linemode = *cmd & (MODE_MASK & ~MODE_ACK);
1223 0 : str_lm_mode[4] = linemode;
1224 0 : if (!init)
1225 0 : str_lm_mode[4] |= MODE_ACK;
1226 0 : if (NETROOM () > (int) sizeof (str_lm_mode))
1227 : {
1228 0 : ring_supply_data (&netoring, str_lm_mode, sizeof (str_lm_mode));
1229 0 : printsub ('>', &str_lm_mode[2], sizeof (str_lm_mode) - 2);
1230 : }
1231 : /*@*/
1232 : else
1233 0 : printf ("lm_mode: not enough room in buffer\n");
1234 0 : setconnmode (0); /* set changed mode */
1235 : }
1236 :
1237 :
1238 :
1239 : /*
1240 : * slc()
1241 : * Handle special character suboption of LINEMODE.
1242 : */
1243 :
1244 : struct spc
1245 : {
1246 : cc_t val;
1247 : cc_t *valp;
1248 : char flags; /* Current flags & level */
1249 : char mylevel; /* Maximum level & flags */
1250 : } spc_data[NSLC + 1];
1251 :
1252 : #define SLC_IMPORT 0
1253 : #define SLC_EXPORT 1
1254 : #define SLC_RVALUE 2
1255 : static int slc_mode = SLC_EXPORT;
1256 :
1257 : void
1258 0 : slc_init (void)
1259 : {
1260 : register struct spc *spcp;
1261 :
1262 0 : localchars = 1;
1263 0 : for (spcp = spc_data; spcp < &spc_data[NSLC + 1]; spcp++)
1264 : {
1265 0 : spcp->val = 0;
1266 0 : spcp->valp = 0;
1267 0 : spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
1268 : }
1269 :
1270 : #define initfunc(func, flags) { \
1271 : spcp = &spc_data[func]; \
1272 : if ((spcp->valp = tcval(func))) { \
1273 : spcp->val = *spcp->valp; \
1274 : spcp->mylevel = SLC_VARIABLE|flags; \
1275 : } else { \
1276 : spcp->val = 0; \
1277 : spcp->mylevel = SLC_DEFAULT; \
1278 : } \
1279 : }
1280 :
1281 0 : initfunc (SLC_SYNCH, 0);
1282 : /* No BRK */
1283 0 : initfunc (SLC_AO, 0);
1284 0 : initfunc (SLC_AYT, 0);
1285 : /* No EOR */
1286 0 : initfunc (SLC_ABORT, SLC_FLUSHIN | SLC_FLUSHOUT);
1287 0 : initfunc (SLC_EOF, 0);
1288 : #ifndef SYSV_TERMIO
1289 0 : initfunc (SLC_SUSP, SLC_FLUSHIN);
1290 : #endif
1291 0 : initfunc (SLC_EC, 0);
1292 0 : initfunc (SLC_EL, 0);
1293 : #ifndef SYSV_TERMIO
1294 0 : initfunc (SLC_EW, 0);
1295 0 : initfunc (SLC_RP, 0);
1296 0 : initfunc (SLC_LNEXT, 0);
1297 : #endif
1298 0 : initfunc (SLC_XON, 0);
1299 0 : initfunc (SLC_XOFF, 0);
1300 : #ifdef SYSV_TERMIO
1301 : spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
1302 : spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
1303 : #endif
1304 0 : initfunc (SLC_FORW1, 0);
1305 : #ifdef USE_TERMIO
1306 0 : initfunc (SLC_FORW2, 0);
1307 : /* No FORW2 */
1308 : #endif
1309 :
1310 0 : initfunc (SLC_IP, SLC_FLUSHIN | SLC_FLUSHOUT);
1311 : #undef initfunc
1312 :
1313 0 : if (slc_mode == SLC_EXPORT)
1314 0 : slc_export ();
1315 : else
1316 0 : slc_import (1);
1317 :
1318 0 : }
1319 :
1320 : void
1321 0 : slcstate (void)
1322 : {
1323 0 : printf ("Special characters are %s values\n",
1324 0 : slc_mode == SLC_IMPORT ? "remote default" :
1325 0 : slc_mode == SLC_EXPORT ? "local" : "remote");
1326 0 : }
1327 :
1328 : void
1329 0 : slc_mode_export (void)
1330 : {
1331 0 : slc_mode = SLC_EXPORT;
1332 0 : if (my_state_is_will (TELOPT_LINEMODE))
1333 0 : slc_export ();
1334 0 : }
1335 :
1336 : void
1337 0 : slc_mode_import (int def)
1338 : {
1339 0 : slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
1340 0 : if (my_state_is_will (TELOPT_LINEMODE))
1341 0 : slc_import (def);
1342 0 : }
1343 :
1344 : unsigned char slc_import_val[] = {
1345 : IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1346 : };
1347 : unsigned char slc_import_def[] = {
1348 : IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1349 : };
1350 :
1351 : void
1352 0 : slc_import (int def)
1353 : {
1354 0 : if (NETROOM () > (int) sizeof (slc_import_val))
1355 : {
1356 0 : if (def)
1357 : {
1358 0 : ring_supply_data (&netoring, slc_import_def,
1359 : sizeof (slc_import_def));
1360 0 : printsub ('>', &slc_import_def[2], sizeof (slc_import_def) - 2);
1361 : }
1362 : else
1363 : {
1364 0 : ring_supply_data (&netoring, slc_import_val,
1365 : sizeof (slc_import_val));
1366 0 : printsub ('>', &slc_import_val[2], sizeof (slc_import_val) - 2);
1367 : }
1368 : }
1369 : /*@*/
1370 : else
1371 0 : printf ("slc_import: not enough room\n");
1372 0 : }
1373 :
1374 : void
1375 0 : slc_export (void)
1376 : {
1377 : register struct spc *spcp;
1378 :
1379 0 : TerminalDefaultChars ();
1380 :
1381 0 : slc_start_reply ();
1382 0 : for (spcp = &spc_data[1]; spcp < &spc_data[NSLC + 1]; spcp++)
1383 : {
1384 0 : if (spcp->mylevel != SLC_NOSUPPORT)
1385 : {
1386 0 : if (spcp->val == (cc_t) (_POSIX_VDISABLE))
1387 0 : spcp->flags = SLC_NOSUPPORT;
1388 : else
1389 0 : spcp->flags = spcp->mylevel;
1390 0 : if (spcp->valp)
1391 0 : spcp->val = *spcp->valp;
1392 0 : slc_add_reply (spcp - spc_data, spcp->flags, spcp->val);
1393 : }
1394 : }
1395 0 : slc_end_reply ();
1396 0 : slc_update ();
1397 0 : setconnmode (1); /* Make sure the character values are set */
1398 0 : }
1399 :
1400 : void
1401 0 : slc (register unsigned char *cp, int len)
1402 : {
1403 : register struct spc *spcp;
1404 : register int func, level;
1405 :
1406 0 : slc_start_reply ();
1407 :
1408 0 : for (; len >= 3; len -= 3, cp += 3)
1409 : {
1410 :
1411 0 : func = cp[SLC_FUNC];
1412 :
1413 0 : if (func == 0)
1414 : {
1415 : /*
1416 : * Client side: always ignore 0 function.
1417 : */
1418 0 : continue;
1419 : }
1420 0 : if (func > NSLC)
1421 : {
1422 0 : if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1423 0 : slc_add_reply (func, SLC_NOSUPPORT, 0);
1424 0 : continue;
1425 : }
1426 :
1427 0 : spcp = &spc_data[func];
1428 :
1429 0 : level = cp[SLC_FLAGS] & (SLC_LEVELBITS | SLC_ACK);
1430 :
1431 0 : if ((cp[SLC_VALUE] == (unsigned char) spcp->val) &&
1432 0 : ((level & SLC_LEVELBITS) == (spcp->flags & SLC_LEVELBITS)))
1433 : {
1434 0 : continue;
1435 : }
1436 :
1437 0 : if (level == (SLC_DEFAULT | SLC_ACK))
1438 : {
1439 : /*
1440 : * This is an error condition, the SLC_ACK
1441 : * bit should never be set for the SLC_DEFAULT
1442 : * level. Our best guess to recover is to
1443 : * ignore the SLC_ACK bit.
1444 : */
1445 0 : cp[SLC_FLAGS] &= ~SLC_ACK;
1446 : }
1447 :
1448 0 : if (level == ((spcp->flags & SLC_LEVELBITS) | SLC_ACK))
1449 : {
1450 0 : spcp->val = (cc_t) cp[SLC_VALUE];
1451 0 : spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
1452 0 : continue;
1453 : }
1454 :
1455 0 : level &= ~SLC_ACK;
1456 :
1457 0 : if (level <= (spcp->mylevel & SLC_LEVELBITS))
1458 : {
1459 0 : spcp->flags = cp[SLC_FLAGS] | SLC_ACK;
1460 0 : spcp->val = (cc_t) cp[SLC_VALUE];
1461 : }
1462 0 : if (level == SLC_DEFAULT)
1463 : {
1464 0 : if ((spcp->mylevel & SLC_LEVELBITS) != SLC_DEFAULT)
1465 0 : spcp->flags = spcp->mylevel;
1466 : else
1467 0 : spcp->flags = SLC_NOSUPPORT;
1468 : }
1469 0 : slc_add_reply (func, spcp->flags, spcp->val);
1470 : }
1471 0 : slc_end_reply ();
1472 0 : if (slc_update ())
1473 0 : setconnmode (1); /* set the new character values */
1474 0 : }
1475 :
1476 : void
1477 0 : slc_check (void)
1478 : {
1479 : register struct spc *spcp;
1480 :
1481 0 : slc_start_reply ();
1482 0 : for (spcp = &spc_data[1]; spcp < &spc_data[NSLC + 1]; spcp++)
1483 : {
1484 0 : if (spcp->valp && spcp->val != *spcp->valp)
1485 : {
1486 0 : spcp->val = *spcp->valp;
1487 0 : if (spcp->val == (cc_t) (_POSIX_VDISABLE))
1488 0 : spcp->flags = SLC_NOSUPPORT;
1489 : else
1490 0 : spcp->flags = spcp->mylevel;
1491 0 : slc_add_reply (spcp - spc_data, spcp->flags, spcp->val);
1492 : }
1493 : }
1494 0 : slc_end_reply ();
1495 0 : setconnmode (1);
1496 0 : }
1497 :
1498 :
1499 : unsigned char slc_reply[128];
1500 : unsigned char *slc_replyp;
1501 :
1502 : void
1503 0 : slc_start_reply (void)
1504 : {
1505 0 : slc_replyp = slc_reply;
1506 0 : *slc_replyp++ = IAC;
1507 0 : *slc_replyp++ = SB;
1508 0 : *slc_replyp++ = TELOPT_LINEMODE;
1509 0 : *slc_replyp++ = LM_SLC;
1510 0 : }
1511 :
1512 : void
1513 0 : slc_add_reply (unsigned char func, unsigned char flags, cc_t value)
1514 : {
1515 0 : if ((*slc_replyp++ = func) == IAC)
1516 0 : *slc_replyp++ = IAC;
1517 0 : if ((*slc_replyp++ = flags) == IAC)
1518 0 : *slc_replyp++ = IAC;
1519 0 : if ((*slc_replyp++ = (unsigned char) value) == IAC)
1520 0 : *slc_replyp++ = IAC;
1521 0 : }
1522 :
1523 : void
1524 0 : slc_end_reply (void)
1525 : {
1526 : register int len;
1527 :
1528 0 : *slc_replyp++ = IAC;
1529 0 : *slc_replyp++ = SE;
1530 0 : len = slc_replyp - slc_reply;
1531 0 : if (len <= 6)
1532 0 : return;
1533 0 : if (NETROOM () > len)
1534 : {
1535 0 : ring_supply_data (&netoring, slc_reply, slc_replyp - slc_reply);
1536 0 : printsub ('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1537 : }
1538 : /*@*/
1539 : else
1540 0 : printf ("slc_end_reply: not enough room\n");
1541 : }
1542 :
1543 : int
1544 0 : slc_update (void)
1545 : {
1546 : register struct spc *spcp;
1547 0 : int need_update = 0;
1548 :
1549 0 : for (spcp = &spc_data[1]; spcp < &spc_data[NSLC + 1]; spcp++)
1550 : {
1551 0 : if (!(spcp->flags & SLC_ACK))
1552 0 : continue;
1553 0 : spcp->flags &= ~SLC_ACK;
1554 0 : if (spcp->valp && (*spcp->valp != spcp->val))
1555 : {
1556 0 : *spcp->valp = spcp->val;
1557 0 : need_update = 1;
1558 : }
1559 : }
1560 0 : return (need_update);
1561 : }
1562 :
1563 : #ifdef OLD_ENVIRON
1564 : # ifdef ENV_HACK
1565 : /*
1566 : * Earlier version of telnet/telnetd from the BSD code had
1567 : * the definitions of VALUE and VAR reversed. To ensure
1568 : * maximum interoperability, we assume that the server is
1569 : * an older BSD server, until proven otherwise. The newer
1570 : * BSD servers should be able to handle either definition,
1571 : * so it is better to use the wrong values if we don't
1572 : * know what type of server it is.
1573 : */
1574 : int env_auto = 1;
1575 : int old_env_var = OLD_ENV_VAR;
1576 : int old_env_value = OLD_ENV_VALUE;
1577 : # else
1578 : # define old_env_var OLD_ENV_VAR
1579 : # define old_env_value OLD_ENV_VALUE
1580 : # endif
1581 : #endif
1582 :
1583 : void
1584 0 : env_opt (register unsigned char *buf, register int len)
1585 : {
1586 0 : register unsigned char *ep = 0, *epc = 0;
1587 : register int i;
1588 :
1589 0 : switch (buf[0] & 0xff)
1590 : {
1591 : case TELQUAL_SEND:
1592 0 : env_opt_start ();
1593 0 : if (len == 1)
1594 : {
1595 0 : env_opt_add (NULL);
1596 : }
1597 : else
1598 0 : for (i = 1; i < len; i++)
1599 : {
1600 0 : switch (buf[i] & 0xff)
1601 : {
1602 : #ifdef OLD_ENVIRON
1603 : case OLD_ENV_VAR:
1604 : # ifdef ENV_HACK
1605 : if (telopt_environ == TELOPT_OLD_ENVIRON && env_auto)
1606 : {
1607 : /* Server has the same definitions */
1608 : old_env_var = OLD_ENV_VAR;
1609 : old_env_value = OLD_ENV_VALUE;
1610 : }
1611 : /* FALL THROUGH */
1612 : # endif
1613 : case OLD_ENV_VALUE:
1614 : /*
1615 : * Although OLD_ENV_VALUE is not legal, we will
1616 : * still recognize it, just in case it is an
1617 : * old server that has VAR & VALUE mixed up...
1618 : */
1619 : /* FALL THROUGH */
1620 : #else
1621 : case NEW_ENV_VAR:
1622 : #endif
1623 : case ENV_USERVAR:
1624 0 : if (ep)
1625 : {
1626 0 : *epc = 0;
1627 0 : env_opt_add (ep);
1628 : }
1629 0 : ep = epc = &buf[i + 1];
1630 0 : break;
1631 : case ENV_ESC:
1632 0 : i++;
1633 : /*FALL THROUGH */
1634 : default:
1635 0 : if (epc)
1636 0 : *epc++ = buf[i];
1637 0 : break;
1638 : }
1639 : }
1640 0 : if (ep)
1641 : {
1642 0 : *epc = 0;
1643 0 : env_opt_add (ep);
1644 : }
1645 0 : env_opt_end (1);
1646 0 : break;
1647 :
1648 : case TELQUAL_IS:
1649 : case TELQUAL_INFO:
1650 : /* Ignore for now. We shouldn't get it anyway. */
1651 0 : break;
1652 :
1653 : default:
1654 0 : break;
1655 : }
1656 0 : }
1657 :
1658 : #define OPT_REPLY_SIZE 256
1659 : unsigned char *opt_reply;
1660 : unsigned char *opt_replyp;
1661 : unsigned char *opt_replyend;
1662 :
1663 : void
1664 0 : env_opt_start (void)
1665 : {
1666 0 : if (opt_reply)
1667 0 : opt_reply = (unsigned char *) realloc (opt_reply, OPT_REPLY_SIZE);
1668 : else
1669 0 : opt_reply = (unsigned char *) malloc (OPT_REPLY_SIZE);
1670 0 : if (opt_reply == NULL)
1671 : {
1672 0 : /*@*/ printf ("env_opt_start: malloc()/realloc() failed!!!\n");
1673 0 : opt_reply = opt_replyp = opt_replyend = NULL;
1674 0 : return;
1675 : }
1676 0 : opt_replyp = opt_reply;
1677 0 : opt_replyend = opt_reply + OPT_REPLY_SIZE;
1678 0 : *opt_replyp++ = IAC;
1679 0 : *opt_replyp++ = SB;
1680 0 : *opt_replyp++ = telopt_environ;
1681 0 : *opt_replyp++ = TELQUAL_IS;
1682 : }
1683 :
1684 : void
1685 0 : env_opt_start_info (void)
1686 : {
1687 0 : env_opt_start ();
1688 0 : if (opt_replyp)
1689 0 : opt_replyp[-1] = TELQUAL_INFO;
1690 0 : }
1691 :
1692 : void
1693 0 : env_opt_add (register unsigned char *ep)
1694 : {
1695 : register unsigned char *vp, c;
1696 :
1697 0 : if (opt_reply == NULL)
1698 0 : /*XXX*/ return;
1699 0 : /*XXX*/ if (ep == NULL || *ep == '\0')
1700 : {
1701 : /* Send user defined variables first. */
1702 0 : env_default (1, 0);
1703 0 : while ((ep = env_default (0, 0)))
1704 0 : env_opt_add (ep);
1705 :
1706 : /* Now add the list of well know variables. */
1707 0 : env_default (1, 1);
1708 0 : while ((ep = env_default (0, 1)))
1709 0 : env_opt_add (ep);
1710 0 : return;
1711 : }
1712 0 : vp = env_getvalue ((char *)ep);
1713 0 : if (opt_replyp + (vp ? strlen ((char *) vp) : 0) +
1714 0 : strlen ((char *) ep) + 6 > opt_replyend)
1715 : {
1716 : register int len;
1717 0 : opt_replyend += OPT_REPLY_SIZE;
1718 0 : len = opt_replyend - opt_reply;
1719 0 : opt_reply = (unsigned char *) realloc (opt_reply, len);
1720 0 : if (opt_reply == NULL)
1721 : {
1722 0 : /*@*/ printf ("env_opt_add: realloc() failed!!!\n");
1723 0 : opt_reply = opt_replyp = opt_replyend = NULL;
1724 0 : return;
1725 : }
1726 0 : opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
1727 0 : opt_replyend = opt_reply + len;
1728 : }
1729 0 : if (opt_welldefined ((char *) ep))
1730 : #ifdef OLD_ENVIRON
1731 : if (telopt_environ == TELOPT_OLD_ENVIRON)
1732 : *opt_replyp++ = old_env_var;
1733 : else
1734 : #endif
1735 0 : *opt_replyp++ = NEW_ENV_VAR;
1736 : else
1737 0 : *opt_replyp++ = ENV_USERVAR;
1738 : for (;;)
1739 : {
1740 0 : while ((c = *ep++))
1741 : {
1742 0 : switch (c & 0xff)
1743 : {
1744 : case IAC:
1745 0 : *opt_replyp++ = IAC;
1746 0 : break;
1747 : case NEW_ENV_VAR:
1748 : case NEW_ENV_VALUE:
1749 : case ENV_ESC:
1750 : case ENV_USERVAR:
1751 0 : *opt_replyp++ = ENV_ESC;
1752 0 : break;
1753 : }
1754 0 : *opt_replyp++ = c;
1755 : }
1756 0 : if ((ep = vp))
1757 : {
1758 : #ifdef OLD_ENVIRON
1759 : if (telopt_environ == TELOPT_OLD_ENVIRON)
1760 : *opt_replyp++ = old_env_value;
1761 : else
1762 : #endif
1763 0 : *opt_replyp++ = NEW_ENV_VALUE;
1764 0 : vp = NULL;
1765 : }
1766 : else
1767 0 : break;
1768 0 : }
1769 : }
1770 :
1771 : int
1772 186 : opt_welldefined (char *ep)
1773 : {
1774 369 : if ((strcmp (ep, "USER") == 0) ||
1775 363 : (strcmp (ep, "DISPLAY") == 0) ||
1776 360 : (strcmp (ep, "PRINTER") == 0) ||
1777 360 : (strcmp (ep, "SYSTEMTYPE") == 0) ||
1778 360 : (strcmp (ep, "JOB") == 0) || (strcmp (ep, "ACCT") == 0))
1779 6 : return (1);
1780 180 : return (0);
1781 : }
1782 :
1783 : void
1784 0 : env_opt_end (register int emptyok)
1785 : {
1786 : register int len;
1787 :
1788 0 : len = opt_replyp - opt_reply + 2;
1789 0 : if (emptyok || len > 6)
1790 : {
1791 0 : *opt_replyp++ = IAC;
1792 0 : *opt_replyp++ = SE;
1793 0 : if (NETROOM () > len)
1794 : {
1795 0 : ring_supply_data (&netoring, opt_reply, len);
1796 0 : printsub ('>', &opt_reply[2], len - 2);
1797 : }
1798 : /*@*/
1799 : else
1800 0 : printf ("slc_end_reply: not enough room\n");
1801 : }
1802 0 : if (opt_reply)
1803 : {
1804 0 : free (opt_reply);
1805 0 : opt_reply = opt_replyp = opt_replyend = NULL;
1806 : }
1807 0 : }
1808 :
1809 :
1810 :
1811 : int
1812 6 : telrcv (void)
1813 : {
1814 : register int c;
1815 : register int scc;
1816 : register unsigned char *sbp;
1817 : int count;
1818 6 : int returnValue = 0;
1819 :
1820 6 : scc = 0;
1821 6 : count = 0;
1822 87 : while (TTYROOM () > 2)
1823 : {
1824 81 : if (scc == 0)
1825 : {
1826 9 : if (count)
1827 : {
1828 3 : ring_consumed (&netiring, count);
1829 3 : returnValue = 1;
1830 3 : count = 0;
1831 : }
1832 9 : sbp = netiring.consume;
1833 9 : scc = ring_full_consecutive (&netiring);
1834 9 : if (scc == 0)
1835 : {
1836 : /* No more data coming in */
1837 6 : break;
1838 : }
1839 : }
1840 :
1841 75 : c = *sbp++ & 0xff, scc--;
1842 75 : count++;
1843 : #ifdef ENCRYPTION
1844 : if (decrypt_input)
1845 : c = (*decrypt_input) (c);
1846 : #endif /* ENCRYPTION */
1847 :
1848 75 : switch (telrcv_state)
1849 : {
1850 :
1851 : case TS_CR:
1852 0 : telrcv_state = TS_DATA;
1853 0 : if (c == '\0')
1854 : {
1855 0 : break; /* Ignore \0 after CR */
1856 : }
1857 0 : else if ((c == '\n') && my_want_state_is_dont (TELOPT_ECHO)
1858 0 : && !crmod)
1859 : {
1860 0 : TTYADD (c);
1861 0 : break;
1862 : }
1863 : /* Else, fall through */
1864 :
1865 : case TS_DATA:
1866 75 : if (c == IAC)
1867 : {
1868 0 : telrcv_state = TS_IAC;
1869 0 : break;
1870 : }
1871 : #if defined TN3270
1872 : if (In3270)
1873 : {
1874 : *Ifrontp++ = c;
1875 : while (scc > 0)
1876 : {
1877 : c = *sbp++ & 0377, scc--;
1878 : count++;
1879 : # ifdef ENCRYPTION
1880 : if (decrypt_input)
1881 : c = (*decrypt_input) (c);
1882 : # endif /* ENCRYPTION */
1883 : if (c == IAC)
1884 : {
1885 : telrcv_state = TS_IAC;
1886 : break;
1887 : }
1888 : *Ifrontp++ = c;
1889 : }
1890 : }
1891 : else
1892 : #endif /* defined(TN3270) */
1893 : /*
1894 : * The 'crmod' hack (see following) is needed
1895 : * since we can't * set CRMOD on output only.
1896 : * Machines like MULTICS like to send \r without
1897 : * \n; since we must turn off CRMOD to get proper
1898 : * input, the mapping is done here (sigh).
1899 : */
1900 75 : if ((c == '\r') && my_want_state_is_dont (TELOPT_BINARY))
1901 : {
1902 0 : if (scc > 0)
1903 : {
1904 0 : c = *sbp & 0xff;
1905 : #ifdef ENCRYPTION
1906 : if (decrypt_input)
1907 : c = (*decrypt_input) (c);
1908 : #endif /* ENCRYPTION */
1909 0 : if (c == 0)
1910 : {
1911 0 : sbp++, scc--;
1912 0 : count++;
1913 : /* a "true" CR */
1914 0 : TTYADD ('\r');
1915 : }
1916 0 : else if (my_want_state_is_dont (TELOPT_ECHO) && (c == '\n'))
1917 : {
1918 0 : sbp++, scc--;
1919 0 : count++;
1920 0 : TTYADD ('\n');
1921 : }
1922 : else
1923 : {
1924 : #ifdef ENCRYPTION
1925 : if (decrypt_input)
1926 : (*decrypt_input) (-1);
1927 : #endif /* ENCRYPTION */
1928 :
1929 0 : TTYADD ('\r');
1930 0 : if (crmod)
1931 : {
1932 0 : TTYADD ('\n');
1933 : }
1934 : }
1935 : }
1936 : else
1937 : {
1938 0 : telrcv_state = TS_CR;
1939 0 : TTYADD ('\r');
1940 0 : if (crmod)
1941 : {
1942 0 : TTYADD ('\n');
1943 : }
1944 : }
1945 : }
1946 : else
1947 : {
1948 75 : TTYADD (c);
1949 : }
1950 75 : continue;
1951 :
1952 : case TS_IAC:
1953 : process_iac:
1954 0 : switch (c)
1955 : {
1956 :
1957 : case WILL:
1958 0 : telrcv_state = TS_WILL;
1959 0 : continue;
1960 :
1961 : case WONT:
1962 0 : telrcv_state = TS_WONT;
1963 0 : continue;
1964 :
1965 : case DO:
1966 0 : telrcv_state = TS_DO;
1967 0 : continue;
1968 :
1969 : case DONT:
1970 0 : telrcv_state = TS_DONT;
1971 0 : continue;
1972 :
1973 : case DM:
1974 : /*
1975 : * We may have missed an urgent notification,
1976 : * so make sure we flush whatever is in the
1977 : * buffer currently.
1978 : */
1979 0 : printoption ("RCVD", IAC, DM);
1980 0 : SYNCHing = 1;
1981 0 : ttyflush (1);
1982 0 : SYNCHing = stilloob ();
1983 0 : settimer (gotDM);
1984 0 : break;
1985 :
1986 : case SB:
1987 0 : SB_CLEAR ();
1988 0 : telrcv_state = TS_SB;
1989 0 : continue;
1990 :
1991 : #if defined TN3270
1992 : case EOR:
1993 : if (In3270)
1994 : {
1995 : if (Ibackp == Ifrontp)
1996 : {
1997 : Ibackp = Ifrontp = Ibuf;
1998 : ISend = 0; /* should have been! */
1999 : }
2000 : else
2001 : {
2002 : Ibackp += DataFromNetwork (Ibackp, Ifrontp - Ibackp, 1);
2003 : ISend = 1;
2004 : }
2005 : }
2006 : printoption ("RCVD", IAC, EOR);
2007 : break;
2008 : #endif /* defined(TN3270) */
2009 :
2010 : case IAC:
2011 : #if !defined TN3270
2012 0 : TTYADD (IAC);
2013 : #else /* !defined(TN3270) */
2014 : if (In3270)
2015 : {
2016 : *Ifrontp++ = IAC;
2017 : }
2018 : else
2019 : {
2020 : TTYADD (IAC);
2021 : }
2022 : #endif /* !defined(TN3270) */
2023 0 : break;
2024 :
2025 : case NOP:
2026 : case GA:
2027 : default:
2028 0 : printoption ("RCVD", IAC, c);
2029 0 : break;
2030 : }
2031 0 : telrcv_state = TS_DATA;
2032 0 : continue;
2033 :
2034 : case TS_WILL:
2035 0 : printoption ("RCVD", WILL, c);
2036 0 : willoption (c);
2037 : SetIn3270 ();
2038 0 : telrcv_state = TS_DATA;
2039 0 : continue;
2040 :
2041 : case TS_WONT:
2042 0 : printoption ("RCVD", WONT, c);
2043 0 : wontoption (c);
2044 : SetIn3270 ();
2045 0 : telrcv_state = TS_DATA;
2046 0 : continue;
2047 :
2048 : case TS_DO:
2049 0 : printoption ("RCVD", DO, c);
2050 0 : dooption (c);
2051 : SetIn3270 ();
2052 0 : if (c == TELOPT_NAWS)
2053 : {
2054 0 : sendnaws ();
2055 : }
2056 0 : else if (c == TELOPT_LFLOW)
2057 : {
2058 0 : localflow = 1;
2059 0 : setcommandmode ();
2060 0 : setconnmode (0);
2061 : }
2062 0 : telrcv_state = TS_DATA;
2063 0 : continue;
2064 :
2065 : case TS_DONT:
2066 0 : printoption ("RCVD", DONT, c);
2067 0 : dontoption (c);
2068 0 : flushline = 1;
2069 0 : setconnmode (0); /* set new tty mode (maybe) */
2070 : SetIn3270 ();
2071 0 : telrcv_state = TS_DATA;
2072 0 : continue;
2073 :
2074 : case TS_SB:
2075 0 : if (c == IAC)
2076 : {
2077 0 : telrcv_state = TS_SE;
2078 : }
2079 : else
2080 : {
2081 0 : SB_ACCUM (c);
2082 : }
2083 0 : continue;
2084 :
2085 : case TS_SE:
2086 0 : if (c != SE)
2087 : {
2088 0 : if (c != IAC)
2089 : {
2090 : /*
2091 : * This is an error. We only expect to get
2092 : * "IAC IAC" or "IAC SE". Several things may
2093 : * have happend. An IAC was not doubled, the
2094 : * IAC SE was left off, or another option got
2095 : * inserted into the suboption are all possibilities.
2096 : * If we assume that the IAC was not doubled,
2097 : * and really the IAC SE was left off, we could
2098 : * get into an infinate loop here. So, instead,
2099 : * we terminate the suboption, and process the
2100 : * partial suboption if we can.
2101 : */
2102 0 : SB_ACCUM (IAC);
2103 0 : SB_ACCUM (c);
2104 0 : subpointer -= 2;
2105 0 : SB_TERM ();
2106 :
2107 0 : printoption ("In SUBOPTION processing, RCVD", IAC, c);
2108 0 : suboption (); /* handle sub-option */
2109 : SetIn3270 ();
2110 0 : telrcv_state = TS_IAC;
2111 0 : goto process_iac;
2112 : }
2113 0 : SB_ACCUM (c);
2114 0 : telrcv_state = TS_SB;
2115 : }
2116 : else
2117 : {
2118 0 : SB_ACCUM (IAC);
2119 0 : SB_ACCUM (SE);
2120 0 : subpointer -= 2;
2121 0 : SB_TERM ();
2122 0 : suboption (); /* handle sub-option */
2123 : SetIn3270 ();
2124 0 : telrcv_state = TS_DATA;
2125 : }
2126 : }
2127 : }
2128 6 : if (count)
2129 0 : ring_consumed (&netiring, count);
2130 6 : return returnValue || count;
2131 : }
2132 :
2133 : static int bol = 1, local = 0;
2134 :
2135 : int
2136 0 : rlogin_susp (void)
2137 : {
2138 0 : if (local)
2139 : {
2140 0 : local = 0;
2141 0 : bol = 1;
2142 0 : command (0, "z\n", 2);
2143 0 : return (1);
2144 : }
2145 0 : return (0);
2146 : }
2147 :
2148 : static int
2149 0 : telsnd (void)
2150 : {
2151 : int tcc;
2152 : int count;
2153 0 : int returnValue = 0;
2154 : unsigned char *tbp;
2155 :
2156 0 : tcc = 0;
2157 0 : count = 0;
2158 0 : while (NETROOM () > 2)
2159 : {
2160 : register int sc;
2161 : register int c;
2162 :
2163 0 : if (tcc == 0)
2164 : {
2165 0 : if (count)
2166 : {
2167 0 : ring_consumed (&ttyiring, count);
2168 0 : returnValue = 1;
2169 0 : count = 0;
2170 : }
2171 0 : tbp = ttyiring.consume;
2172 0 : tcc = ring_full_consecutive (&ttyiring);
2173 0 : if (tcc == 0)
2174 : {
2175 0 : break;
2176 : }
2177 : }
2178 0 : c = *tbp++ & 0xff, sc = strip (c), tcc--;
2179 0 : count++;
2180 0 : if (rlogin != _POSIX_VDISABLE)
2181 : {
2182 0 : if (bol)
2183 : {
2184 0 : bol = 0;
2185 0 : if (sc == rlogin)
2186 : {
2187 0 : local = 1;
2188 0 : continue;
2189 : }
2190 : }
2191 0 : else if (local)
2192 : {
2193 0 : local = 0;
2194 0 : if (sc == '.' || c == termEofChar)
2195 : {
2196 0 : bol = 1;
2197 0 : command (0, "close\n", 6);
2198 0 : continue;
2199 : }
2200 0 : if (sc == termSuspChar)
2201 : {
2202 0 : bol = 1;
2203 0 : command (0, "z\n", 2);
2204 0 : continue;
2205 : }
2206 0 : if (sc == escape)
2207 : {
2208 0 : command (0, (char *) tbp, tcc);
2209 0 : bol = 1;
2210 0 : count += tcc;
2211 0 : tcc = 0;
2212 0 : flushline = 1;
2213 0 : break;
2214 : }
2215 0 : if (sc != rlogin)
2216 : {
2217 0 : ++tcc;
2218 0 : --tbp;
2219 0 : --count;
2220 0 : c = sc = rlogin;
2221 : }
2222 : }
2223 0 : if ((sc == '\n') || (sc == '\r'))
2224 0 : bol = 1;
2225 : }
2226 0 : else if (sc == escape)
2227 : {
2228 : /*
2229 : * Double escape is a pass through of a single escape character.
2230 : */
2231 0 : if (tcc && strip (*tbp) == escape)
2232 : {
2233 0 : tbp++;
2234 0 : tcc--;
2235 0 : count++;
2236 0 : bol = 0;
2237 : }
2238 : else
2239 : {
2240 0 : command (0, (char *) tbp, tcc);
2241 0 : bol = 1;
2242 0 : count += tcc;
2243 0 : tcc = 0;
2244 0 : flushline = 1;
2245 0 : break;
2246 : }
2247 : }
2248 : else
2249 0 : bol = 0;
2250 : #ifdef KLUDGELINEMODE
2251 0 : if (kludgelinemode && (globalmode & MODE_EDIT) && (sc == echoc))
2252 : {
2253 0 : if (tcc > 0 && strip (*tbp) == echoc)
2254 : {
2255 0 : tcc--;
2256 0 : tbp++;
2257 0 : count++;
2258 : }
2259 : else
2260 : {
2261 0 : dontlecho = !dontlecho;
2262 0 : settimer (echotoggle);
2263 0 : setconnmode (0);
2264 0 : flushline = 1;
2265 0 : break;
2266 : }
2267 : }
2268 : #endif
2269 0 : if (MODE_LOCAL_CHARS (globalmode))
2270 : {
2271 0 : if (TerminalSpecialChars (sc) == 0)
2272 : {
2273 0 : bol = 1;
2274 0 : break;
2275 : }
2276 : }
2277 0 : if (my_want_state_is_wont (TELOPT_BINARY))
2278 : {
2279 0 : switch (c)
2280 : {
2281 : case '\n':
2282 : /*
2283 : * If we are in CRMOD mode (\r ==> \n)
2284 : * on our local machine, then probably
2285 : * a newline (unix) is CRLF (TELNET).
2286 : */
2287 0 : if (MODE_LOCAL_CHARS (globalmode))
2288 : {
2289 0 : NETADD ('\r');
2290 : }
2291 0 : NETADD ('\n');
2292 0 : bol = flushline = 1;
2293 0 : break;
2294 : case '\r':
2295 0 : if (!crlf)
2296 : {
2297 0 : NET2ADD ('\r', '\0');
2298 : }
2299 : else
2300 : {
2301 0 : NET2ADD ('\r', '\n');
2302 : }
2303 0 : bol = flushline = 1;
2304 0 : break;
2305 : case IAC:
2306 0 : NET2ADD (IAC, IAC);
2307 0 : break;
2308 : default:
2309 0 : NETADD (c);
2310 0 : break;
2311 : }
2312 : }
2313 0 : else if (c == IAC)
2314 : {
2315 0 : NET2ADD (IAC, IAC);
2316 : }
2317 : else
2318 : {
2319 0 : NETADD (c);
2320 : }
2321 : }
2322 0 : if (count)
2323 0 : ring_consumed (&ttyiring, count);
2324 0 : return returnValue || count; /* Non-zero if we did anything */
2325 : }
2326 :
2327 : /*
2328 : * Scheduler()
2329 : *
2330 : * Try to do something.
2331 : *
2332 : * If we do something useful, return 1; else return 0.
2333 : *
2334 : */
2335 :
2336 :
2337 : /* block; should we block in the select ? */
2338 : int
2339 9 : Scheduler (int block)
2340 : {
2341 : /* One wants to be a bit careful about setting returnValue
2342 : * to one, since a one implies we did some useful work,
2343 : * and therefore probably won't be called to block next
2344 : * time (TN3270 mode only).
2345 : */
2346 : int returnValue;
2347 : int netin, netout, netex, ttyin, ttyout;
2348 :
2349 : /* Decide which rings should be processed */
2350 :
2351 9 : netout = ring_full_count (&netoring) &&
2352 0 : (flushline || (my_want_state_is_wont (TELOPT_LINEMODE)
2353 : #ifdef KLUDGELINEMODE
2354 0 : && (!kludgelinemode || my_want_state_is_do (TELOPT_SGA))
2355 : #endif
2356 0 : ) || my_want_state_is_will (TELOPT_BINARY));
2357 9 : ttyout = ring_full_count (&ttyoring);
2358 :
2359 : #if defined TN3270
2360 : ttyin = ring_empty_count (&ttyiring) && (shell_active == 0);
2361 : #else /* defined(TN3270) */
2362 9 : ttyin = ring_empty_count (&ttyiring);
2363 : #endif /* defined(TN3270) */
2364 :
2365 : #if defined TN3270
2366 : netin = ring_empty_count (&netiring);
2367 : #else /* !defined(TN3270) */
2368 9 : netin = !ISend && ring_empty_count (&netiring);
2369 : #endif /* !defined(TN3270) */
2370 :
2371 9 : netex = !SYNCHing;
2372 :
2373 : /* If we have seen a signal recently, reset things */
2374 : #if defined TN3270 && (defined unix || defined __unix || defined __unix__)
2375 : if (HaveInput)
2376 : {
2377 : HaveInput = 0;
2378 : signal (SIGIO, inputAvailable);
2379 : }
2380 : #endif /* TN3270 && (unix || __unix || __unix__) */
2381 :
2382 : /* Call to system code to process rings */
2383 :
2384 9 : returnValue = process_rings (netin, netout, netex, ttyin, ttyout, !block);
2385 :
2386 : /* Now, look at the input rings, looking for work to do. */
2387 :
2388 9 : if (ring_full_count (&ttyiring))
2389 : {
2390 : #if defined TN3270
2391 : if (In3270)
2392 : {
2393 : int c;
2394 :
2395 : c = DataFromTerminal (ttyiring.consume,
2396 : ring_full_consecutive (&ttyiring));
2397 : if (c)
2398 : {
2399 : returnValue = 1;
2400 : ring_consumed (&ttyiring, c);
2401 : }
2402 : }
2403 : else
2404 : {
2405 : #endif /* defined(TN3270) */
2406 0 : returnValue |= telsnd ();
2407 : #if defined TN3270
2408 : }
2409 : #endif /* defined(TN3270) */
2410 : }
2411 :
2412 9 : if (ring_full_count (&netiring))
2413 : {
2414 : #if !defined TN3270
2415 3 : returnValue |= telrcv ();
2416 : #else /* !defined(TN3270) */
2417 : returnValue = Push3270 ();
2418 : #endif /* !defined(TN3270) */
2419 : }
2420 9 : return returnValue;
2421 : }
2422 :
2423 : /*
2424 : * Select from tty and network...
2425 : */
2426 : void
2427 3 : telnet (char *user)
2428 : {
2429 3 : sys_telnet_init ();
2430 :
2431 : #if defined AUTHENTICATION || defined ENCRYPTION
2432 : {
2433 : static char *local_host = 0;
2434 :
2435 : if (!local_host)
2436 : local_host = localhost ();
2437 :
2438 : auth_encrypt_init (local_host, hostname, NULL, "TELNET", 0);
2439 : auth_encrypt_user (user);
2440 : }
2441 : #else /* !defined(AUTHENTICATION) && !defined(ENCRYPTION) */
2442 : (void) user;
2443 : #endif
2444 : #if !defined TN3270
2445 3 : if (telnetport)
2446 : {
2447 : # if defined AUTHENTICATION
2448 : if (autologin)
2449 : send_will (TELOPT_AUTHENTICATION, 1);
2450 : # endif
2451 : # ifdef ENCRYPTION
2452 : send_do (TELOPT_ENCRYPT, 1);
2453 : send_will (TELOPT_ENCRYPT, 1);
2454 : # endif /* ENCRYPTION */
2455 0 : send_do (TELOPT_SGA, 1);
2456 0 : send_will (TELOPT_TTYPE, 1);
2457 0 : send_will (TELOPT_NAWS, 1);
2458 0 : send_will (TELOPT_TSPEED, 1);
2459 0 : send_will (TELOPT_LFLOW, 1);
2460 0 : send_will (TELOPT_LINEMODE, 1);
2461 0 : send_will (TELOPT_NEW_ENVIRON, 1);
2462 0 : send_do (TELOPT_STATUS, 1);
2463 0 : if (env_getvalue ("DISPLAY"))
2464 0 : send_will (TELOPT_XDISPLOC, 1);
2465 0 : if (eight)
2466 0 : tel_enter_binary (eight);
2467 : }
2468 : #endif /* !defined(TN3270) */
2469 :
2470 : #if !defined TN3270
2471 : for (;;)
2472 : {
2473 : int schedValue;
2474 :
2475 12 : while ((schedValue = Scheduler (0)) != 0)
2476 : {
2477 3 : if (schedValue == -1)
2478 : {
2479 3 : setcommandmode ();
2480 3 : return;
2481 : }
2482 : }
2483 :
2484 3 : if (Scheduler (1) == -1)
2485 : {
2486 0 : setcommandmode ();
2487 0 : return;
2488 : }
2489 3 : }
2490 : #else /* !defined(TN3270) */
2491 : for (;;)
2492 : {
2493 : int schedValue;
2494 :
2495 : while (!In3270 && !shell_active)
2496 : {
2497 : if (Scheduler (1) == -1)
2498 : {
2499 : setcommandmode ();
2500 : return;
2501 : }
2502 : }
2503 :
2504 : while ((schedValue = Scheduler (0)) != 0)
2505 : {
2506 : if (schedValue == -1)
2507 : {
2508 : setcommandmode ();
2509 : return;
2510 : }
2511 : }
2512 : /* If there is data waiting to go out to terminal, don't
2513 : * schedule any more data for the terminal.
2514 : */
2515 : if (ring_full_count (&ttyoring))
2516 : {
2517 : schedValue = 1;
2518 : }
2519 : else
2520 : {
2521 : if (shell_active)
2522 : {
2523 : if (shell_continue () == 0)
2524 : {
2525 : ConnectScreen ();
2526 : }
2527 : }
2528 : else if (In3270)
2529 : {
2530 : schedValue = DoTerminalOutput ();
2531 : }
2532 : }
2533 : if (schedValue && (shell_active == 0))
2534 : {
2535 : if (Scheduler (1) == -1)
2536 : {
2537 : setcommandmode ();
2538 : return;
2539 : }
2540 : }
2541 : }
2542 : #endif /* !defined(TN3270) */
2543 : }
2544 :
2545 : #if 0 /* XXX - this not being in is a bug */
2546 : /*
2547 : * nextitem()
2548 : *
2549 : * Return the address of the next "item" in the TELNET data
2550 : * stream. This will be the address of the next character if
2551 : * the current address is a user data character, or it will
2552 : * be the address of the character following the TELNET command
2553 : * if the current address is a TELNET IAC ("I Am a Command")
2554 : * character.
2555 : */
2556 :
2557 : static char *
2558 : nextitem (char *current)
2559 : {
2560 : if ((*current & 0xff) != IAC)
2561 : {
2562 : return current + 1;
2563 : }
2564 : switch (*(current + 1) & 0xff)
2565 : {
2566 : case DO:
2567 : case DONT:
2568 : case WILL:
2569 : case WONT:
2570 : return current + 3;
2571 : case SB: /* loop forever looking for the SE */
2572 : {
2573 : register char *look = current + 2;
2574 :
2575 : for (;;)
2576 : {
2577 : if ((*look++ & 0xff) == IAC)
2578 : {
2579 : if ((*look++ & 0xff) == SE)
2580 : {
2581 : return look;
2582 : }
2583 : }
2584 : }
2585 : }
2586 : default:
2587 : return current + 2;
2588 : }
2589 : }
2590 : #endif /* 0 */
2591 :
2592 : /*
2593 : * netclear()
2594 : *
2595 : * We are about to do a TELNET SYNCH operation. Clear
2596 : * the path to the network.
2597 : *
2598 : * Things are a bit tricky since we may have sent the first
2599 : * byte or so of a previous TELNET command into the network.
2600 : * So, we have to scan the network buffer from the beginning
2601 : * until we are up to where we want to be.
2602 : *
2603 : * A side effect of what we do, just to keep things
2604 : * simple, is to clear the urgent data pointer. The principal
2605 : * caller should be setting the urgent data pointer AFTER calling
2606 : * us in any case.
2607 : */
2608 :
2609 : static void
2610 0 : netclear (void)
2611 : {
2612 : #if 0 /* XXX */
2613 : register char *thisitem, *next;
2614 : char *good;
2615 : # define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
2616 : ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2617 :
2618 : thisitem = netobuf;
2619 :
2620 : while ((next = nextitem (thisitem)) <= netobuf.send)
2621 : {
2622 : thisitem = next;
2623 : }
2624 :
2625 : /* Now, thisitem is first before/at boundary. */
2626 :
2627 : good = netobuf; /* where the good bytes go */
2628 :
2629 : while (netoring.add > thisitem)
2630 : {
2631 : if (wewant (thisitem))
2632 : {
2633 : int length;
2634 :
2635 : next = thisitem;
2636 : do
2637 : {
2638 : next = nextitem (next);
2639 : }
2640 : while (wewant (next) && (nfrontp > next));
2641 : length = next - thisitem;
2642 : memmove (good, thisitem, length);
2643 : good += length;
2644 : thisitem = next;
2645 : }
2646 : else
2647 : {
2648 : thisitem = nextitem (thisitem);
2649 : }
2650 : }
2651 :
2652 : #endif /* 0 */
2653 0 : }
2654 :
2655 : /*
2656 : * These routines add various telnet commands to the data stream.
2657 : */
2658 :
2659 : static void
2660 0 : doflush (void)
2661 : {
2662 0 : NET2ADD (IAC, DO);
2663 0 : NETADD (TELOPT_TM);
2664 0 : flushline = 1;
2665 0 : flushout = 1;
2666 0 : ttyflush (1); /* Flush/drop output */
2667 : /* do printoption AFTER flush, otherwise the output gets tossed... */
2668 0 : printoption ("SENT", DO, TELOPT_TM);
2669 0 : }
2670 :
2671 : void
2672 0 : xmitAO (void)
2673 : {
2674 0 : NET2ADD (IAC, AO);
2675 0 : printoption ("SENT", IAC, AO);
2676 0 : if (autoflush)
2677 : {
2678 0 : doflush ();
2679 : }
2680 0 : }
2681 :
2682 :
2683 : void
2684 0 : xmitEL (void)
2685 : {
2686 0 : NET2ADD (IAC, EL);
2687 0 : printoption ("SENT", IAC, EL);
2688 0 : }
2689 :
2690 : void
2691 0 : xmitEC (void)
2692 : {
2693 0 : NET2ADD (IAC, EC);
2694 0 : printoption ("SENT", IAC, EC);
2695 0 : }
2696 :
2697 :
2698 : int
2699 0 : dosynch (void)
2700 : {
2701 0 : netclear (); /* clear the path to the network */
2702 0 : NETADD (IAC);
2703 0 : setneturg ();
2704 0 : NETADD (DM);
2705 0 : printoption ("SENT", IAC, DM);
2706 0 : return 1;
2707 : }
2708 :
2709 : int want_status_response = 0;
2710 :
2711 : int
2712 0 : get_status (void)
2713 : {
2714 : unsigned char tmp[16];
2715 : register unsigned char *cp;
2716 :
2717 0 : if (my_want_state_is_dont (TELOPT_STATUS))
2718 : {
2719 0 : printf ("Remote side does not support STATUS option\n");
2720 0 : return 0;
2721 : }
2722 0 : cp = tmp;
2723 :
2724 0 : *cp++ = IAC;
2725 0 : *cp++ = SB;
2726 0 : *cp++ = TELOPT_STATUS;
2727 0 : *cp++ = TELQUAL_SEND;
2728 0 : *cp++ = IAC;
2729 0 : *cp++ = SE;
2730 0 : if (NETROOM () >= cp - tmp)
2731 : {
2732 0 : ring_supply_data (&netoring, tmp, cp - tmp);
2733 0 : printsub ('>', tmp + 2, cp - tmp - 2);
2734 : }
2735 0 : ++want_status_response;
2736 0 : return 1;
2737 : }
2738 :
2739 : void
2740 0 : intp (void)
2741 : {
2742 0 : NET2ADD (IAC, IP);
2743 0 : printoption ("SENT", IAC, IP);
2744 0 : flushline = 1;
2745 0 : if (autoflush)
2746 : {
2747 0 : doflush ();
2748 : }
2749 0 : if (autosynch)
2750 : {
2751 0 : dosynch ();
2752 : }
2753 0 : }
2754 :
2755 : void
2756 0 : sendbrk (void)
2757 : {
2758 0 : NET2ADD (IAC, BREAK);
2759 0 : printoption ("SENT", IAC, BREAK);
2760 0 : flushline = 1;
2761 0 : if (autoflush)
2762 : {
2763 0 : doflush ();
2764 : }
2765 0 : if (autosynch)
2766 : {
2767 0 : dosynch ();
2768 : }
2769 0 : }
2770 :
2771 : void
2772 0 : sendabort (void)
2773 : {
2774 0 : NET2ADD (IAC, ABORT);
2775 0 : printoption ("SENT", IAC, ABORT);
2776 0 : flushline = 1;
2777 0 : if (autoflush)
2778 : {
2779 0 : doflush ();
2780 : }
2781 0 : if (autosynch)
2782 : {
2783 0 : dosynch ();
2784 : }
2785 0 : }
2786 :
2787 : void
2788 0 : sendsusp (void)
2789 : {
2790 0 : NET2ADD (IAC, SUSP);
2791 0 : printoption ("SENT", IAC, SUSP);
2792 0 : flushline = 1;
2793 0 : if (autoflush)
2794 : {
2795 0 : doflush ();
2796 : }
2797 0 : if (autosynch)
2798 : {
2799 0 : dosynch ();
2800 : }
2801 0 : }
2802 :
2803 : void
2804 0 : sendeof (void)
2805 : {
2806 0 : NET2ADD (IAC, xEOF);
2807 0 : printoption ("SENT", IAC, xEOF);
2808 0 : }
2809 :
2810 : void
2811 0 : sendayt (void)
2812 : {
2813 0 : NET2ADD (IAC, AYT);
2814 0 : printoption ("SENT", IAC, AYT);
2815 0 : }
2816 :
2817 : /*
2818 : * Send a window size update to the remote system.
2819 : */
2820 :
2821 : void
2822 0 : sendnaws (void)
2823 : {
2824 : long rows, cols;
2825 : unsigned char tmp[16];
2826 : register unsigned char *cp;
2827 :
2828 0 : if (my_state_is_wont (TELOPT_NAWS))
2829 0 : return;
2830 :
2831 : #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2832 : if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2833 :
2834 0 : if (TerminalWindowSize (&rows, &cols) == 0)
2835 : { /* Failed */
2836 0 : return;
2837 : }
2838 :
2839 0 : cp = tmp;
2840 :
2841 0 : *cp++ = IAC;
2842 0 : *cp++ = SB;
2843 0 : *cp++ = TELOPT_NAWS;
2844 0 : PUTSHORT (cp, cols);
2845 0 : PUTSHORT (cp, rows);
2846 0 : *cp++ = IAC;
2847 0 : *cp++ = SE;
2848 0 : if (NETROOM () >= cp - tmp)
2849 : {
2850 0 : ring_supply_data (&netoring, tmp, cp - tmp);
2851 0 : printsub ('>', tmp + 2, cp - tmp - 2);
2852 : }
2853 : }
2854 :
2855 : void
2856 0 : tel_enter_binary (int rw)
2857 : {
2858 0 : if (rw & 1)
2859 0 : send_do (TELOPT_BINARY, 1);
2860 0 : if (rw & 2)
2861 0 : send_will (TELOPT_BINARY, 1);
2862 0 : }
2863 :
2864 : void
2865 0 : tel_leave_binary (int rw)
2866 : {
2867 0 : if (rw & 1)
2868 0 : send_dont (TELOPT_BINARY, 1);
2869 0 : if (rw & 2)
2870 0 : send_wont (TELOPT_BINARY, 1);
2871 0 : }
|