PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/telnet/telnet/utilities.c

https://bitbucket.org/evzijst/freebsd
C | 912 lines | 819 code | 42 blank | 51 comment | 135 complexity | f1d57d1861ef74790e1470d28dd53cd8 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, AGPL-1.0, LGPL-2.1, GPL-2.0, BSD-2-Clause, 0BSD, MPL-2.0-no-copyleft-exception
  1. /*
  2. * Copyright (c) 1988, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by the University of
  16. * California, Berkeley and its contributors.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #if 0
  34. #ifndef lint
  35. static const char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95";
  36. #endif
  37. #endif
  38. #include <sys/cdefs.h>
  39. __FBSDID("$FreeBSD$");
  40. #define TELOPTS
  41. #define TELCMDS
  42. #define SLC_NAMES
  43. #include <arpa/telnet.h>
  44. #include <sys/types.h>
  45. #include <sys/socket.h>
  46. #include <sys/time.h>
  47. #include <ctype.h>
  48. #include <stdlib.h>
  49. #include <unistd.h>
  50. #include "general.h"
  51. #include "fdset.h"
  52. #include "ring.h"
  53. #include "defines.h"
  54. #include "externs.h"
  55. #ifdef AUTHENTICATION
  56. #include <libtelnet/auth.h>
  57. #endif
  58. #ifdef ENCRYPTION
  59. #include <libtelnet/encrypt.h>
  60. #endif
  61. FILE *NetTrace = 0; /* Not in bss, since needs to stay */
  62. int prettydump;
  63. /*
  64. * upcase()
  65. *
  66. * Upcase (in place) the argument.
  67. */
  68. void
  69. upcase(char *argument)
  70. {
  71. int c;
  72. while ((c = *argument) != 0) {
  73. if (islower(c)) {
  74. *argument = toupper(c);
  75. }
  76. argument++;
  77. }
  78. }
  79. /*
  80. * SetSockOpt()
  81. *
  82. * Compensate for differences in 4.2 and 4.3 systems.
  83. */
  84. int
  85. SetSockOpt(int fd, int level, int option, int yesno)
  86. {
  87. return setsockopt(fd, level, option,
  88. (char *)&yesno, sizeof yesno);
  89. }
  90. /*
  91. * The following are routines used to print out debugging information.
  92. */
  93. unsigned char NetTraceFile[256] = "(standard output)";
  94. void
  95. SetNetTrace(char *file)
  96. {
  97. if (NetTrace && NetTrace != stdout)
  98. fclose(NetTrace);
  99. if (file && (strcmp(file, "-") != 0)) {
  100. NetTrace = fopen(file, "w");
  101. if (NetTrace) {
  102. strcpy((char *)NetTraceFile, file);
  103. return;
  104. }
  105. fprintf(stderr, "Cannot open %s.\n", file);
  106. }
  107. NetTrace = stdout;
  108. strcpy((char *)NetTraceFile, "(standard output)");
  109. }
  110. void
  111. Dump(char direction, unsigned char *buffer, int length)
  112. {
  113. # define BYTES_PER_LINE 32
  114. # define min(x,y) ((x<y)? x:y)
  115. unsigned char *pThis;
  116. int offset;
  117. offset = 0;
  118. while (length) {
  119. /* print one line */
  120. fprintf(NetTrace, "%c 0x%x\t", direction, offset);
  121. pThis = buffer;
  122. if (prettydump) {
  123. buffer = buffer + min(length, BYTES_PER_LINE/2);
  124. while (pThis < buffer) {
  125. fprintf(NetTrace, "%c%.2x",
  126. (((*pThis)&0xff) == 0xff) ? '*' : ' ',
  127. (*pThis)&0xff);
  128. pThis++;
  129. }
  130. length -= BYTES_PER_LINE/2;
  131. offset += BYTES_PER_LINE/2;
  132. } else {
  133. buffer = buffer + min(length, BYTES_PER_LINE);
  134. while (pThis < buffer) {
  135. fprintf(NetTrace, "%.2x", (*pThis)&0xff);
  136. pThis++;
  137. }
  138. length -= BYTES_PER_LINE;
  139. offset += BYTES_PER_LINE;
  140. }
  141. if (NetTrace == stdout) {
  142. fprintf(NetTrace, "\r\n");
  143. } else {
  144. fprintf(NetTrace, "\n");
  145. }
  146. if (length < 0) {
  147. fflush(NetTrace);
  148. return;
  149. }
  150. /* find next unique line */
  151. }
  152. fflush(NetTrace);
  153. }
  154. void
  155. printoption(const char *direction, int cmd, int option)
  156. {
  157. if (!showoptions)
  158. return;
  159. if (cmd == IAC) {
  160. if (TELCMD_OK(option))
  161. fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
  162. else
  163. fprintf(NetTrace, "%s IAC %d", direction, option);
  164. } else {
  165. const char *fmt;
  166. fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
  167. (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
  168. if (fmt) {
  169. fprintf(NetTrace, "%s %s ", direction, fmt);
  170. if (TELOPT_OK(option))
  171. fprintf(NetTrace, "%s", TELOPT(option));
  172. else if (option == TELOPT_EXOPL)
  173. fprintf(NetTrace, "EXOPL");
  174. else
  175. fprintf(NetTrace, "%d", option);
  176. } else
  177. fprintf(NetTrace, "%s %d %d", direction, cmd, option);
  178. }
  179. if (NetTrace == stdout) {
  180. fprintf(NetTrace, "\r\n");
  181. fflush(NetTrace);
  182. } else {
  183. fprintf(NetTrace, "\n");
  184. }
  185. return;
  186. }
  187. void
  188. optionstatus(void)
  189. {
  190. int i;
  191. extern char will_wont_resp[], do_dont_resp[];
  192. for (i = 0; i < 256; i++) {
  193. if (do_dont_resp[i]) {
  194. if (TELOPT_OK(i))
  195. printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
  196. else if (TELCMD_OK(i))
  197. printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
  198. else
  199. printf("resp DO_DONT %d: %d\n", i,
  200. do_dont_resp[i]);
  201. if (my_want_state_is_do(i)) {
  202. if (TELOPT_OK(i))
  203. printf("want DO %s\n", TELOPT(i));
  204. else if (TELCMD_OK(i))
  205. printf("want DO %s\n", TELCMD(i));
  206. else
  207. printf("want DO %d\n", i);
  208. } else {
  209. if (TELOPT_OK(i))
  210. printf("want DONT %s\n", TELOPT(i));
  211. else if (TELCMD_OK(i))
  212. printf("want DONT %s\n", TELCMD(i));
  213. else
  214. printf("want DONT %d\n", i);
  215. }
  216. } else {
  217. if (my_state_is_do(i)) {
  218. if (TELOPT_OK(i))
  219. printf(" DO %s\n", TELOPT(i));
  220. else if (TELCMD_OK(i))
  221. printf(" DO %s\n", TELCMD(i));
  222. else
  223. printf(" DO %d\n", i);
  224. }
  225. }
  226. if (will_wont_resp[i]) {
  227. if (TELOPT_OK(i))
  228. printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
  229. else if (TELCMD_OK(i))
  230. printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
  231. else
  232. printf("resp WILL_WONT %d: %d\n",
  233. i, will_wont_resp[i]);
  234. if (my_want_state_is_will(i)) {
  235. if (TELOPT_OK(i))
  236. printf("want WILL %s\n", TELOPT(i));
  237. else if (TELCMD_OK(i))
  238. printf("want WILL %s\n", TELCMD(i));
  239. else
  240. printf("want WILL %d\n", i);
  241. } else {
  242. if (TELOPT_OK(i))
  243. printf("want WONT %s\n", TELOPT(i));
  244. else if (TELCMD_OK(i))
  245. printf("want WONT %s\n", TELCMD(i));
  246. else
  247. printf("want WONT %d\n", i);
  248. }
  249. } else {
  250. if (my_state_is_will(i)) {
  251. if (TELOPT_OK(i))
  252. printf(" WILL %s\n", TELOPT(i));
  253. else if (TELCMD_OK(i))
  254. printf(" WILL %s\n", TELCMD(i));
  255. else
  256. printf(" WILL %d\n", i);
  257. }
  258. }
  259. }
  260. }
  261. void
  262. printsub(char direction, unsigned char *pointer, int length)
  263. {
  264. int i;
  265. #ifdef AUTHENTICATION
  266. char buf[512];
  267. #endif
  268. extern int want_status_response;
  269. if (showoptions || direction == 0 ||
  270. (want_status_response && (pointer[0] == TELOPT_STATUS))) {
  271. if (direction) {
  272. fprintf(NetTrace, "%s IAC SB ",
  273. (direction == '<')? "RCVD":"SENT");
  274. if (length >= 3) {
  275. int j;
  276. i = pointer[length-2];
  277. j = pointer[length-1];
  278. if (i != IAC || j != SE) {
  279. fprintf(NetTrace, "(terminated by ");
  280. if (TELOPT_OK(i))
  281. fprintf(NetTrace, "%s ", TELOPT(i));
  282. else if (TELCMD_OK(i))
  283. fprintf(NetTrace, "%s ", TELCMD(i));
  284. else
  285. fprintf(NetTrace, "%d ", i);
  286. if (TELOPT_OK(j))
  287. fprintf(NetTrace, "%s", TELOPT(j));
  288. else if (TELCMD_OK(j))
  289. fprintf(NetTrace, "%s", TELCMD(j));
  290. else
  291. fprintf(NetTrace, "%d", j);
  292. fprintf(NetTrace, ", not IAC SE!) ");
  293. }
  294. }
  295. length -= 2;
  296. }
  297. if (length < 1) {
  298. fprintf(NetTrace, "(Empty suboption??\?)");
  299. if (NetTrace == stdout)
  300. fflush(NetTrace);
  301. return;
  302. }
  303. switch (pointer[0]) {
  304. case TELOPT_TTYPE:
  305. fprintf(NetTrace, "TERMINAL-TYPE ");
  306. switch (pointer[1]) {
  307. case TELQUAL_IS:
  308. fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
  309. break;
  310. case TELQUAL_SEND:
  311. fprintf(NetTrace, "SEND");
  312. break;
  313. default:
  314. fprintf(NetTrace,
  315. "- unknown qualifier %d (0x%x).",
  316. pointer[1], pointer[1]);
  317. }
  318. break;
  319. case TELOPT_TSPEED:
  320. fprintf(NetTrace, "TERMINAL-SPEED");
  321. if (length < 2) {
  322. fprintf(NetTrace, " (empty suboption??\?)");
  323. break;
  324. }
  325. switch (pointer[1]) {
  326. case TELQUAL_IS:
  327. fprintf(NetTrace, " IS ");
  328. fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
  329. break;
  330. default:
  331. if (pointer[1] == 1)
  332. fprintf(NetTrace, " SEND");
  333. else
  334. fprintf(NetTrace, " %d (unknown)", pointer[1]);
  335. for (i = 2; i < length; i++)
  336. fprintf(NetTrace, " ?%d?", pointer[i]);
  337. break;
  338. }
  339. break;
  340. case TELOPT_LFLOW:
  341. fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
  342. if (length < 2) {
  343. fprintf(NetTrace, " (empty suboption??\?)");
  344. break;
  345. }
  346. switch (pointer[1]) {
  347. case LFLOW_OFF:
  348. fprintf(NetTrace, " OFF"); break;
  349. case LFLOW_ON:
  350. fprintf(NetTrace, " ON"); break;
  351. case LFLOW_RESTART_ANY:
  352. fprintf(NetTrace, " RESTART-ANY"); break;
  353. case LFLOW_RESTART_XON:
  354. fprintf(NetTrace, " RESTART-XON"); break;
  355. default:
  356. fprintf(NetTrace, " %d (unknown)", pointer[1]);
  357. }
  358. for (i = 2; i < length; i++)
  359. fprintf(NetTrace, " ?%d?", pointer[i]);
  360. break;
  361. case TELOPT_NAWS:
  362. fprintf(NetTrace, "NAWS");
  363. if (length < 2) {
  364. fprintf(NetTrace, " (empty suboption??\?)");
  365. break;
  366. }
  367. if (length == 2) {
  368. fprintf(NetTrace, " ?%d?", pointer[1]);
  369. break;
  370. }
  371. fprintf(NetTrace, " %d %d (%d)",
  372. pointer[1], pointer[2],
  373. (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
  374. if (length == 4) {
  375. fprintf(NetTrace, " ?%d?", pointer[3]);
  376. break;
  377. }
  378. fprintf(NetTrace, " %d %d (%d)",
  379. pointer[3], pointer[4],
  380. (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
  381. for (i = 5; i < length; i++)
  382. fprintf(NetTrace, " ?%d?", pointer[i]);
  383. break;
  384. #ifdef AUTHENTICATION
  385. case TELOPT_AUTHENTICATION:
  386. fprintf(NetTrace, "AUTHENTICATION");
  387. if (length < 2) {
  388. fprintf(NetTrace, " (empty suboption??\?)");
  389. break;
  390. }
  391. switch (pointer[1]) {
  392. case TELQUAL_REPLY:
  393. case TELQUAL_IS:
  394. fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
  395. "IS" : "REPLY");
  396. if (AUTHTYPE_NAME_OK(pointer[2]))
  397. fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
  398. else
  399. fprintf(NetTrace, "%d ", pointer[2]);
  400. if (length < 3) {
  401. fprintf(NetTrace, "(partial suboption??\?)");
  402. break;
  403. }
  404. fprintf(NetTrace, "%s|%s",
  405. ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
  406. "CLIENT" : "SERVER",
  407. ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
  408. "MUTUAL" : "ONE-WAY");
  409. auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
  410. fprintf(NetTrace, "%s", buf);
  411. break;
  412. case TELQUAL_SEND:
  413. i = 2;
  414. fprintf(NetTrace, " SEND ");
  415. while (i < length) {
  416. if (AUTHTYPE_NAME_OK(pointer[i]))
  417. fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
  418. else
  419. fprintf(NetTrace, "%d ", pointer[i]);
  420. if (++i >= length) {
  421. fprintf(NetTrace, "(partial suboption??\?)");
  422. break;
  423. }
  424. fprintf(NetTrace, "%s|%s ",
  425. ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
  426. "CLIENT" : "SERVER",
  427. ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
  428. "MUTUAL" : "ONE-WAY");
  429. ++i;
  430. }
  431. break;
  432. case TELQUAL_NAME:
  433. i = 2;
  434. fprintf(NetTrace, " NAME \"");
  435. while (i < length)
  436. putc(pointer[i++], NetTrace);
  437. putc('"', NetTrace);
  438. break;
  439. default:
  440. for (i = 2; i < length; i++)
  441. fprintf(NetTrace, " ?%d?", pointer[i]);
  442. break;
  443. }
  444. break;
  445. #endif
  446. #ifdef ENCRYPTION
  447. case TELOPT_ENCRYPT:
  448. fprintf(NetTrace, "ENCRYPT");
  449. if (length < 2) {
  450. fprintf(NetTrace, " (empty suboption??\?)");
  451. break;
  452. }
  453. switch (pointer[1]) {
  454. case ENCRYPT_START:
  455. fprintf(NetTrace, " START");
  456. break;
  457. case ENCRYPT_END:
  458. fprintf(NetTrace, " END");
  459. break;
  460. case ENCRYPT_REQSTART:
  461. fprintf(NetTrace, " REQUEST-START");
  462. break;
  463. case ENCRYPT_REQEND:
  464. fprintf(NetTrace, " REQUEST-END");
  465. break;
  466. case ENCRYPT_IS:
  467. case ENCRYPT_REPLY:
  468. fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
  469. "IS" : "REPLY");
  470. if (length < 3) {
  471. fprintf(NetTrace, " (partial suboption??\?)");
  472. break;
  473. }
  474. if (ENCTYPE_NAME_OK(pointer[2]))
  475. fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2]));
  476. else
  477. fprintf(NetTrace, " %d (unknown)", pointer[2]);
  478. encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
  479. fprintf(NetTrace, "%s", buf);
  480. break;
  481. case ENCRYPT_SUPPORT:
  482. i = 2;
  483. fprintf(NetTrace, " SUPPORT ");
  484. while (i < length) {
  485. if (ENCTYPE_NAME_OK(pointer[i]))
  486. fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i]));
  487. else
  488. fprintf(NetTrace, "%d ", pointer[i]);
  489. i++;
  490. }
  491. break;
  492. case ENCRYPT_ENC_KEYID:
  493. fprintf(NetTrace, " ENC_KEYID ");
  494. goto encommon;
  495. case ENCRYPT_DEC_KEYID:
  496. fprintf(NetTrace, " DEC_KEYID ");
  497. goto encommon;
  498. default:
  499. fprintf(NetTrace, " %d (unknown)", pointer[1]);
  500. encommon:
  501. for (i = 2; i < length; i++)
  502. fprintf(NetTrace, " %d", pointer[i]);
  503. break;
  504. }
  505. break;
  506. #endif /* ENCRYPTION */
  507. case TELOPT_LINEMODE:
  508. fprintf(NetTrace, "LINEMODE ");
  509. if (length < 2) {
  510. fprintf(NetTrace, " (empty suboption??\?)");
  511. break;
  512. }
  513. switch (pointer[1]) {
  514. case WILL:
  515. fprintf(NetTrace, "WILL ");
  516. goto common;
  517. case WONT:
  518. fprintf(NetTrace, "WONT ");
  519. goto common;
  520. case DO:
  521. fprintf(NetTrace, "DO ");
  522. goto common;
  523. case DONT:
  524. fprintf(NetTrace, "DONT ");
  525. common:
  526. if (length < 3) {
  527. fprintf(NetTrace, "(no option??\?)");
  528. break;
  529. }
  530. switch (pointer[2]) {
  531. case LM_FORWARDMASK:
  532. fprintf(NetTrace, "Forward Mask");
  533. for (i = 3; i < length; i++)
  534. fprintf(NetTrace, " %x", pointer[i]);
  535. break;
  536. default:
  537. fprintf(NetTrace, "%d (unknown)", pointer[2]);
  538. for (i = 3; i < length; i++)
  539. fprintf(NetTrace, " %d", pointer[i]);
  540. break;
  541. }
  542. break;
  543. case LM_SLC:
  544. fprintf(NetTrace, "SLC");
  545. for (i = 2; i < length - 2; i += 3) {
  546. if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
  547. fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
  548. else
  549. fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
  550. switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
  551. case SLC_NOSUPPORT:
  552. fprintf(NetTrace, " NOSUPPORT"); break;
  553. case SLC_CANTCHANGE:
  554. fprintf(NetTrace, " CANTCHANGE"); break;
  555. case SLC_VARIABLE:
  556. fprintf(NetTrace, " VARIABLE"); break;
  557. case SLC_DEFAULT:
  558. fprintf(NetTrace, " DEFAULT"); break;
  559. }
  560. fprintf(NetTrace, "%s%s%s",
  561. pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
  562. pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
  563. pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
  564. if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
  565. SLC_FLUSHOUT| SLC_LEVELBITS))
  566. fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
  567. fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
  568. if ((pointer[i+SLC_VALUE] == IAC) &&
  569. (pointer[i+SLC_VALUE+1] == IAC))
  570. i++;
  571. }
  572. for (; i < length; i++)
  573. fprintf(NetTrace, " ?%d?", pointer[i]);
  574. break;
  575. case LM_MODE:
  576. fprintf(NetTrace, "MODE ");
  577. if (length < 3) {
  578. fprintf(NetTrace, "(no mode??\?)");
  579. break;
  580. }
  581. {
  582. char tbuf[64];
  583. sprintf(tbuf, "%s%s%s%s%s",
  584. pointer[2]&MODE_EDIT ? "|EDIT" : "",
  585. pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
  586. pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
  587. pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
  588. pointer[2]&MODE_ACK ? "|ACK" : "");
  589. fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
  590. }
  591. if (pointer[2]&~(MODE_MASK))
  592. fprintf(NetTrace, " (0x%x)", pointer[2]);
  593. for (i = 3; i < length; i++)
  594. fprintf(NetTrace, " ?0x%x?", pointer[i]);
  595. break;
  596. default:
  597. fprintf(NetTrace, "%d (unknown)", pointer[1]);
  598. for (i = 2; i < length; i++)
  599. fprintf(NetTrace, " %d", pointer[i]);
  600. }
  601. break;
  602. case TELOPT_STATUS: {
  603. const char *cp;
  604. int j, k;
  605. fprintf(NetTrace, "STATUS");
  606. switch (pointer[1]) {
  607. default:
  608. if (pointer[1] == TELQUAL_SEND)
  609. fprintf(NetTrace, " SEND");
  610. else
  611. fprintf(NetTrace, " %d (unknown)", pointer[1]);
  612. for (i = 2; i < length; i++)
  613. fprintf(NetTrace, " ?%d?", pointer[i]);
  614. break;
  615. case TELQUAL_IS:
  616. if (--want_status_response < 0)
  617. want_status_response = 0;
  618. if (NetTrace == stdout)
  619. fprintf(NetTrace, " IS\r\n");
  620. else
  621. fprintf(NetTrace, " IS\n");
  622. for (i = 2; i < length; i++) {
  623. switch(pointer[i]) {
  624. case DO: cp = "DO"; goto common2;
  625. case DONT: cp = "DONT"; goto common2;
  626. case WILL: cp = "WILL"; goto common2;
  627. case WONT: cp = "WONT"; goto common2;
  628. common2:
  629. i++;
  630. if (TELOPT_OK((int)pointer[i]))
  631. fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
  632. else
  633. fprintf(NetTrace, " %s %d", cp, pointer[i]);
  634. if (NetTrace == stdout)
  635. fprintf(NetTrace, "\r\n");
  636. else
  637. fprintf(NetTrace, "\n");
  638. break;
  639. case SB:
  640. fprintf(NetTrace, " SB ");
  641. i++;
  642. j = k = i;
  643. while (j < length) {
  644. if (pointer[j] == SE) {
  645. if (j+1 == length)
  646. break;
  647. if (pointer[j+1] == SE)
  648. j++;
  649. else
  650. break;
  651. }
  652. pointer[k++] = pointer[j++];
  653. }
  654. printsub(0, &pointer[i], k - i);
  655. if (i < length) {
  656. fprintf(NetTrace, " SE");
  657. i = j;
  658. } else
  659. i = j - 1;
  660. if (NetTrace == stdout)
  661. fprintf(NetTrace, "\r\n");
  662. else
  663. fprintf(NetTrace, "\n");
  664. break;
  665. default:
  666. fprintf(NetTrace, " %d", pointer[i]);
  667. break;
  668. }
  669. }
  670. break;
  671. }
  672. break;
  673. }
  674. case TELOPT_XDISPLOC:
  675. fprintf(NetTrace, "X-DISPLAY-LOCATION ");
  676. switch (pointer[1]) {
  677. case TELQUAL_IS:
  678. fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
  679. break;
  680. case TELQUAL_SEND:
  681. fprintf(NetTrace, "SEND");
  682. break;
  683. default:
  684. fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
  685. pointer[1], pointer[1]);
  686. }
  687. break;
  688. case TELOPT_NEW_ENVIRON:
  689. fprintf(NetTrace, "NEW-ENVIRON ");
  690. #ifdef OLD_ENVIRON
  691. goto env_common1;
  692. case TELOPT_OLD_ENVIRON:
  693. fprintf(NetTrace, "OLD-ENVIRON");
  694. env_common1:
  695. #endif
  696. switch (pointer[1]) {
  697. case TELQUAL_IS:
  698. fprintf(NetTrace, "IS ");
  699. goto env_common;
  700. case TELQUAL_SEND:
  701. fprintf(NetTrace, "SEND ");
  702. goto env_common;
  703. case TELQUAL_INFO:
  704. fprintf(NetTrace, "INFO ");
  705. env_common:
  706. {
  707. int noquote = 2;
  708. #if defined(ENV_HACK) && defined(OLD_ENVIRON)
  709. extern int old_env_var, old_env_value;
  710. #endif
  711. for (i = 2; i < length; i++ ) {
  712. switch (pointer[i]) {
  713. case NEW_ENV_VALUE:
  714. #ifdef OLD_ENVIRON
  715. /* case NEW_ENV_OVAR: */
  716. if (pointer[0] == TELOPT_OLD_ENVIRON) {
  717. # ifdef ENV_HACK
  718. if (old_env_var == OLD_ENV_VALUE)
  719. fprintf(NetTrace, "\" (VALUE) " + noquote);
  720. else
  721. # endif
  722. fprintf(NetTrace, "\" VAR " + noquote);
  723. } else
  724. #endif /* OLD_ENVIRON */
  725. fprintf(NetTrace, "\" VALUE " + noquote);
  726. noquote = 2;
  727. break;
  728. case NEW_ENV_VAR:
  729. #ifdef OLD_ENVIRON
  730. /* case OLD_ENV_VALUE: */
  731. if (pointer[0] == TELOPT_OLD_ENVIRON) {
  732. # ifdef ENV_HACK
  733. if (old_env_value == OLD_ENV_VAR)
  734. fprintf(NetTrace, "\" (VAR) " + noquote);
  735. else
  736. # endif
  737. fprintf(NetTrace, "\" VALUE " + noquote);
  738. } else
  739. #endif /* OLD_ENVIRON */
  740. fprintf(NetTrace, "\" VAR " + noquote);
  741. noquote = 2;
  742. break;
  743. case ENV_ESC:
  744. fprintf(NetTrace, "\" ESC " + noquote);
  745. noquote = 2;
  746. break;
  747. case ENV_USERVAR:
  748. fprintf(NetTrace, "\" USERVAR " + noquote);
  749. noquote = 2;
  750. break;
  751. default:
  752. if (isprint(pointer[i]) && pointer[i] != '"') {
  753. if (noquote) {
  754. putc('"', NetTrace);
  755. noquote = 0;
  756. }
  757. putc(pointer[i], NetTrace);
  758. } else {
  759. fprintf(NetTrace, "\" %03o " + noquote,
  760. pointer[i]);
  761. noquote = 2;
  762. }
  763. break;
  764. }
  765. }
  766. if (!noquote)
  767. putc('"', NetTrace);
  768. break;
  769. }
  770. }
  771. break;
  772. default:
  773. if (TELOPT_OK(pointer[0]))
  774. fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
  775. else
  776. fprintf(NetTrace, "%d (unknown)", pointer[0]);
  777. for (i = 1; i < length; i++)
  778. fprintf(NetTrace, " %d", pointer[i]);
  779. break;
  780. }
  781. if (direction) {
  782. if (NetTrace == stdout)
  783. fprintf(NetTrace, "\r\n");
  784. else
  785. fprintf(NetTrace, "\n");
  786. }
  787. if (NetTrace == stdout)
  788. fflush(NetTrace);
  789. }
  790. }
  791. /* EmptyTerminal - called to make sure that the terminal buffer is empty.
  792. * Note that we consider the buffer to run all the
  793. * way to the kernel (thus the select).
  794. */
  795. static void
  796. EmptyTerminal(void)
  797. {
  798. fd_set o;
  799. FD_ZERO(&o);
  800. if (TTYBYTES() == 0) {
  801. FD_SET(tout, &o);
  802. (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
  803. (struct timeval *) 0); /* wait for TTLOWAT */
  804. } else {
  805. while (TTYBYTES()) {
  806. (void) ttyflush(0);
  807. FD_SET(tout, &o);
  808. (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
  809. (struct timeval *) 0); /* wait for TTLOWAT */
  810. }
  811. }
  812. }
  813. static void
  814. SetForExit(void)
  815. {
  816. setconnmode(0);
  817. do {
  818. (void)telrcv(); /* Process any incoming data */
  819. EmptyTerminal();
  820. } while (ring_full_count(&netiring)); /* While there is any */
  821. setcommandmode();
  822. fflush(stdout);
  823. fflush(stderr);
  824. setconnmode(0);
  825. EmptyTerminal(); /* Flush the path to the tty */
  826. setcommandmode();
  827. }
  828. void
  829. Exit(int returnCode)
  830. {
  831. SetForExit();
  832. exit(returnCode);
  833. }
  834. void
  835. ExitString(const char *string, int returnCode)
  836. {
  837. SetForExit();
  838. fwrite(string, 1, strlen(string), stderr);
  839. exit(returnCode);
  840. }