PageRenderTime 63ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/crypto/heimdal/appl/telnet/telnet/commands.c

https://github.com/okuoku/freebsd-head
C | 2145 lines | 1823 code | 193 blank | 129 comment | 429 complexity | 8a98024eb1225ee95da13894b0512c4d MD5 | raw file
  1. /*
  2. * Copyright (c) 1988, 1990, 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. #include "telnet_locl.h"
  34. RCSID("$Id: commands.c 16224 2005-10-22 17:17:44Z lha $");
  35. #if defined(IPPROTO_IP) && defined(IP_TOS)
  36. int tos = -1;
  37. #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
  38. char *hostname;
  39. static char _hostname[MaxHostNameLen];
  40. typedef int (*intrtn_t)(int, char**);
  41. static int call(intrtn_t, ...);
  42. typedef struct {
  43. char *name; /* command name */
  44. char *help; /* help string (NULL for no help) */
  45. int (*handler)(); /* routine which executes command */
  46. int needconnect; /* Do we need to be connected to execute? */
  47. } Command;
  48. static char line[256];
  49. static char saveline[256];
  50. static int margc;
  51. static char *margv[20];
  52. static void
  53. makeargv()
  54. {
  55. char *cp, *cp2, c;
  56. char **argp = margv;
  57. margc = 0;
  58. cp = line;
  59. if (*cp == '!') { /* Special case shell escape */
  60. /* save for shell command */
  61. strlcpy(saveline, line, sizeof(saveline));
  62. *argp++ = "!"; /* No room in string to get this */
  63. margc++;
  64. cp++;
  65. }
  66. while ((c = *cp)) {
  67. int inquote = 0;
  68. while (isspace((unsigned char)c))
  69. c = *++cp;
  70. if (c == '\0')
  71. break;
  72. *argp++ = cp;
  73. margc += 1;
  74. for (cp2 = cp; c != '\0'; c = *++cp) {
  75. if (inquote) {
  76. if (c == inquote) {
  77. inquote = 0;
  78. continue;
  79. }
  80. } else {
  81. if (c == '\\') {
  82. if ((c = *++cp) == '\0')
  83. break;
  84. } else if (c == '"') {
  85. inquote = '"';
  86. continue;
  87. } else if (c == '\'') {
  88. inquote = '\'';
  89. continue;
  90. } else if (isspace((unsigned char)c))
  91. break;
  92. }
  93. *cp2++ = c;
  94. }
  95. *cp2 = '\0';
  96. if (c == '\0')
  97. break;
  98. cp++;
  99. }
  100. *argp++ = 0;
  101. }
  102. /*
  103. * Make a character string into a number.
  104. *
  105. * Todo: 1. Could take random integers (12, 0x12, 012, 0b1).
  106. */
  107. static char
  108. special(char *s)
  109. {
  110. char c;
  111. char b;
  112. switch (*s) {
  113. case '^':
  114. b = *++s;
  115. if (b == '?') {
  116. c = b | 0x40; /* DEL */
  117. } else {
  118. c = b & 0x1f;
  119. }
  120. break;
  121. default:
  122. c = *s;
  123. break;
  124. }
  125. return c;
  126. }
  127. /*
  128. * Construct a control character sequence
  129. * for a special character.
  130. */
  131. static char *
  132. control(cc_t c)
  133. {
  134. static char buf[5];
  135. /*
  136. * The only way I could get the Sun 3.5 compiler
  137. * to shut up about
  138. * if ((unsigned int)c >= 0x80)
  139. * was to assign "c" to an unsigned int variable...
  140. * Arggg....
  141. */
  142. unsigned int uic = (unsigned int)c;
  143. if (uic == 0x7f)
  144. return ("^?");
  145. if (c == (cc_t)_POSIX_VDISABLE) {
  146. return "off";
  147. }
  148. if (uic >= 0x80) {
  149. buf[0] = '\\';
  150. buf[1] = ((c>>6)&07) + '0';
  151. buf[2] = ((c>>3)&07) + '0';
  152. buf[3] = (c&07) + '0';
  153. buf[4] = 0;
  154. } else if (uic >= 0x20) {
  155. buf[0] = c;
  156. buf[1] = 0;
  157. } else {
  158. buf[0] = '^';
  159. buf[1] = '@'+c;
  160. buf[2] = 0;
  161. }
  162. return (buf);
  163. }
  164. /*
  165. * The following are data structures and routines for
  166. * the "send" command.
  167. *
  168. */
  169. struct sendlist {
  170. char *name; /* How user refers to it (case independent) */
  171. char *help; /* Help information (0 ==> no help) */
  172. int needconnect; /* Need to be connected */
  173. int narg; /* Number of arguments */
  174. int (*handler)(); /* Routine to perform (for special ops) */
  175. int nbyte; /* Number of bytes to send this command */
  176. int what; /* Character to be sent (<0 ==> special) */
  177. };
  178. static int
  179. send_esc (void),
  180. send_help (void),
  181. send_docmd (char *),
  182. send_dontcmd (char *),
  183. send_willcmd (char *),
  184. send_wontcmd (char *);
  185. static struct sendlist Sendlist[] = {
  186. { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO },
  187. { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT },
  188. { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK },
  189. { "break", 0, 1, 0, 0, 2, BREAK },
  190. { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC },
  191. { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL },
  192. { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 },
  193. { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA },
  194. { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP },
  195. { "intp", 0, 1, 0, 0, 2, IP },
  196. { "interrupt", 0, 1, 0, 0, 2, IP },
  197. { "intr", 0, 1, 0, 0, 2, IP },
  198. { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP },
  199. { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR },
  200. { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT },
  201. { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP },
  202. { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF },
  203. { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 },
  204. { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 },
  205. { "?", "Display send options", 0, 0, send_help, 0, 0 },
  206. { "help", 0, 0, 0, send_help, 0, 0 },
  207. { "do", 0, 0, 1, send_docmd, 3, 0 },
  208. { "dont", 0, 0, 1, send_dontcmd, 3, 0 },
  209. { "will", 0, 0, 1, send_willcmd, 3, 0 },
  210. { "wont", 0, 0, 1, send_wontcmd, 3, 0 },
  211. { 0 }
  212. };
  213. #define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
  214. sizeof(struct sendlist)))
  215. static int
  216. sendcmd(int argc, char **argv)
  217. {
  218. int count; /* how many bytes we are going to need to send */
  219. int i;
  220. struct sendlist *s; /* pointer to current command */
  221. int success = 0;
  222. int needconnect = 0;
  223. if (argc < 2) {
  224. printf("need at least one argument for 'send' command\r\n");
  225. printf("'send ?' for help\r\n");
  226. return 0;
  227. }
  228. /*
  229. * First, validate all the send arguments.
  230. * In addition, we see how much space we are going to need, and
  231. * whether or not we will be doing a "SYNCH" operation (which
  232. * flushes the network queue).
  233. */
  234. count = 0;
  235. for (i = 1; i < argc; i++) {
  236. s = GETSEND(argv[i]);
  237. if (s == 0) {
  238. printf("Unknown send argument '%s'\r\n'send ?' for help.\r\n",
  239. argv[i]);
  240. return 0;
  241. } else if (Ambiguous(s)) {
  242. printf("Ambiguous send argument '%s'\r\n'send ?' for help.\r\n",
  243. argv[i]);
  244. return 0;
  245. }
  246. if (i + s->narg >= argc) {
  247. fprintf(stderr,
  248. "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\r\n",
  249. s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
  250. return 0;
  251. }
  252. count += s->nbyte;
  253. if (s->handler == send_help) {
  254. send_help();
  255. return 0;
  256. }
  257. i += s->narg;
  258. needconnect += s->needconnect;
  259. }
  260. if (!connected && needconnect) {
  261. printf("?Need to be connected first.\r\n");
  262. printf("'send ?' for help\r\n");
  263. return 0;
  264. }
  265. /* Now, do we have enough room? */
  266. if (NETROOM() < count) {
  267. printf("There is not enough room in the buffer TO the network\r\n");
  268. printf("to process your request. Nothing will be done.\r\n");
  269. printf("('send synch' will throw away most data in the network\r\n");
  270. printf("buffer, if this might help.)\r\n");
  271. return 0;
  272. }
  273. /* OK, they are all OK, now go through again and actually send */
  274. count = 0;
  275. for (i = 1; i < argc; i++) {
  276. if ((s = GETSEND(argv[i])) == 0) {
  277. fprintf(stderr, "Telnet 'send' error - argument disappeared!\r\n");
  278. quit();
  279. /*NOTREACHED*/
  280. }
  281. if (s->handler) {
  282. count++;
  283. success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
  284. (s->narg > 1) ? argv[i+2] : 0);
  285. i += s->narg;
  286. } else {
  287. NET2ADD(IAC, s->what);
  288. printoption("SENT", IAC, s->what);
  289. }
  290. }
  291. return (count == success);
  292. }
  293. static int
  294. send_tncmd(void (*func)(), char *cmd, char *name);
  295. static int
  296. send_esc()
  297. {
  298. NETADD(escape);
  299. return 1;
  300. }
  301. static int
  302. send_docmd(char *name)
  303. {
  304. return(send_tncmd(send_do, "do", name));
  305. }
  306. static int
  307. send_dontcmd(char *name)
  308. {
  309. return(send_tncmd(send_dont, "dont", name));
  310. }
  311. static int
  312. send_willcmd(char *name)
  313. {
  314. return(send_tncmd(send_will, "will", name));
  315. }
  316. static int
  317. send_wontcmd(char *name)
  318. {
  319. return(send_tncmd(send_wont, "wont", name));
  320. }
  321. extern char *telopts[]; /* XXX */
  322. static int
  323. send_tncmd(void (*func)(), char *cmd, char *name)
  324. {
  325. char **cpp;
  326. int val = 0;
  327. if (isprefix(name, "help") || isprefix(name, "?")) {
  328. int col, len;
  329. printf("Usage: send %s <value|option>\r\n", cmd);
  330. printf("\"value\" must be from 0 to 255\r\n");
  331. printf("Valid options are:\r\n\t");
  332. col = 8;
  333. for (cpp = telopts; *cpp; cpp++) {
  334. len = strlen(*cpp) + 3;
  335. if (col + len > 65) {
  336. printf("\r\n\t");
  337. col = 8;
  338. }
  339. printf(" \"%s\"", *cpp);
  340. col += len;
  341. }
  342. printf("\r\n");
  343. return 0;
  344. }
  345. cpp = genget(name, telopts, sizeof(char *));
  346. if (Ambiguous(cpp)) {
  347. fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\r\n",
  348. name, cmd);
  349. return 0;
  350. }
  351. if (cpp) {
  352. val = cpp - telopts;
  353. } else {
  354. char *cp = name;
  355. while (*cp >= '0' && *cp <= '9') {
  356. val *= 10;
  357. val += *cp - '0';
  358. cp++;
  359. }
  360. if (*cp != 0) {
  361. fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\r\n",
  362. name, cmd);
  363. return 0;
  364. } else if (val < 0 || val > 255) {
  365. fprintf(stderr, "'%s': bad value ('send %s ?' for help).\r\n",
  366. name, cmd);
  367. return 0;
  368. }
  369. }
  370. if (!connected) {
  371. printf("?Need to be connected first.\r\n");
  372. return 0;
  373. }
  374. (*func)(val, 1);
  375. return 1;
  376. }
  377. static int
  378. send_help()
  379. {
  380. struct sendlist *s; /* pointer to current command */
  381. for (s = Sendlist; s->name; s++) {
  382. if (s->help)
  383. printf("%-15s %s\r\n", s->name, s->help);
  384. }
  385. return(0);
  386. }
  387. /*
  388. * The following are the routines and data structures referred
  389. * to by the arguments to the "toggle" command.
  390. */
  391. static int
  392. lclchars()
  393. {
  394. donelclchars = 1;
  395. return 1;
  396. }
  397. static int
  398. togdebug()
  399. {
  400. #ifndef NOT43
  401. if (net > 0 &&
  402. (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
  403. perror("setsockopt (SO_DEBUG)");
  404. }
  405. #else /* NOT43 */
  406. if (debug) {
  407. if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
  408. perror("setsockopt (SO_DEBUG)");
  409. } else
  410. printf("Cannot turn off socket debugging\r\n");
  411. #endif /* NOT43 */
  412. return 1;
  413. }
  414. #if defined(KRB4) && defined(HAVE_KRB_DISABLE_DEBUG)
  415. #include <krb.h>
  416. static int
  417. togkrbdebug(void)
  418. {
  419. if(krb_debug)
  420. krb_enable_debug();
  421. else
  422. krb_disable_debug();
  423. return 1;
  424. }
  425. #endif
  426. static int
  427. togcrlf()
  428. {
  429. if (crlf) {
  430. printf("Will send carriage returns as telnet <CR><LF>.\r\n");
  431. } else {
  432. printf("Will send carriage returns as telnet <CR><NUL>.\r\n");
  433. }
  434. return 1;
  435. }
  436. int binmode;
  437. static int
  438. togbinary(int val)
  439. {
  440. donebinarytoggle = 1;
  441. if (val >= 0) {
  442. binmode = val;
  443. } else {
  444. if (my_want_state_is_will(TELOPT_BINARY) &&
  445. my_want_state_is_do(TELOPT_BINARY)) {
  446. binmode = 1;
  447. } else if (my_want_state_is_wont(TELOPT_BINARY) &&
  448. my_want_state_is_dont(TELOPT_BINARY)) {
  449. binmode = 0;
  450. }
  451. val = binmode ? 0 : 1;
  452. }
  453. if (val == 1) {
  454. if (my_want_state_is_will(TELOPT_BINARY) &&
  455. my_want_state_is_do(TELOPT_BINARY)) {
  456. printf("Already operating in binary mode with remote host.\r\n");
  457. } else {
  458. printf("Negotiating binary mode with remote host.\r\n");
  459. tel_enter_binary(3);
  460. }
  461. } else {
  462. if (my_want_state_is_wont(TELOPT_BINARY) &&
  463. my_want_state_is_dont(TELOPT_BINARY)) {
  464. printf("Already in network ascii mode with remote host.\r\n");
  465. } else {
  466. printf("Negotiating network ascii mode with remote host.\r\n");
  467. tel_leave_binary(3);
  468. }
  469. }
  470. return 1;
  471. }
  472. static int
  473. togrbinary(int val)
  474. {
  475. donebinarytoggle = 1;
  476. if (val == -1)
  477. val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
  478. if (val == 1) {
  479. if (my_want_state_is_do(TELOPT_BINARY)) {
  480. printf("Already receiving in binary mode.\r\n");
  481. } else {
  482. printf("Negotiating binary mode on input.\r\n");
  483. tel_enter_binary(1);
  484. }
  485. } else {
  486. if (my_want_state_is_dont(TELOPT_BINARY)) {
  487. printf("Already receiving in network ascii mode.\r\n");
  488. } else {
  489. printf("Negotiating network ascii mode on input.\r\n");
  490. tel_leave_binary(1);
  491. }
  492. }
  493. return 1;
  494. }
  495. static int
  496. togxbinary(int val)
  497. {
  498. donebinarytoggle = 1;
  499. if (val == -1)
  500. val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
  501. if (val == 1) {
  502. if (my_want_state_is_will(TELOPT_BINARY)) {
  503. printf("Already transmitting in binary mode.\r\n");
  504. } else {
  505. printf("Negotiating binary mode on output.\r\n");
  506. tel_enter_binary(2);
  507. }
  508. } else {
  509. if (my_want_state_is_wont(TELOPT_BINARY)) {
  510. printf("Already transmitting in network ascii mode.\r\n");
  511. } else {
  512. printf("Negotiating network ascii mode on output.\r\n");
  513. tel_leave_binary(2);
  514. }
  515. }
  516. return 1;
  517. }
  518. static int togglehelp (void);
  519. #if defined(AUTHENTICATION)
  520. extern int auth_togdebug (int);
  521. #endif
  522. #if defined(ENCRYPTION)
  523. extern int EncryptAutoEnc (int);
  524. extern int EncryptAutoDec (int);
  525. extern int EncryptDebug (int);
  526. extern int EncryptVerbose (int);
  527. #endif
  528. struct togglelist {
  529. char *name; /* name of toggle */
  530. char *help; /* help message */
  531. int (*handler)(); /* routine to do actual setting */
  532. int *variable;
  533. char *actionexplanation;
  534. };
  535. static struct togglelist Togglelist[] = {
  536. { "autoflush",
  537. "flushing of output when sending interrupt characters",
  538. 0,
  539. &autoflush,
  540. "flush output when sending interrupt characters" },
  541. { "autosynch",
  542. "automatic sending of interrupt characters in urgent mode",
  543. 0,
  544. &autosynch,
  545. "send interrupt characters in urgent mode" },
  546. #if defined(AUTHENTICATION)
  547. { "autologin",
  548. "automatic sending of login and/or authentication info",
  549. 0,
  550. &autologin,
  551. "send login name and/or authentication information" },
  552. { "authdebug",
  553. "authentication debugging",
  554. auth_togdebug,
  555. 0,
  556. "print authentication debugging information" },
  557. #endif
  558. #if defined(ENCRYPTION)
  559. { "autoencrypt",
  560. "automatic encryption of data stream",
  561. EncryptAutoEnc,
  562. 0,
  563. "automatically encrypt output" },
  564. { "autodecrypt",
  565. "automatic decryption of data stream",
  566. EncryptAutoDec,
  567. 0,
  568. "automatically decrypt input" },
  569. { "verbose_encrypt",
  570. "verbose encryption output",
  571. EncryptVerbose,
  572. 0,
  573. "print verbose encryption output" },
  574. { "encdebug",
  575. "encryption debugging",
  576. EncryptDebug,
  577. 0,
  578. "print encryption debugging information" },
  579. #endif
  580. #if defined(KRB5)
  581. { "forward",
  582. "credentials forwarding",
  583. kerberos5_set_forward,
  584. 0,
  585. "forward credentials" },
  586. { "forwardable",
  587. "forwardable flag of forwarded credentials",
  588. kerberos5_set_forwardable,
  589. 0,
  590. "forward forwardable credentials" },
  591. #endif
  592. { "skiprc",
  593. "don't read ~/.telnetrc file",
  594. 0,
  595. &skiprc,
  596. "skip reading of ~/.telnetrc file" },
  597. { "binary",
  598. "sending and receiving of binary data",
  599. togbinary,
  600. 0,
  601. 0 },
  602. { "inbinary",
  603. "receiving of binary data",
  604. togrbinary,
  605. 0,
  606. 0 },
  607. { "outbinary",
  608. "sending of binary data",
  609. togxbinary,
  610. 0,
  611. 0 },
  612. { "crlf",
  613. "sending carriage returns as telnet <CR><LF>",
  614. togcrlf,
  615. &crlf,
  616. 0 },
  617. { "crmod",
  618. "mapping of received carriage returns",
  619. 0,
  620. &crmod,
  621. "map carriage return on output" },
  622. { "localchars",
  623. "local recognition of certain control characters",
  624. lclchars,
  625. &localchars,
  626. "recognize certain control characters" },
  627. { " ", "", 0 }, /* empty line */
  628. { "debug",
  629. "debugging",
  630. togdebug,
  631. &debug,
  632. "turn on socket level debugging" },
  633. #if defined(KRB4) && defined(HAVE_KRB_DISABLE_DEBUG)
  634. { "krb_debug",
  635. "kerberos 4 debugging",
  636. togkrbdebug,
  637. &krb_debug,
  638. "turn on kerberos 4 debugging" },
  639. #endif
  640. { "netdata",
  641. "printing of hexadecimal network data (debugging)",
  642. 0,
  643. &netdata,
  644. "print hexadecimal representation of network traffic" },
  645. { "prettydump",
  646. "output of \"netdata\" to user readable format (debugging)",
  647. 0,
  648. &prettydump,
  649. "print user readable output for \"netdata\"" },
  650. { "options",
  651. "viewing of options processing (debugging)",
  652. 0,
  653. &showoptions,
  654. "show option processing" },
  655. { "termdata",
  656. "printing of hexadecimal terminal data (debugging)",
  657. 0,
  658. &termdata,
  659. "print hexadecimal representation of terminal traffic" },
  660. { "?",
  661. 0,
  662. togglehelp },
  663. { "help",
  664. 0,
  665. togglehelp },
  666. { 0 }
  667. };
  668. static int
  669. togglehelp()
  670. {
  671. struct togglelist *c;
  672. for (c = Togglelist; c->name; c++) {
  673. if (c->help) {
  674. if (*c->help)
  675. printf("%-15s toggle %s\r\n", c->name, c->help);
  676. else
  677. printf("\r\n");
  678. }
  679. }
  680. printf("\r\n");
  681. printf("%-15s %s\r\n", "?", "display help information");
  682. return 0;
  683. }
  684. static void
  685. settogglehelp(int set)
  686. {
  687. struct togglelist *c;
  688. for (c = Togglelist; c->name; c++) {
  689. if (c->help) {
  690. if (*c->help)
  691. printf("%-15s %s %s\r\n", c->name, set ? "enable" : "disable",
  692. c->help);
  693. else
  694. printf("\r\n");
  695. }
  696. }
  697. }
  698. #define GETTOGGLE(name) (struct togglelist *) \
  699. genget(name, (char **) Togglelist, sizeof(struct togglelist))
  700. static int
  701. toggle(int argc, char *argv[])
  702. {
  703. int retval = 1;
  704. char *name;
  705. struct togglelist *c;
  706. if (argc < 2) {
  707. fprintf(stderr,
  708. "Need an argument to 'toggle' command. 'toggle ?' for help.\r\n");
  709. return 0;
  710. }
  711. argc--;
  712. argv++;
  713. while (argc--) {
  714. name = *argv++;
  715. c = GETTOGGLE(name);
  716. if (Ambiguous(c)) {
  717. fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\r\n",
  718. name);
  719. return 0;
  720. } else if (c == 0) {
  721. fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\r\n",
  722. name);
  723. return 0;
  724. } else {
  725. if (c->variable) {
  726. *c->variable = !*c->variable; /* invert it */
  727. if (c->actionexplanation) {
  728. printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
  729. c->actionexplanation);
  730. }
  731. }
  732. if (c->handler) {
  733. retval &= (*c->handler)(-1);
  734. }
  735. }
  736. }
  737. return retval;
  738. }
  739. /*
  740. * The following perform the "set" command.
  741. */
  742. struct termios new_tc = { 0 };
  743. struct setlist {
  744. char *name; /* name */
  745. char *help; /* help information */
  746. void (*handler)();
  747. cc_t *charp; /* where it is located at */
  748. };
  749. static struct setlist Setlist[] = {
  750. #ifdef KLUDGELINEMODE
  751. { "echo", "character to toggle local echoing on/off", 0, &echoc },
  752. #endif
  753. { "escape", "character to escape back to telnet command mode", 0, &escape },
  754. { "rlogin", "rlogin escape character", 0, &rlogin },
  755. { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
  756. { " ", "" },
  757. { " ", "The following need 'localchars' to be toggled true", 0, 0 },
  758. { "flushoutput", "character to cause an Abort Output", 0, &termFlushChar },
  759. { "interrupt", "character to cause an Interrupt Process", 0, &termIntChar },
  760. { "quit", "character to cause an Abort process", 0, &termQuitChar },
  761. { "eof", "character to cause an EOF ", 0, &termEofChar },
  762. { " ", "" },
  763. { " ", "The following are for local editing in linemode", 0, 0 },
  764. { "erase", "character to use to erase a character", 0, &termEraseChar },
  765. { "kill", "character to use to erase a line", 0, &termKillChar },
  766. { "lnext", "character to use for literal next", 0, &termLiteralNextChar },
  767. { "susp", "character to cause a Suspend Process", 0, &termSuspChar },
  768. { "reprint", "character to use for line reprint", 0, &termRprntChar },
  769. { "worderase", "character to use to erase a word", 0, &termWerasChar },
  770. { "start", "character to use for XON", 0, &termStartChar },
  771. { "stop", "character to use for XOFF", 0, &termStopChar },
  772. { "forw1", "alternate end of line character", 0, &termForw1Char },
  773. { "forw2", "alternate end of line character", 0, &termForw2Char },
  774. { "ayt", "alternate AYT character", 0, &termAytChar },
  775. { 0 }
  776. };
  777. static struct setlist *
  778. getset(char *name)
  779. {
  780. return (struct setlist *)
  781. genget(name, (char **) Setlist, sizeof(struct setlist));
  782. }
  783. void
  784. set_escape_char(char *s)
  785. {
  786. if (rlogin != _POSIX_VDISABLE) {
  787. rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
  788. printf("Telnet rlogin escape character is '%s'.\r\n",
  789. control(rlogin));
  790. } else {
  791. escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
  792. printf("Telnet escape character is '%s'.\r\n", control(escape));
  793. }
  794. }
  795. static int
  796. setcmd(int argc, char *argv[])
  797. {
  798. int value;
  799. struct setlist *ct;
  800. struct togglelist *c;
  801. if (argc < 2 || argc > 3) {
  802. printf("Format is 'set Name Value'\r\n'set ?' for help.\r\n");
  803. return 0;
  804. }
  805. if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
  806. for (ct = Setlist; ct->name; ct++)
  807. printf("%-15s %s\r\n", ct->name, ct->help);
  808. printf("\r\n");
  809. settogglehelp(1);
  810. printf("%-15s %s\r\n", "?", "display help information");
  811. return 0;
  812. }
  813. ct = getset(argv[1]);
  814. if (ct == 0) {
  815. c = GETTOGGLE(argv[1]);
  816. if (c == 0) {
  817. fprintf(stderr, "'%s': unknown argument ('set ?' for help).\r\n",
  818. argv[1]);
  819. return 0;
  820. } else if (Ambiguous(c)) {
  821. fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\r\n",
  822. argv[1]);
  823. return 0;
  824. }
  825. if (c->variable) {
  826. if ((argc == 2) || (strcmp("on", argv[2]) == 0))
  827. *c->variable = 1;
  828. else if (strcmp("off", argv[2]) == 0)
  829. *c->variable = 0;
  830. else {
  831. printf("Format is 'set togglename [on|off]'\r\n'set ?' for help.\r\n");
  832. return 0;
  833. }
  834. if (c->actionexplanation) {
  835. printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
  836. c->actionexplanation);
  837. }
  838. }
  839. if (c->handler)
  840. (*c->handler)(1);
  841. } else if (argc != 3) {
  842. printf("Format is 'set Name Value'\r\n'set ?' for help.\r\n");
  843. return 0;
  844. } else if (Ambiguous(ct)) {
  845. fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\r\n",
  846. argv[1]);
  847. return 0;
  848. } else if (ct->handler) {
  849. (*ct->handler)(argv[2]);
  850. printf("%s set to \"%s\".\r\n", ct->name, (char *)ct->charp);
  851. } else {
  852. if (strcmp("off", argv[2])) {
  853. value = special(argv[2]);
  854. } else {
  855. value = _POSIX_VDISABLE;
  856. }
  857. *(ct->charp) = (cc_t)value;
  858. printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp)));
  859. }
  860. slc_check();
  861. return 1;
  862. }
  863. static int
  864. unsetcmd(int argc, char *argv[])
  865. {
  866. struct setlist *ct;
  867. struct togglelist *c;
  868. char *name;
  869. if (argc < 2) {
  870. fprintf(stderr,
  871. "Need an argument to 'unset' command. 'unset ?' for help.\r\n");
  872. return 0;
  873. }
  874. if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
  875. for (ct = Setlist; ct->name; ct++)
  876. printf("%-15s %s\r\n", ct->name, ct->help);
  877. printf("\r\n");
  878. settogglehelp(0);
  879. printf("%-15s %s\r\n", "?", "display help information");
  880. return 0;
  881. }
  882. argc--;
  883. argv++;
  884. while (argc--) {
  885. name = *argv++;
  886. ct = getset(name);
  887. if (ct == 0) {
  888. c = GETTOGGLE(name);
  889. if (c == 0) {
  890. fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\r\n",
  891. name);
  892. return 0;
  893. } else if (Ambiguous(c)) {
  894. fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\r\n",
  895. name);
  896. return 0;
  897. }
  898. if (c->variable) {
  899. *c->variable = 0;
  900. if (c->actionexplanation) {
  901. printf("%s %s.\r\n", *c->variable? "Will" : "Won't",
  902. c->actionexplanation);
  903. }
  904. }
  905. if (c->handler)
  906. (*c->handler)(0);
  907. } else if (Ambiguous(ct)) {
  908. fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\r\n",
  909. name);
  910. return 0;
  911. } else if (ct->handler) {
  912. (*ct->handler)(0);
  913. printf("%s reset to \"%s\".\r\n", ct->name, (char *)ct->charp);
  914. } else {
  915. *(ct->charp) = _POSIX_VDISABLE;
  916. printf("%s character is '%s'.\r\n", ct->name, control(*(ct->charp)));
  917. }
  918. }
  919. return 1;
  920. }
  921. /*
  922. * The following are the data structures and routines for the
  923. * 'mode' command.
  924. */
  925. #ifdef KLUDGELINEMODE
  926. static int
  927. dokludgemode(void)
  928. {
  929. kludgelinemode = 1;
  930. send_wont(TELOPT_LINEMODE, 1);
  931. send_dont(TELOPT_SGA, 1);
  932. send_dont(TELOPT_ECHO, 1);
  933. return 1;
  934. }
  935. #endif
  936. static int
  937. dolinemode()
  938. {
  939. #ifdef KLUDGELINEMODE
  940. if (kludgelinemode)
  941. send_dont(TELOPT_SGA, 1);
  942. #endif
  943. send_will(TELOPT_LINEMODE, 1);
  944. send_dont(TELOPT_ECHO, 1);
  945. return 1;
  946. }
  947. static int
  948. docharmode()
  949. {
  950. #ifdef KLUDGELINEMODE
  951. if (kludgelinemode)
  952. send_do(TELOPT_SGA, 1);
  953. else
  954. #endif
  955. send_wont(TELOPT_LINEMODE, 1);
  956. send_do(TELOPT_ECHO, 1);
  957. return 1;
  958. }
  959. static int
  960. dolmmode(int bit, int on)
  961. {
  962. unsigned char c;
  963. if (my_want_state_is_wont(TELOPT_LINEMODE)) {
  964. printf("?Need to have LINEMODE option enabled first.\r\n");
  965. printf("'mode ?' for help.\r\n");
  966. return 0;
  967. }
  968. if (on)
  969. c = (linemode | bit);
  970. else
  971. c = (linemode & ~bit);
  972. lm_mode(&c, 1, 1);
  973. return 1;
  974. }
  975. static int
  976. tn_setmode(int bit)
  977. {
  978. return dolmmode(bit, 1);
  979. }
  980. static int
  981. tn_clearmode(int bit)
  982. {
  983. return dolmmode(bit, 0);
  984. }
  985. struct modelist {
  986. char *name; /* command name */
  987. char *help; /* help string */
  988. int (*handler)(); /* routine which executes command */
  989. int needconnect; /* Do we need to be connected to execute? */
  990. int arg1;
  991. };
  992. static int modehelp(void);
  993. static struct modelist ModeList[] = {
  994. { "character", "Disable LINEMODE option", docharmode, 1 },
  995. #ifdef KLUDGELINEMODE
  996. { "", "(or disable obsolete line-by-line mode)", 0 },
  997. #endif
  998. { "line", "Enable LINEMODE option", dolinemode, 1 },
  999. #ifdef KLUDGELINEMODE
  1000. { "", "(or enable obsolete line-by-line mode)", 0 },
  1001. #endif
  1002. { "", "", 0 },
  1003. { "", "These require the LINEMODE option to be enabled", 0 },
  1004. { "isig", "Enable signal trapping", tn_setmode, 1, MODE_TRAPSIG },
  1005. { "+isig", 0, tn_setmode, 1, MODE_TRAPSIG },
  1006. { "-isig", "Disable signal trapping", tn_clearmode, 1, MODE_TRAPSIG },
  1007. { "edit", "Enable character editing", tn_setmode, 1, MODE_EDIT },
  1008. { "+edit", 0, tn_setmode, 1, MODE_EDIT },
  1009. { "-edit", "Disable character editing", tn_clearmode, 1, MODE_EDIT },
  1010. { "softtabs", "Enable tab expansion", tn_setmode, 1, MODE_SOFT_TAB },
  1011. { "+softtabs", 0, tn_setmode, 1, MODE_SOFT_TAB },
  1012. { "-softtabs", "Disable tab expansion", tn_clearmode, 1, MODE_SOFT_TAB },
  1013. { "litecho", "Enable literal character echo", tn_setmode, 1, MODE_LIT_ECHO },
  1014. { "+litecho", 0, tn_setmode, 1, MODE_LIT_ECHO },
  1015. { "-litecho", "Disable literal character echo", tn_clearmode, 1, MODE_LIT_ECHO },
  1016. { "help", 0, modehelp, 0 },
  1017. #ifdef KLUDGELINEMODE
  1018. { "kludgeline", 0, dokludgemode, 1 },
  1019. #endif
  1020. { "", "", 0 },
  1021. { "?", "Print help information", modehelp, 0 },
  1022. { 0 },
  1023. };
  1024. static int
  1025. modehelp(void)
  1026. {
  1027. struct modelist *mt;
  1028. printf("format is: 'mode Mode', where 'Mode' is one of:\r\n\r\n");
  1029. for (mt = ModeList; mt->name; mt++) {
  1030. if (mt->help) {
  1031. if (*mt->help)
  1032. printf("%-15s %s\r\n", mt->name, mt->help);
  1033. else
  1034. printf("\r\n");
  1035. }
  1036. }
  1037. return 0;
  1038. }
  1039. #define GETMODECMD(name) (struct modelist *) \
  1040. genget(name, (char **) ModeList, sizeof(struct modelist))
  1041. static int
  1042. modecmd(int argc, char **argv)
  1043. {
  1044. struct modelist *mt;
  1045. if (argc != 2) {
  1046. printf("'mode' command requires an argument\r\n");
  1047. printf("'mode ?' for help.\r\n");
  1048. } else if ((mt = GETMODECMD(argv[1])) == 0) {
  1049. fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\r\n", argv[1]);
  1050. } else if (Ambiguous(mt)) {
  1051. fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\r\n", argv[1]);
  1052. } else if (mt->needconnect && !connected) {
  1053. printf("?Need to be connected first.\r\n");
  1054. printf("'mode ?' for help.\r\n");
  1055. } else if (mt->handler) {
  1056. return (*mt->handler)(mt->arg1);
  1057. }
  1058. return 0;
  1059. }
  1060. /*
  1061. * The following data structures and routines implement the
  1062. * "display" command.
  1063. */
  1064. static int
  1065. display(int argc, char *argv[])
  1066. {
  1067. struct togglelist *tl;
  1068. struct setlist *sl;
  1069. #define dotog(tl) if (tl->variable && tl->actionexplanation) { \
  1070. if (*tl->variable) { \
  1071. printf("will"); \
  1072. } else { \
  1073. printf("won't"); \
  1074. } \
  1075. printf(" %s.\r\n", tl->actionexplanation); \
  1076. }
  1077. #define doset(sl) if (sl->name && *sl->name != ' ') { \
  1078. if (sl->handler == 0) \
  1079. printf("%-15s [%s]\r\n", sl->name, control(*sl->charp)); \
  1080. else \
  1081. printf("%-15s \"%s\"\r\n", sl->name, (char *)sl->charp); \
  1082. }
  1083. if (argc == 1) {
  1084. for (tl = Togglelist; tl->name; tl++) {
  1085. dotog(tl);
  1086. }
  1087. printf("\r\n");
  1088. for (sl = Setlist; sl->name; sl++) {
  1089. doset(sl);
  1090. }
  1091. } else {
  1092. int i;
  1093. for (i = 1; i < argc; i++) {
  1094. sl = getset(argv[i]);
  1095. tl = GETTOGGLE(argv[i]);
  1096. if (Ambiguous(sl) || Ambiguous(tl)) {
  1097. printf("?Ambiguous argument '%s'.\r\n", argv[i]);
  1098. return 0;
  1099. } else if (!sl && !tl) {
  1100. printf("?Unknown argument '%s'.\r\n", argv[i]);
  1101. return 0;
  1102. } else {
  1103. if (tl) {
  1104. dotog(tl);
  1105. }
  1106. if (sl) {
  1107. doset(sl);
  1108. }
  1109. }
  1110. }
  1111. }
  1112. /*@*/optionstatus();
  1113. #if defined(ENCRYPTION)
  1114. EncryptStatus();
  1115. #endif
  1116. return 1;
  1117. #undef doset
  1118. #undef dotog
  1119. }
  1120. /*
  1121. * The following are the data structures, and many of the routines,
  1122. * relating to command processing.
  1123. */
  1124. /*
  1125. * Set the escape character.
  1126. */
  1127. static int
  1128. setescape(int argc, char *argv[])
  1129. {
  1130. char *arg;
  1131. char buf[50];
  1132. printf(
  1133. "Deprecated usage - please use 'set escape%s%s' in the future.\r\n",
  1134. (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
  1135. if (argc > 2)
  1136. arg = argv[1];
  1137. else {
  1138. printf("new escape character: ");
  1139. fgets(buf, sizeof(buf), stdin);
  1140. arg = buf;
  1141. }
  1142. if (arg[0] != '\0')
  1143. escape = arg[0];
  1144. printf("Escape character is '%s'.\r\n", control(escape));
  1145. fflush(stdout);
  1146. return 1;
  1147. }
  1148. static int
  1149. togcrmod()
  1150. {
  1151. crmod = !crmod;
  1152. printf("Deprecated usage - please use 'toggle crmod' in the future.\r\n");
  1153. printf("%s map carriage return on output.\r\n", crmod ? "Will" : "Won't");
  1154. fflush(stdout);
  1155. return 1;
  1156. }
  1157. static int
  1158. telnetsuspend()
  1159. {
  1160. #ifdef SIGTSTP
  1161. setcommandmode();
  1162. {
  1163. long oldrows, oldcols, newrows, newcols, err;
  1164. err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
  1165. kill(0, SIGTSTP);
  1166. /*
  1167. * If we didn't get the window size before the SUSPEND, but we
  1168. * can get them now (?), then send the NAWS to make sure that
  1169. * we are set up for the right window size.
  1170. */
  1171. if (TerminalWindowSize(&newrows, &newcols) && connected &&
  1172. (err || ((oldrows != newrows) || (oldcols != newcols)))) {
  1173. sendnaws();
  1174. }
  1175. }
  1176. /* reget parameters in case they were changed */
  1177. TerminalSaveState();
  1178. setconnmode(0);
  1179. #else
  1180. printf("Suspend is not supported. Try the '!' command instead\r\n");
  1181. #endif
  1182. return 1;
  1183. }
  1184. static int
  1185. shell(int argc, char **argv)
  1186. {
  1187. long oldrows, oldcols, newrows, newcols, err;
  1188. setcommandmode();
  1189. err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
  1190. switch(fork()) {
  1191. case -1:
  1192. perror("Fork failed\r\n");
  1193. break;
  1194. case 0:
  1195. {
  1196. /*
  1197. * Fire up the shell in the child.
  1198. */
  1199. char *shellp, *shellname;
  1200. shellp = getenv("SHELL");
  1201. if (shellp == NULL)
  1202. shellp = "/bin/sh";
  1203. if ((shellname = strrchr(shellp, '/')) == 0)
  1204. shellname = shellp;
  1205. else
  1206. shellname++;
  1207. if (argc > 1)
  1208. execl(shellp, shellname, "-c", &saveline[1], NULL);
  1209. else
  1210. execl(shellp, shellname, NULL);
  1211. perror("Execl");
  1212. _exit(1);
  1213. }
  1214. default:
  1215. wait((int *)0); /* Wait for the shell to complete */
  1216. if (TerminalWindowSize(&newrows, &newcols) && connected &&
  1217. (err || ((oldrows != newrows) || (oldcols != newcols)))) {
  1218. sendnaws();
  1219. }
  1220. break;
  1221. }
  1222. return 1;
  1223. }
  1224. static int
  1225. bye(int argc, char **argv)
  1226. {
  1227. if (connected) {
  1228. shutdown(net, 2);
  1229. printf("Connection closed.\r\n");
  1230. NetClose(net);
  1231. connected = 0;
  1232. resettermname = 1;
  1233. #if defined(AUTHENTICATION) || defined(ENCRYPTION)
  1234. auth_encrypt_connect(connected);
  1235. #endif
  1236. /* reset options */
  1237. tninit();
  1238. }
  1239. if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0))
  1240. longjmp(toplevel, 1);
  1241. return 0; /* NOTREACHED */
  1242. }
  1243. int
  1244. quit(void)
  1245. {
  1246. call(bye, "bye", "fromquit", 0);
  1247. Exit(0);
  1248. return 0; /*NOTREACHED*/
  1249. }
  1250. static int
  1251. logout()
  1252. {
  1253. send_do(TELOPT_LOGOUT, 1);
  1254. netflush();
  1255. return 1;
  1256. }
  1257. /*
  1258. * The SLC command.
  1259. */
  1260. struct slclist {
  1261. char *name;
  1262. char *help;
  1263. void (*handler)();
  1264. int arg;
  1265. };
  1266. static void slc_help(void);
  1267. struct slclist SlcList[] = {
  1268. { "export", "Use local special character definitions",
  1269. slc_mode_export, 0 },
  1270. { "import", "Use remote special character definitions",
  1271. slc_mode_import, 1 },
  1272. { "check", "Verify remote special character definitions",
  1273. slc_mode_import, 0 },
  1274. { "help", 0, slc_help, 0 },
  1275. { "?", "Print help information", slc_help, 0 },
  1276. { 0 },
  1277. };
  1278. static void
  1279. slc_help(void)
  1280. {
  1281. struct slclist *c;
  1282. for (c = SlcList; c->name; c++) {
  1283. if (c->help) {
  1284. if (*c->help)
  1285. printf("%-15s %s\r\n", c->name, c->help);
  1286. else
  1287. printf("\r\n");
  1288. }
  1289. }
  1290. }
  1291. static struct slclist *
  1292. getslc(char *name)
  1293. {
  1294. return (struct slclist *)
  1295. genget(name, (char **) SlcList, sizeof(struct slclist));
  1296. }
  1297. static int
  1298. slccmd(int argc, char **argv)
  1299. {
  1300. struct slclist *c;
  1301. if (argc != 2) {
  1302. fprintf(stderr,
  1303. "Need an argument to 'slc' command. 'slc ?' for help.\r\n");
  1304. return 0;
  1305. }
  1306. c = getslc(argv[1]);
  1307. if (c == 0) {
  1308. fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\r\n",
  1309. argv[1]);
  1310. return 0;
  1311. }
  1312. if (Ambiguous(c)) {
  1313. fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\r\n",
  1314. argv[1]);
  1315. return 0;
  1316. }
  1317. (*c->handler)(c->arg);
  1318. slcstate();
  1319. return 1;
  1320. }
  1321. /*
  1322. * The ENVIRON command.
  1323. */
  1324. struct envlist {
  1325. char *name;
  1326. char *help;
  1327. void (*handler)();
  1328. int narg;
  1329. };
  1330. static void env_help (void);
  1331. struct envlist EnvList[] = {
  1332. { "define", "Define an environment variable",
  1333. (void (*)())env_define, 2 },
  1334. { "undefine", "Undefine an environment variable",
  1335. env_undefine, 1 },
  1336. { "export", "Mark an environment variable for automatic export",
  1337. env_export, 1 },
  1338. { "unexport", "Don't mark an environment variable for automatic export",
  1339. env_unexport, 1 },
  1340. { "send", "Send an environment variable", env_send, 1 },
  1341. { "list", "List the current environment variables",
  1342. env_list, 0 },
  1343. { "help", 0, env_help, 0 },
  1344. { "?", "Print help information", env_help, 0 },
  1345. { 0 },
  1346. };
  1347. static void
  1348. env_help()
  1349. {
  1350. struct envlist *c;
  1351. for (c = EnvList; c->name; c++) {
  1352. if (c->help) {
  1353. if (*c->help)
  1354. printf("%-15s %s\r\n", c->name, c->help);
  1355. else
  1356. printf("\r\n");
  1357. }
  1358. }
  1359. }
  1360. static struct envlist *
  1361. getenvcmd(char *name)
  1362. {
  1363. return (struct envlist *)
  1364. genget(name, (char **) EnvList, sizeof(struct envlist));
  1365. }
  1366. static int
  1367. env_cmd(int argc, char **argv)
  1368. {
  1369. struct envlist *c;
  1370. if (argc < 2) {
  1371. fprintf(stderr,
  1372. "Need an argument to 'environ' command. 'environ ?' for help.\r\n");
  1373. return 0;
  1374. }
  1375. c = getenvcmd(argv[1]);
  1376. if (c == 0) {
  1377. fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\r\n",
  1378. argv[1]);
  1379. return 0;
  1380. }
  1381. if (Ambiguous(c)) {
  1382. fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\r\n",
  1383. argv[1]);
  1384. return 0;
  1385. }
  1386. if (c->narg + 2 != argc) {
  1387. fprintf(stderr,
  1388. "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\r\n",
  1389. c->narg < argc + 2 ? "only " : "",
  1390. c->narg, c->narg == 1 ? "" : "s", c->name);
  1391. return 0;
  1392. }
  1393. (*c->handler)(argv[2], argv[3]);
  1394. return 1;
  1395. }
  1396. struct env_lst {
  1397. struct env_lst *next; /* pointer to next structure */
  1398. struct env_lst *prev; /* pointer to previous structure */
  1399. unsigned char *var; /* pointer to variable name */
  1400. unsigned char *value; /* pointer to variable value */
  1401. int export; /* 1 -> export with default list of variables */
  1402. int welldefined; /* A well defined variable */
  1403. };
  1404. struct env_lst envlisthead;
  1405. struct env_lst *
  1406. env_find(unsigned char *var)
  1407. {
  1408. struct env_lst *ep;
  1409. for (ep = envlisthead.next; ep; ep = ep->next) {
  1410. if (strcmp((char *)ep->var, (char *)var) == 0)
  1411. return(ep);
  1412. }
  1413. return(NULL);
  1414. }
  1415. #ifdef IRIX4
  1416. #define environ _environ
  1417. #endif
  1418. void
  1419. env_init(void)
  1420. {
  1421. char **epp, *cp;
  1422. struct env_lst *ep;
  1423. for (epp = environ; *epp; epp++) {
  1424. if ((cp = strchr(*epp, '='))) {
  1425. *cp = '\0';
  1426. ep = env_define((unsigned char *)*epp,
  1427. (unsigned char *)cp+1);
  1428. ep->export = 0;
  1429. *cp = '=';
  1430. }
  1431. }
  1432. /*
  1433. * Special case for DISPLAY variable. If it is ":0.0" or
  1434. * "unix:0.0", we have to get rid of "unix" and insert our
  1435. * hostname.
  1436. */
  1437. if ((ep = env_find((unsigned char*)"DISPLAY"))
  1438. && (*ep->value == ':'
  1439. || strncmp((char *)ep->value, "unix:", 5) == 0)) {
  1440. char hbuf[256+1];
  1441. char *cp2 = strchr((char *)ep->value, ':');
  1442. int error;
  1443. /* XXX - should be k_gethostname? */
  1444. gethostname(hbuf, 256);
  1445. hbuf[256] = '\0';
  1446. /* If this is not the full name, try to get it via DNS */
  1447. if (strchr(hbuf, '.') == 0) {
  1448. struct addrinfo hints, *ai, *a;
  1449. memset (&hints, 0, sizeof(hints));
  1450. hints.ai_flags = AI_CANONNAME;
  1451. error = getaddrinfo (hbuf, NULL, &hints, &ai);
  1452. if (error == 0) {
  1453. for (a = ai; a != NULL; a = a->ai_next)
  1454. if (a->ai_canonname != NULL) {
  1455. strlcpy (hbuf,
  1456. ai->ai_canonname,
  1457. 256);
  1458. break;
  1459. }
  1460. freeaddrinfo (ai);
  1461. }
  1462. }
  1463. error = asprintf (&cp, "%s%s", hbuf, cp2);
  1464. if (error != -1) {
  1465. free (ep->value);
  1466. ep->value = (unsigned char *)cp;
  1467. }
  1468. }
  1469. /*
  1470. * If USER is not defined, but LOGNAME is, then add
  1471. * USER with the value from LOGNAME. By default, we
  1472. * don't export the USER variable.
  1473. */
  1474. if ((env_find((unsigned char*)"USER") == NULL) &&
  1475. (ep = env_find((unsigned char*)"LOGNAME"))) {
  1476. env_define((unsigned char *)"USER", ep->value);
  1477. env_unexport((unsigned char *)"USER");
  1478. }
  1479. env_export((unsigned char *)"DISPLAY");
  1480. env_export((unsigned char *)"PRINTER");
  1481. env_export((unsigned char *)"XAUTHORITY");
  1482. }
  1483. struct env_lst *
  1484. env_define(unsigned char *var, unsigned char *value)
  1485. {
  1486. struct env_lst *ep;
  1487. if ((ep = env_find(var))) {
  1488. if (ep->var)
  1489. free(ep->var);
  1490. if (ep->value)
  1491. free(ep->value);
  1492. } else {
  1493. ep = (struct env_lst *)malloc(sizeof(struct env_lst));
  1494. ep->next = envlisthead.next;
  1495. envlisthead.next = ep;
  1496. ep->prev = &envlisthead;
  1497. if (ep->next)
  1498. ep->next->prev = ep;
  1499. }
  1500. ep->welldefined = opt_welldefined((char *)var);
  1501. ep->export = 1;
  1502. ep->var = (unsigned char *)strdup((char *)var);
  1503. ep->value = (unsigned char *)strdup((char *)value);
  1504. return(ep);
  1505. }
  1506. void
  1507. env_undefine(unsigned char *var)
  1508. {
  1509. struct env_lst *ep;
  1510. if ((ep = env_find(var))) {
  1511. ep->prev->next = ep->next;
  1512. if (ep->next)
  1513. ep->next->prev = ep->prev;
  1514. if (ep->var)
  1515. free(ep->var);
  1516. if (ep->value)
  1517. free(ep->value);
  1518. free(ep);
  1519. }
  1520. }
  1521. void
  1522. env_export(unsigned char *var)
  1523. {
  1524. struct env_lst *ep;
  1525. if ((ep = env_find(var)))
  1526. ep->export = 1;
  1527. }
  1528. void
  1529. env_unexport(unsigned char *var)
  1530. {
  1531. struct env_lst *ep;
  1532. if ((ep = env_find(var)))
  1533. ep->export = 0;
  1534. }
  1535. void
  1536. env_send(unsigned char *var)
  1537. {
  1538. struct env_lst *ep;
  1539. if (my_state_is_wont(TELOPT_NEW_ENVIRON)
  1540. #ifdef OLD_ENVIRON
  1541. && my_state_is_wont(TELOPT_OLD_ENVIRON)
  1542. #endif
  1543. ) {
  1544. fprintf(stderr,
  1545. "Cannot send '%s': Telnet ENVIRON option not enabled\r\n",
  1546. var);
  1547. return;
  1548. }
  1549. ep = env_find(var);
  1550. if (ep == 0) {
  1551. fprintf(stderr, "Cannot send '%s': variable not defined\r\n",
  1552. var);
  1553. return;
  1554. }
  1555. env_opt_start_info();
  1556. env_opt_add(ep->var);
  1557. env_opt_end(0);
  1558. }
  1559. void
  1560. env_list(void)
  1561. {
  1562. struct env_lst *ep;
  1563. for (ep = envlisthead.next; ep; ep = ep->next) {
  1564. printf("%c %-20s %s\r\n", ep->export ? '*' : ' ',
  1565. ep->var, ep->value);
  1566. }
  1567. }
  1568. unsigned char *
  1569. env_default(int init, int welldefined)
  1570. {
  1571. static struct env_lst *nep = NULL;
  1572. if (init) {
  1573. nep = &envlisthead;
  1574. return NULL;
  1575. }
  1576. if (nep) {
  1577. while ((nep = nep->next)) {
  1578. if (nep->export && (nep->welldefined == welldefined))
  1579. return(nep->var);
  1580. }
  1581. }
  1582. return(NULL);
  1583. }
  1584. unsigned char *
  1585. env_getvalue(unsigned char *var)
  1586. {
  1587. struct env_lst *ep;
  1588. if ((ep = env_find(var)))
  1589. return(ep->value);
  1590. return(NULL);
  1591. }
  1592. #if defined(AUTHENTICATION)
  1593. /*
  1594. * The AUTHENTICATE command.
  1595. */
  1596. struct authlist {
  1597. char *name;
  1598. char *help;
  1599. int (*handler)();
  1600. int narg;
  1601. };
  1602. static int
  1603. auth_help (void);
  1604. struct authlist AuthList[] = {
  1605. { "status", "Display current status of authentication information",
  1606. auth_status, 0 },
  1607. { "disable", "Disable an authentication type ('auth disable ?' for more)",
  1608. auth_disable, 1 },
  1609. { "enable", "Enable an authentication type ('auth enable ?' for more)",
  1610. auth_enable, 1 },
  1611. { "help", 0, auth_help, 0 },
  1612. { "?", "Print help information", auth_help, 0 },
  1613. { 0 },
  1614. };
  1615. static int
  1616. auth_help()
  1617. {
  1618. struct authlist *c;
  1619. for (c = AuthList; c->name; c++) {
  1620. if (c->help) {
  1621. if (*c->help)
  1622. printf("%-15s %s\r\n", c->name, c->help);
  1623. else
  1624. printf("\r\n");
  1625. }
  1626. }
  1627. return 0;
  1628. }
  1629. static int
  1630. auth_cmd(int argc, char **argv)
  1631. {
  1632. struct authlist *c;
  1633. if (argc < 2) {
  1634. fprintf(stderr,
  1635. "Need an argument to 'auth' command. 'auth ?' for help.\r\n");
  1636. return 0;
  1637. }
  1638. c = (struct authlist *)
  1639. genget(argv[1], (char **) AuthList, sizeof(struct authlist));
  1640. if (c == 0) {
  1641. fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\r\n",
  1642. argv[1]);
  1643. return 0;
  1644. }
  1645. if (Ambiguous(c)) {
  1646. fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\r\n",
  1647. argv[1]);
  1648. return 0;
  1649. }
  1650. if (c->narg + 2 != argc) {
  1651. fprintf(stderr,
  1652. "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\r\n",
  1653. c->narg < argc + 2 ? "only " : "",
  1654. c->narg, c->narg == 1 ? "" : "s", c->name);
  1655. return 0;
  1656. }
  1657. return((*c->handler)(argv[2], argv[3]));
  1658. }
  1659. #endif
  1660. #if defined(ENCRYPTION)
  1661. /*
  1662. * The ENCRYPT command.
  1663. */
  1664. struct encryptlist {
  1665. char *name;
  1666. char *help;
  1667. int (*handler)();
  1668. int needconnect;
  1669. int minarg;
  1670. int maxarg;
  1671. };
  1672. static int
  1673. EncryptHelp (void);
  1674. struct encryptlist EncryptList[] = {
  1675. { "enable", "Enable encryption. ('encrypt enable ?' for more)",
  1676. EncryptEnable, 1, 1, 2 },
  1677. { "disable", "Disable encryption. ('encrypt enable ?' for more)",
  1678. EncryptDisable, 0, 1, 2 },
  1679. { "type", "Set encryptiong type. ('encrypt type ?' for more)",
  1680. EncryptType, 0, 1, 1 },
  1681. { "start", "Start encryption. ('encrypt start ?' for more)",
  1682. EncryptStart, 1, 0, 1 },
  1683. { "stop", "Stop encryption. ('encrypt stop ?' for more)",
  1684. EncryptStop, 1, 0, 1 },
  1685. { "input", "Start encrypting the input stream",
  1686. EncryptStartInput, 1, 0, 0 },
  1687. { "-input", "Stop encrypting the input stream",
  1688. EncryptStopInput, 1, 0, 0 },
  1689. { "output", "Start encrypting the output stream",
  1690. EncryptStartOutput, 1, 0, 0 },
  1691. { "-output", "Stop encrypting the output stream",
  1692. EncryptStopOutput, 1, 0, 0 },
  1693. { "status", "Display current status of authentication information",
  1694. EncryptStatus, 0, 0, 0 },
  1695. { "help", 0, EncryptHelp, 0, 0, 0 },
  1696. { "?", "Print help information", EncryptHelp, 0, 0, 0 },
  1697. { 0 },
  1698. };
  1699. static int
  1700. EncryptHelp()
  1701. {
  1702. struct encryptlist *c;
  1703. for (c = EncryptList; c->name; c++) {
  1704. if (c->help) {
  1705. if (*c->help)
  1706. printf("%-15s %s\r\n", c->name, c->help);
  1707. else
  1708. printf("\r\n");
  1709. }
  1710. }
  1711. return 0;
  1712. }
  1713. static int
  1714. encrypt_cmd(int argc, char **argv)
  1715. {
  1716. struct encryptlist *c;
  1717. c = (struct encryptlist *)
  1718. genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
  1719. if (c == 0) {
  1720. fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\r\n",
  1721. argv[1]);
  1722. return 0;
  1723. }
  1724. if (Ambiguous(c)) {
  1725. fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\r\n",
  1726. argv[1]);
  1727. return 0;
  1728. }
  1729. argc -= 2;
  1730. if (argc < c->minarg || argc > c->maxarg) {
  1731. if (c->minarg == c->maxarg) {
  1732. fprintf(stderr, "Need %s%d argument%s ",
  1733. c->minarg < argc ? "only " : "", c->minarg,
  1734. c->minarg == 1 ? "" : "s");
  1735. } else {
  1736. fprintf(stderr, "Need %s%d-%d arguments ",
  1737. c->maxarg < argc ? "only " : "", c->minarg, c->maxarg);
  1738. }
  1739. fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\r\n",
  1740. c->name);
  1741. return 0;
  1742. }
  1743. if (c->needconnect && !connected) {
  1744. if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) {
  1745. printf("?Need to be connected first.\r\n");
  1746. return 0;
  1747. }
  1748. }
  1749. return ((*c->handler)(argc > 0 ? argv[2] : 0,
  1750. argc > 1 ? argv[3] : 0,
  1751. argc > 2 ? argv[4] : 0));
  1752. }
  1753. #endif
  1754. /*
  1755. * Print status about the connection.
  1756. */
  1757. static int
  1758. status(int argc, char **argv)
  1759. {
  1760. if (connected) {
  1761. printf("Connected to %s.\r\n", hostname);
  1762. if ((argc < 2) || strcmp(argv[1], "notmuch")) {
  1763. int mode = getconnmode();
  1764. if (my_want_state_is_will(TELOPT_LINEMODE)) {
  1765. printf("Operating with LINEMODE option\r\n");
  1766. printf("%s line editing\r\n", (mode&MODE_EDIT) ? "Local" : "No");
  1767. printf("%s catching of signals\r\n",
  1768. (mode&MODE_TRAPSIG) ? "Local" : "No");
  1769. slcstate();
  1770. #ifdef KLUDGELINEMODE
  1771. } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
  1772. printf("Operating in obsolete linemode\r\n");
  1773. #endif
  1774. } else {
  1775. printf("Operating in single character mode\r\n");
  1776. if (localchars)
  1777. printf("Catching signals locally\r\n");
  1778. }
  1779. printf("%s character echo\r\n", (mode&MODE_ECHO) ? "Local" : "Remote");
  1780. if (my_want_state_is_will(TELOPT_LFLOW))
  1781. printf("%s flow control\r\n", (mode&MODE_FLOW) ? "Local" : "No");
  1782. #if defined(ENCRYPTION)
  1783. encrypt_display();
  1784. #endif
  1785. }
  1786. } else {
  1787. printf("No connection.\r\n");
  1788. }
  1789. printf("Escape character is '%s'.\r\n", control(escape));
  1790. fflush(stdout);
  1791. return 1;
  1792. }
  1793. #ifdef SIGINFO
  1794. /*
  1795. * Function that gets called when SIGINFO is received.
  1796. */
  1797. RETSIGTYPE
  1798. ayt_status(int ignore)
  1799. {
  1800. call(status, "status", "notmuch", 0);
  1801. }
  1802. #endif
  1803. static Command *getcmd(char *name);
  1804. static void
  1805. cmdrc(char *m1, char *m2)
  1806. {
  1807. static char rcname[128];
  1808. Command *c;
  1809. FILE *rcfile;
  1810. int gotmachine = 0;
  1811. int l1 = strlen(m1);
  1812. int l2 = strlen(m2);
  1813. char m1save[64];
  1814. if (skiprc)
  1815. return;
  1816. strlcpy(m1save, m1, sizeof(m1save));
  1817. m1 = m1save;
  1818. if (rcname[0] == 0) {
  1819. char *home = getenv("HOME");
  1820. snprintf (rcname, sizeof(rcname), "%s/.telnetrc",
  1821. home ? home : "");
  1822. }
  1823. if ((rcfile = fopen(rcname, "r")) == 0) {
  1824. return;
  1825. }
  1826. for (;;) {
  1827. if (fgets(line, sizeof(line), rcfile) == NULL)
  1828. break;
  1829. if (line[0] == 0)
  1830. break;
  1831. if (line[0] == '#')
  1832. continue;
  1833. if (gotmachine) {
  1834. if (!isspace((unsigned char)line[0]))
  1835. gotmachine = 0;
  1836. }
  1837. if (gotmachine == 0) {
  1838. if (isspace((unsigned char)line[0]))
  1839. continue;
  1840. if (strncasecmp(line, m1, l1) == 0)
  1841. strncpy(line, &line[l1], sizeof(line) - l1);
  1842. else if (strncasecmp(line, m2, l2) == 0)
  1843. strncpy(line, &line[l2], sizeof(line) - l2);
  1844. else if (strncasecmp(line, "DEFAULT", 7) == 0)
  1845. strncpy(line, &line[7], sizeof(line) - 7);
  1846. else
  1847. continue;
  1848. if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
  1849. continue;
  1850. gotmachine = 1;
  1851. }
  1852. makeargv();
  1853. if (margv[0] == 0)
  1854. continue;
  1855. c = getcmd(margv[0]);
  1856. if (Ambiguous(c)) {
  1857. printf("?Ambiguous command: %s\r\n", margv[0]);
  1858. continue;
  1859. }
  1860. if (c == 0) {
  1861. printf("?Invalid command: %s\r\n", margv[0]);
  1862. continue;
  1863. }
  1864. /*
  1865. * This should never happen...
  1866. */
  1867. if (c->needconnect && !connected) {
  1868. printf("?Need to be connected first for %s.\r\n", margv[0]);
  1869. continue;
  1870. }
  1871. (*c->handler)(margc, margv);
  1872. }
  1873. fclose(rcfile);
  1874. }
  1875. int
  1876. tn(int argc, char **argv)
  1877. {
  1878. struct servent *sp = 0;
  1879. char *cmd, *hostp = 0, *portp = 0;
  1880. char *user = 0;
  1881. int port = 0;
  1882. /* clear the socket address prior to use */
  1883. if (connected) {
  1884. printf("?Already connected to %s\r\n", hostname);
  1885. return 0;
  1886. }
  1887. if (argc < 2) {
  1888. strlcpy(line, "open ", sizeof(line));
  1889. printf("(to) ");
  1890. fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
  1891. makeargv();
  1892. argc = margc;
  1893. argv = margv;
  1894. }
  1895. cmd = *argv;
  1896. --argc; ++argv;
  1897. while (argc) {
  1898. if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
  1899. goto usage;
  1900. if (strcmp(*argv, "-l") == 0) {
  1901. --argc; ++argv;
  1902. if (argc == 0)
  1903. goto usage;
  1904. user = strdup(*argv++);
  1905. --argc;
  1906. continue;
  1907. }
  1908. if (strcmp(*argv, "-a") == 0) {
  1909. --argc; ++argv;
  1910. autologin = 1;
  1911. continue;
  1912. }
  1913. if (hostp == 0) {
  1914. hostp = *argv++;
  1915. --argc;
  1916. continue;
  1917. }
  1918. if (portp == 0) {
  1919. portp = *argv++;
  1920. --argc;
  1921. continue;
  1922. }
  1923. usage:
  1924. printf("usage: %s [-l user] [-a] host-name [port]\r\n", cmd);
  1925. return 0;
  1926. }
  1927. if (hostp == 0)
  1928. goto usage;
  1929. strlcpy (_hostname, hostp, sizeof(_hostname));
  1930. hostp = _hostname;
  1931. if (hostp[0] == '@' || hostp[0] == '!') {
  1932. char *p;
  1933. hostname = NULL;
  1934. for (p = hostp + 1; *p; p++) {
  1935. if (*p == ',' || *p == '@')
  1936. hostname = p;
  1937. }
  1938. if (hostname == NULL) {
  1939. fprintf(stderr, "%s: bad source route specification\n", hostp);
  1940. return 0;
  1941. }
  1942. *hostname++ = '\0';
  1943. } else
  1944. hostname = host