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