Annotation of src/usr.bin/telnet/commands.c, Revision 1.4
1.4 ! deraadt 1: /* $OpenBSD: commands.c,v 1.3 1996/03/27 19:32:58 niklas Exp $ */
! 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.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
1.3 niklas 38: #if 0
39: static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
1.4 ! deraadt 40: static char rcsid[] = "$NetBSD: commands.c,v 1.14 1996/03/24 22:03:48 jtk Exp $";
1.3 niklas 41: #else
1.4 ! deraadt 42: static char rcsid[] = "$OpenBSD: commands.c,v 1.3 1996/03/27 19:32:58 niklas Exp $";
1.3 niklas 43: #endif
1.1 deraadt 44: #endif /* not lint */
45:
46: #if defined(unix)
47: #include <sys/param.h>
48: #if defined(CRAY) || defined(sysV88)
49: #include <sys/types.h>
50: #endif
51: #include <sys/file.h>
52: #else
53: #include <sys/types.h>
54: #endif /* defined(unix) */
55: #include <sys/socket.h>
56: #include <netinet/in.h>
57: #ifdef CRAY
58: #include <fcntl.h>
59: #endif /* CRAY */
60:
61: #include <signal.h>
62: #include <netdb.h>
63: #include <ctype.h>
64: #include <pwd.h>
65: #include <varargs.h>
66: #include <errno.h>
67:
68: #include <arpa/telnet.h>
1.3 niklas 69: #include <sys/cdefs.h>
70: #define P __P
1.1 deraadt 71:
72: #include "general.h"
73:
74: #include "ring.h"
75:
76: #include "externs.h"
77: #include "defines.h"
78: #include "types.h"
79:
80: #if !defined(CRAY) && !defined(sysV88)
81: #include <netinet/in_systm.h>
82: # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
83: # include <machine/endian.h>
84: # endif /* vax */
85: #endif /* !defined(CRAY) && !defined(sysV88) */
86: #include <netinet/ip.h>
87:
88:
1.3 niklas 89: #ifndef MAXHOSTNAMELEN
90: #define MAXHOSTNAMELEN 64
91: #endif MAXHOSTNAMELEN
1.1 deraadt 92:
93: #if defined(IPPROTO_IP) && defined(IP_TOS)
94: int tos = -1;
95: #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
96:
97: char *hostname;
98: static char _hostname[MAXHOSTNAMELEN];
99:
100: extern char *getenv();
101:
102: extern int isprefix();
103: extern char **genget();
104: extern int Ambiguous();
105:
106: static call();
107:
108: typedef struct {
109: char *name; /* command name */
110: char *help; /* help string (NULL for no help) */
111: int (*handler)(); /* routine which executes command */
112: int needconnect; /* Do we need to be connected to execute? */
113: } Command;
114:
115: static char line[256];
116: static char saveline[256];
117: static int margc;
118: static char *margv[20];
119:
120: static void
121: makeargv()
122: {
123: register char *cp, *cp2, c;
124: register char **argp = margv;
125:
126: margc = 0;
127: cp = line;
128: if (*cp == '!') { /* Special case shell escape */
129: strcpy(saveline, line); /* save for shell command */
130: *argp++ = "!"; /* No room in string to get this */
131: margc++;
132: cp++;
133: }
134: while (c = *cp) {
135: register int inquote = 0;
136: while (isspace(c))
137: c = *++cp;
138: if (c == '\0')
139: break;
140: *argp++ = cp;
141: margc += 1;
142: for (cp2 = cp; c != '\0'; c = *++cp) {
143: if (inquote) {
144: if (c == inquote) {
145: inquote = 0;
146: continue;
147: }
148: } else {
149: if (c == '\\') {
150: if ((c = *++cp) == '\0')
151: break;
152: } else if (c == '"') {
153: inquote = '"';
154: continue;
155: } else if (c == '\'') {
156: inquote = '\'';
157: continue;
158: } else if (isspace(c))
159: break;
160: }
161: *cp2++ = c;
162: }
163: *cp2 = '\0';
164: if (c == '\0')
165: break;
166: cp++;
167: }
168: *argp++ = 0;
169: }
170:
171: /*
172: * Make a character string into a number.
173: *
174: * Todo: 1. Could take random integers (12, 0x12, 012, 0b1).
175: */
176:
177: static
178: special(s)
179: register char *s;
180: {
181: register char c;
182: char b;
183:
184: switch (*s) {
185: case '^':
186: b = *++s;
187: if (b == '?') {
188: c = b | 0x40; /* DEL */
189: } else {
190: c = b & 0x1f;
191: }
192: break;
193: default:
194: c = *s;
195: break;
196: }
197: return c;
198: }
199:
200: /*
201: * Construct a control character sequence
202: * for a special character.
203: */
204: static char *
205: control(c)
206: register cc_t c;
207: {
208: static char buf[5];
209: /*
210: * The only way I could get the Sun 3.5 compiler
211: * to shut up about
212: * if ((unsigned int)c >= 0x80)
213: * was to assign "c" to an unsigned int variable...
214: * Arggg....
215: */
216: register unsigned int uic = (unsigned int)c;
217:
218: if (uic == 0x7f)
219: return ("^?");
220: if (c == (cc_t)_POSIX_VDISABLE) {
221: return "off";
222: }
223: if (uic >= 0x80) {
224: buf[0] = '\\';
225: buf[1] = ((c>>6)&07) + '0';
226: buf[2] = ((c>>3)&07) + '0';
227: buf[3] = (c&07) + '0';
228: buf[4] = 0;
229: } else if (uic >= 0x20) {
230: buf[0] = c;
231: buf[1] = 0;
232: } else {
233: buf[0] = '^';
234: buf[1] = '@'+c;
235: buf[2] = 0;
236: }
237: return (buf);
238: }
239:
240:
241:
242: /*
243: * The following are data structures and routines for
244: * the "send" command.
245: *
246: */
1.3 niklas 247:
1.1 deraadt 248: struct sendlist {
249: char *name; /* How user refers to it (case independent) */
250: char *help; /* Help information (0 ==> no help) */
251: int needconnect; /* Need to be connected */
252: int narg; /* Number of arguments */
253: int (*handler)(); /* Routine to perform (for special ops) */
254: int nbyte; /* Number of bytes to send this command */
255: int what; /* Character to be sent (<0 ==> special) */
256: };
257:
258:
259: static int
260: send_esc P((void)),
261: send_help P((void)),
262: send_docmd P((char *)),
263: send_dontcmd P((char *)),
264: send_willcmd P((char *)),
265: send_wontcmd P((char *));
266:
267: static struct sendlist Sendlist[] = {
268: { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO },
269: { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT },
270: { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK },
271: { "break", 0, 1, 0, 0, 2, BREAK },
272: { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC },
273: { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL },
274: { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 },
275: { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA },
276: { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP },
277: { "intp", 0, 1, 0, 0, 2, IP },
278: { "interrupt", 0, 1, 0, 0, 2, IP },
279: { "intr", 0, 1, 0, 0, 2, IP },
280: { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP },
281: { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR },
282: { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT },
283: { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP },
284: { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF },
285: { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 },
286: { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 },
287: { "?", "Display send options", 0, 0, send_help, 0, 0 },
288: { "help", 0, 0, 0, send_help, 0, 0 },
289: { "do", 0, 0, 1, send_docmd, 3, 0 },
290: { "dont", 0, 0, 1, send_dontcmd, 3, 0 },
291: { "will", 0, 0, 1, send_willcmd, 3, 0 },
292: { "wont", 0, 0, 1, send_wontcmd, 3, 0 },
293: { 0 }
294: };
295:
296: #define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
297: sizeof(struct sendlist)))
298:
299: static int
300: sendcmd(argc, argv)
301: int argc;
302: char **argv;
303: {
304: int count; /* how many bytes we are going to need to send */
305: int i;
306: int question = 0; /* was at least one argument a question */
307: struct sendlist *s; /* pointer to current command */
308: int success = 0;
309: int needconnect = 0;
310:
311: if (argc < 2) {
312: printf("need at least one argument for 'send' command\n");
313: printf("'send ?' for help\n");
314: return 0;
315: }
316: /*
317: * First, validate all the send arguments.
318: * In addition, we see how much space we are going to need, and
319: * whether or not we will be doing a "SYNCH" operation (which
320: * flushes the network queue).
321: */
322: count = 0;
323: for (i = 1; i < argc; i++) {
324: s = GETSEND(argv[i]);
325: if (s == 0) {
326: printf("Unknown send argument '%s'\n'send ?' for help.\n",
327: argv[i]);
328: return 0;
329: } else if (Ambiguous(s)) {
330: printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
331: argv[i]);
332: return 0;
333: }
334: if (i + s->narg >= argc) {
335: fprintf(stderr,
336: "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n",
337: s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
338: return 0;
339: }
340: count += s->nbyte;
341: if (s->handler == send_help) {
342: send_help();
343: return 0;
344: }
345:
346: i += s->narg;
347: needconnect += s->needconnect;
348: }
349: if (!connected && needconnect) {
350: printf("?Need to be connected first.\n");
351: printf("'send ?' for help\n");
352: return 0;
353: }
354: /* Now, do we have enough room? */
355: if (NETROOM() < count) {
356: printf("There is not enough room in the buffer TO the network\n");
357: printf("to process your request. Nothing will be done.\n");
358: printf("('send synch' will throw away most data in the network\n");
359: printf("buffer, if this might help.)\n");
360: return 0;
361: }
362: /* OK, they are all OK, now go through again and actually send */
363: count = 0;
364: for (i = 1; i < argc; i++) {
365: if ((s = GETSEND(argv[i])) == 0) {
366: fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
367: (void) quit();
368: /*NOTREACHED*/
369: }
370: if (s->handler) {
371: count++;
372: success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0,
373: (s->narg > 1) ? argv[i+2] : 0);
374: i += s->narg;
375: } else {
376: NET2ADD(IAC, s->what);
377: printoption("SENT", IAC, s->what);
378: }
379: }
380: return (count == success);
381: }
382:
383: static int
384: send_esc()
385: {
386: NETADD(escape);
387: return 1;
388: }
389:
390: static int
391: send_docmd(name)
392: char *name;
393: {
394: return(send_tncmd(send_do, "do", name));
395: }
396:
397: static int
398: send_dontcmd(name)
399: char *name;
400: {
401: return(send_tncmd(send_dont, "dont", name));
402: }
403: static int
404: send_willcmd(name)
405: char *name;
406: {
407: return(send_tncmd(send_will, "will", name));
408: }
409: static int
410: send_wontcmd(name)
411: char *name;
412: {
413: return(send_tncmd(send_wont, "wont", name));
414: }
415:
416: int
417: send_tncmd(func, cmd, name)
418: void (*func)();
419: char *cmd, *name;
420: {
421: char **cpp;
422: extern char *telopts[];
423: register int val = 0;
424:
1.3 niklas 425: if (isprefix(name, "?")) {
1.1 deraadt 426: register int col, len;
427:
428: printf("Usage: send %s <value|option>\n", cmd);
429: printf("\"value\" must be from 0 to 255\n");
430: printf("Valid options are:\n\t");
431:
432: col = 8;
433: for (cpp = telopts; *cpp; cpp++) {
434: len = strlen(*cpp) + 3;
435: if (col + len > 65) {
436: printf("\n\t");
437: col = 8;
438: }
439: printf(" \"%s\"", *cpp);
440: col += len;
441: }
442: printf("\n");
443: return 0;
444: }
445: cpp = (char **)genget(name, telopts, sizeof(char *));
446: if (Ambiguous(cpp)) {
447: fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
448: name, cmd);
449: return 0;
450: }
451: if (cpp) {
452: val = cpp - telopts;
453: } else {
454: register char *cp = name;
455:
456: while (*cp >= '0' && *cp <= '9') {
457: val *= 10;
458: val += *cp - '0';
459: cp++;
460: }
461: if (*cp != 0) {
462: fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
463: name, cmd);
464: return 0;
465: } else if (val < 0 || val > 255) {
466: fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
467: name, cmd);
468: return 0;
469: }
470: }
471: if (!connected) {
472: printf("?Need to be connected first.\n");
473: return 0;
474: }
475: (*func)(val, 1);
476: return 1;
477: }
478:
479: static int
480: send_help()
481: {
482: struct sendlist *s; /* pointer to current command */
483: for (s = Sendlist; s->name; s++) {
484: if (s->help)
485: printf("%-15s %s\n", s->name, s->help);
486: }
487: return(0);
488: }
489:
490: /*
491: * The following are the routines and data structures referred
492: * to by the arguments to the "toggle" command.
493: */
494:
495: static int
496: lclchars()
497: {
498: donelclchars = 1;
499: return 1;
500: }
501:
502: static int
503: togdebug()
504: {
505: #ifndef NOT43
506: if (net > 0 &&
507: (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
508: perror("setsockopt (SO_DEBUG)");
509: }
510: #else /* NOT43 */
511: if (debug) {
512: if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0)
513: perror("setsockopt (SO_DEBUG)");
514: } else
515: printf("Cannot turn off socket debugging\n");
516: #endif /* NOT43 */
517: return 1;
518: }
519:
520:
521: static int
522: togcrlf()
523: {
524: if (crlf) {
525: printf("Will send carriage returns as telnet <CR><LF>.\n");
526: } else {
527: printf("Will send carriage returns as telnet <CR><NUL>.\n");
528: }
529: return 1;
530: }
531:
532: int binmode;
533:
534: static int
535: togbinary(val)
536: int val;
537: {
538: donebinarytoggle = 1;
539:
540: if (val >= 0) {
541: binmode = val;
542: } else {
543: if (my_want_state_is_will(TELOPT_BINARY) &&
544: my_want_state_is_do(TELOPT_BINARY)) {
545: binmode = 1;
546: } else if (my_want_state_is_wont(TELOPT_BINARY) &&
547: my_want_state_is_dont(TELOPT_BINARY)) {
548: binmode = 0;
549: }
550: val = binmode ? 0 : 1;
551: }
552:
553: if (val == 1) {
554: if (my_want_state_is_will(TELOPT_BINARY) &&
555: my_want_state_is_do(TELOPT_BINARY)) {
556: printf("Already operating in binary mode with remote host.\n");
557: } else {
558: printf("Negotiating binary mode with remote host.\n");
559: tel_enter_binary(3);
560: }
561: } else {
562: if (my_want_state_is_wont(TELOPT_BINARY) &&
563: my_want_state_is_dont(TELOPT_BINARY)) {
564: printf("Already in network ascii mode with remote host.\n");
565: } else {
566: printf("Negotiating network ascii mode with remote host.\n");
567: tel_leave_binary(3);
568: }
569: }
570: return 1;
571: }
572:
573: static int
574: togrbinary(val)
575: int val;
576: {
577: donebinarytoggle = 1;
578:
579: if (val == -1)
580: val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
581:
582: if (val == 1) {
583: if (my_want_state_is_do(TELOPT_BINARY)) {
584: printf("Already receiving in binary mode.\n");
585: } else {
586: printf("Negotiating binary mode on input.\n");
587: tel_enter_binary(1);
588: }
589: } else {
590: if (my_want_state_is_dont(TELOPT_BINARY)) {
591: printf("Already receiving in network ascii mode.\n");
592: } else {
593: printf("Negotiating network ascii mode on input.\n");
594: tel_leave_binary(1);
595: }
596: }
597: return 1;
598: }
599:
600: static int
601: togxbinary(val)
602: int val;
603: {
604: donebinarytoggle = 1;
605:
606: if (val == -1)
607: val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
608:
609: if (val == 1) {
610: if (my_want_state_is_will(TELOPT_BINARY)) {
611: printf("Already transmitting in binary mode.\n");
612: } else {
613: printf("Negotiating binary mode on output.\n");
614: tel_enter_binary(2);
615: }
616: } else {
617: if (my_want_state_is_wont(TELOPT_BINARY)) {
618: printf("Already transmitting in network ascii mode.\n");
619: } else {
620: printf("Negotiating network ascii mode on output.\n");
621: tel_leave_binary(2);
622: }
623: }
624: return 1;
625: }
626:
627:
628: static int togglehelp P((void));
629: #if defined(AUTHENTICATION)
630: extern int auth_togdebug P((int));
631: #endif
632:
633: struct togglelist {
634: char *name; /* name of toggle */
635: char *help; /* help message */
636: int (*handler)(); /* routine to do actual setting */
637: int *variable;
638: char *actionexplanation;
639: };
640:
641: static struct togglelist Togglelist[] = {
642: { "autoflush",
643: "flushing of output when sending interrupt characters",
644: 0,
645: &autoflush,
646: "flush output when sending interrupt characters" },
647: { "autosynch",
648: "automatic sending of interrupt characters in urgent mode",
649: 0,
650: &autosynch,
651: "send interrupt characters in urgent mode" },
652: #if defined(AUTHENTICATION)
653: { "autologin",
654: "automatic sending of login and/or authentication info",
655: 0,
656: &autologin,
657: "send login name and/or authentication information" },
658: { "authdebug",
659: "Toggle authentication debugging",
660: auth_togdebug,
661: 0,
662: "print authentication debugging information" },
663: #endif
664: { "skiprc",
665: "don't read ~/.telnetrc file",
666: 0,
667: &skiprc,
668: "skip reading of ~/.telnetrc file" },
669: { "binary",
670: "sending and receiving of binary data",
671: togbinary,
672: 0,
673: 0 },
674: { "inbinary",
675: "receiving of binary data",
676: togrbinary,
677: 0,
678: 0 },
679: { "outbinary",
680: "sending of binary data",
681: togxbinary,
682: 0,
683: 0 },
684: { "crlf",
685: "sending carriage returns as telnet <CR><LF>",
686: togcrlf,
687: &crlf,
688: 0 },
689: { "crmod",
690: "mapping of received carriage returns",
691: 0,
692: &crmod,
693: "map carriage return on output" },
694: { "localchars",
695: "local recognition of certain control characters",
696: lclchars,
697: &localchars,
698: "recognize certain control characters" },
699: { " ", "", 0 }, /* empty line */
700: #if defined(unix) && defined(TN3270)
701: { "apitrace",
702: "(debugging) toggle tracing of API transactions",
703: 0,
704: &apitrace,
705: "trace API transactions" },
706: { "cursesdata",
707: "(debugging) toggle printing of hexadecimal curses data",
708: 0,
709: &cursesdata,
710: "print hexadecimal representation of curses data" },
711: #endif /* defined(unix) && defined(TN3270) */
712: { "debug",
713: "debugging",
714: togdebug,
715: &debug,
716: "turn on socket level debugging" },
717: { "netdata",
718: "printing of hexadecimal network data (debugging)",
719: 0,
720: &netdata,
721: "print hexadecimal representation of network traffic" },
722: { "prettydump",
723: "output of \"netdata\" to user readable format (debugging)",
724: 0,
725: &prettydump,
726: "print user readable output for \"netdata\"" },
727: { "options",
728: "viewing of options processing (debugging)",
729: 0,
730: &showoptions,
731: "show option processing" },
732: #if defined(unix)
733: { "termdata",
734: "(debugging) toggle printing of hexadecimal terminal data",
735: 0,
736: &termdata,
737: "print hexadecimal representation of terminal traffic" },
738: #endif /* defined(unix) */
739: { "?",
740: 0,
741: togglehelp },
742: { "help",
743: 0,
744: togglehelp },
745: { 0 }
746: };
747:
748: static int
749: togglehelp()
750: {
751: struct togglelist *c;
752:
753: for (c = Togglelist; c->name; c++) {
754: if (c->help) {
755: if (*c->help)
756: printf("%-15s toggle %s\n", c->name, c->help);
757: else
758: printf("\n");
759: }
760: }
761: printf("\n");
762: printf("%-15s %s\n", "?", "display help information");
763: return 0;
764: }
765:
766: static void
767: settogglehelp(set)
768: int set;
769: {
770: struct togglelist *c;
771:
772: for (c = Togglelist; c->name; c++) {
773: if (c->help) {
774: if (*c->help)
775: printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
776: c->help);
777: else
778: printf("\n");
779: }
780: }
781: }
782:
783: #define GETTOGGLE(name) (struct togglelist *) \
784: genget(name, (char **) Togglelist, sizeof(struct togglelist))
785:
786: static int
787: toggle(argc, argv)
788: int argc;
789: char *argv[];
790: {
791: int retval = 1;
792: char *name;
793: struct togglelist *c;
794:
795: if (argc < 2) {
796: fprintf(stderr,
797: "Need an argument to 'toggle' command. 'toggle ?' for help.\n");
798: return 0;
799: }
800: argc--;
801: argv++;
802: while (argc--) {
803: name = *argv++;
804: c = GETTOGGLE(name);
805: if (Ambiguous(c)) {
806: fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
807: name);
808: return 0;
809: } else if (c == 0) {
810: fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
811: name);
812: return 0;
813: } else {
814: if (c->variable) {
815: *c->variable = !*c->variable; /* invert it */
816: if (c->actionexplanation) {
817: printf("%s %s.\n", *c->variable? "Will" : "Won't",
818: c->actionexplanation);
819: }
820: }
821: if (c->handler) {
822: retval &= (*c->handler)(-1);
823: }
824: }
825: }
826: return retval;
827: }
828:
829: /*
830: * The following perform the "set" command.
831: */
832:
833: #ifdef USE_TERMIO
834: struct termio new_tc = { 0 };
835: #endif
836:
837: struct setlist {
838: char *name; /* name */
839: char *help; /* help information */
840: void (*handler)();
841: cc_t *charp; /* where it is located at */
842: };
843:
844: static struct setlist Setlist[] = {
845: #ifdef KLUDGELINEMODE
846: { "echo", "character to toggle local echoing on/off", 0, &echoc },
847: #endif
848: { "escape", "character to escape back to telnet command mode", 0, &escape },
849: { "rlogin", "rlogin escape character", 0, &rlogin },
850: { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
851: { " ", "" },
852: { " ", "The following need 'localchars' to be toggled true", 0, 0 },
853: { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
854: { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
855: { "quit", "character to cause an Abort process", 0, termQuitCharp },
856: { "eof", "character to cause an EOF ", 0, termEofCharp },
857: { " ", "" },
858: { " ", "The following are for local editing in linemode", 0, 0 },
859: { "erase", "character to use to erase a character", 0, termEraseCharp },
860: { "kill", "character to use to erase a line", 0, termKillCharp },
861: { "lnext", "character to use for literal next", 0, termLiteralNextCharp },
862: { "susp", "character to cause a Suspend Process", 0, termSuspCharp },
863: { "reprint", "character to use for line reprint", 0, termRprntCharp },
864: { "worderase", "character to use to erase a word", 0, termWerasCharp },
865: { "start", "character to use for XON", 0, termStartCharp },
866: { "stop", "character to use for XOFF", 0, termStopCharp },
867: { "forw1", "alternate end of line character", 0, termForw1Charp },
868: { "forw2", "alternate end of line character", 0, termForw2Charp },
869: { "ayt", "alternate AYT character", 0, termAytCharp },
870: { 0 }
871: };
872:
873: #if defined(CRAY) && !defined(__STDC__)
874: /* Work around compiler bug in pcc 4.1.5 */
875: void
876: _setlist_init()
877: {
878: #ifndef KLUDGELINEMODE
879: #define N 5
880: #else
881: #define N 6
882: #endif
883: Setlist[N+0].charp = &termFlushChar;
884: Setlist[N+1].charp = &termIntChar;
885: Setlist[N+2].charp = &termQuitChar;
886: Setlist[N+3].charp = &termEofChar;
887: Setlist[N+6].charp = &termEraseChar;
888: Setlist[N+7].charp = &termKillChar;
889: Setlist[N+8].charp = &termLiteralNextChar;
890: Setlist[N+9].charp = &termSuspChar;
891: Setlist[N+10].charp = &termRprntChar;
892: Setlist[N+11].charp = &termWerasChar;
893: Setlist[N+12].charp = &termStartChar;
894: Setlist[N+13].charp = &termStopChar;
895: Setlist[N+14].charp = &termForw1Char;
896: Setlist[N+15].charp = &termForw2Char;
897: Setlist[N+16].charp = &termAytChar;
898: #undef N
899: }
900: #endif /* defined(CRAY) && !defined(__STDC__) */
901:
902: static struct setlist *
903: getset(name)
904: char *name;
905: {
906: return (struct setlist *)
907: genget(name, (char **) Setlist, sizeof(struct setlist));
908: }
909:
910: void
911: set_escape_char(s)
912: char *s;
913: {
914: if (rlogin != _POSIX_VDISABLE) {
915: rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
916: printf("Telnet rlogin escape character is '%s'.\n",
917: control(rlogin));
918: } else {
919: escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
920: printf("Telnet escape character is '%s'.\n", control(escape));
921: }
922: }
923:
924: static int
925: setcmd(argc, argv)
926: int argc;
927: char *argv[];
928: {
929: int value;
930: struct setlist *ct;
931: struct togglelist *c;
932:
933: if (argc < 2 || argc > 3) {
934: printf("Format is 'set Name Value'\n'set ?' for help.\n");
935: return 0;
936: }
937: if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
938: for (ct = Setlist; ct->name; ct++)
939: printf("%-15s %s\n", ct->name, ct->help);
940: printf("\n");
941: settogglehelp(1);
942: printf("%-15s %s\n", "?", "display help information");
943: return 0;
944: }
945:
946: ct = getset(argv[1]);
947: if (ct == 0) {
948: c = GETTOGGLE(argv[1]);
949: if (c == 0) {
950: fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
951: argv[1]);
952: return 0;
953: } else if (Ambiguous(c)) {
954: fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
955: argv[1]);
956: return 0;
957: }
958: if (c->variable) {
959: if ((argc == 2) || (strcmp("on", argv[2]) == 0))
960: *c->variable = 1;
961: else if (strcmp("off", argv[2]) == 0)
962: *c->variable = 0;
963: else {
964: printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
965: return 0;
966: }
967: if (c->actionexplanation) {
968: printf("%s %s.\n", *c->variable? "Will" : "Won't",
969: c->actionexplanation);
970: }
971: }
972: if (c->handler)
973: (*c->handler)(1);
974: } else if (argc != 3) {
975: printf("Format is 'set Name Value'\n'set ?' for help.\n");
976: return 0;
977: } else if (Ambiguous(ct)) {
978: fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
979: argv[1]);
980: return 0;
981: } else if (ct->handler) {
982: (*ct->handler)(argv[2]);
983: printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
984: } else {
985: if (strcmp("off", argv[2])) {
986: value = special(argv[2]);
987: } else {
988: value = _POSIX_VDISABLE;
989: }
990: *(ct->charp) = (cc_t)value;
991: printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
992: }
993: slc_check();
994: return 1;
995: }
996:
997: static int
998: unsetcmd(argc, argv)
999: int argc;
1000: char *argv[];
1001: {
1002: struct setlist *ct;
1003: struct togglelist *c;
1004: register char *name;
1005:
1006: if (argc < 2) {
1007: fprintf(stderr,
1008: "Need an argument to 'unset' command. 'unset ?' for help.\n");
1009: return 0;
1010: }
1011: if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
1012: for (ct = Setlist; ct->name; ct++)
1013: printf("%-15s %s\n", ct->name, ct->help);
1014: printf("\n");
1015: settogglehelp(0);
1016: printf("%-15s %s\n", "?", "display help information");
1017: return 0;
1018: }
1019:
1020: argc--;
1021: argv++;
1022: while (argc--) {
1023: name = *argv++;
1024: ct = getset(name);
1025: if (ct == 0) {
1026: c = GETTOGGLE(name);
1027: if (c == 0) {
1028: fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
1029: name);
1030: return 0;
1031: } else if (Ambiguous(c)) {
1032: fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
1033: name);
1034: return 0;
1035: }
1036: if (c->variable) {
1037: *c->variable = 0;
1038: if (c->actionexplanation) {
1039: printf("%s %s.\n", *c->variable? "Will" : "Won't",
1040: c->actionexplanation);
1041: }
1042: }
1043: if (c->handler)
1044: (*c->handler)(0);
1045: } else if (Ambiguous(ct)) {
1046: fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
1047: name);
1048: return 0;
1049: } else if (ct->handler) {
1050: (*ct->handler)(0);
1051: printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
1052: } else {
1053: *(ct->charp) = _POSIX_VDISABLE;
1054: printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
1055: }
1056: }
1057: return 1;
1058: }
1059:
1060: /*
1061: * The following are the data structures and routines for the
1062: * 'mode' command.
1063: */
1064: #ifdef KLUDGELINEMODE
1065: extern int kludgelinemode;
1066:
1067: static int
1068: dokludgemode()
1069: {
1070: kludgelinemode = 1;
1071: send_wont(TELOPT_LINEMODE, 1);
1072: send_dont(TELOPT_SGA, 1);
1073: send_dont(TELOPT_ECHO, 1);
1074: }
1075: #endif
1076:
1077: static int
1078: dolinemode()
1079: {
1080: #ifdef KLUDGELINEMODE
1081: if (kludgelinemode)
1082: send_dont(TELOPT_SGA, 1);
1083: #endif
1084: send_will(TELOPT_LINEMODE, 1);
1085: send_dont(TELOPT_ECHO, 1);
1086: return 1;
1087: }
1088:
1089: static int
1090: docharmode()
1091: {
1092: #ifdef KLUDGELINEMODE
1093: if (kludgelinemode)
1094: send_do(TELOPT_SGA, 1);
1095: else
1096: #endif
1097: send_wont(TELOPT_LINEMODE, 1);
1098: send_do(TELOPT_ECHO, 1);
1099: return 1;
1100: }
1101:
1102: static int
1103: dolmmode(bit, on)
1104: int bit, on;
1105: {
1106: unsigned char c;
1107: extern int linemode;
1108:
1109: if (my_want_state_is_wont(TELOPT_LINEMODE)) {
1110: printf("?Need to have LINEMODE option enabled first.\n");
1111: printf("'mode ?' for help.\n");
1112: return 0;
1113: }
1114:
1115: if (on)
1116: c = (linemode | bit);
1117: else
1118: c = (linemode & ~bit);
1119: lm_mode(&c, 1, 1);
1120: return 1;
1121: }
1122:
1123: int
1124: setmode(bit)
1125: {
1126: return dolmmode(bit, 1);
1127: }
1128:
1129: int
1130: clearmode(bit)
1131: {
1132: return dolmmode(bit, 0);
1133: }
1134:
1135: struct modelist {
1136: char *name; /* command name */
1137: char *help; /* help string */
1138: int (*handler)(); /* routine which executes command */
1139: int needconnect; /* Do we need to be connected to execute? */
1140: int arg1;
1141: };
1142:
1143: extern int modehelp();
1144:
1145: static struct modelist ModeList[] = {
1146: { "character", "Disable LINEMODE option", docharmode, 1 },
1147: #ifdef KLUDGELINEMODE
1148: { "", "(or disable obsolete line-by-line mode)", 0 },
1149: #endif
1150: { "line", "Enable LINEMODE option", dolinemode, 1 },
1151: #ifdef KLUDGELINEMODE
1152: { "", "(or enable obsolete line-by-line mode)", 0 },
1153: #endif
1154: { "", "", 0 },
1155: { "", "These require the LINEMODE option to be enabled", 0 },
1156: { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG },
1157: { "+isig", 0, setmode, 1, MODE_TRAPSIG },
1158: { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG },
1159: { "edit", "Enable character editing", setmode, 1, MODE_EDIT },
1160: { "+edit", 0, setmode, 1, MODE_EDIT },
1161: { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT },
1162: { "softtabs", "Enable tab expansion", setmode, 1, MODE_SOFT_TAB },
1163: { "+softtabs", 0, setmode, 1, MODE_SOFT_TAB },
1164: { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB },
1165: { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO },
1166: { "+litecho", 0, setmode, 1, MODE_LIT_ECHO },
1167: { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
1168: { "help", 0, modehelp, 0 },
1169: #ifdef KLUDGELINEMODE
1170: { "kludgeline", 0, dokludgemode, 1 },
1171: #endif
1172: { "", "", 0 },
1173: { "?", "Print help information", modehelp, 0 },
1174: { 0 },
1175: };
1176:
1177:
1178: int
1179: modehelp()
1180: {
1181: struct modelist *mt;
1182:
1183: printf("format is: 'mode Mode', where 'Mode' is one of:\n\n");
1184: for (mt = ModeList; mt->name; mt++) {
1185: if (mt->help) {
1186: if (*mt->help)
1187: printf("%-15s %s\n", mt->name, mt->help);
1188: else
1189: printf("\n");
1190: }
1191: }
1192: return 0;
1193: }
1194:
1195: #define GETMODECMD(name) (struct modelist *) \
1196: genget(name, (char **) ModeList, sizeof(struct modelist))
1197:
1198: static int
1199: modecmd(argc, argv)
1200: int argc;
1201: char *argv[];
1202: {
1203: struct modelist *mt;
1204:
1205: if (argc != 2) {
1206: printf("'mode' command requires an argument\n");
1207: printf("'mode ?' for help.\n");
1208: } else if ((mt = GETMODECMD(argv[1])) == 0) {
1209: fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
1210: } else if (Ambiguous(mt)) {
1211: fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
1212: } else if (mt->needconnect && !connected) {
1213: printf("?Need to be connected first.\n");
1214: printf("'mode ?' for help.\n");
1215: } else if (mt->handler) {
1216: return (*mt->handler)(mt->arg1);
1217: }
1218: return 0;
1219: }
1220:
1221: /*
1222: * The following data structures and routines implement the
1223: * "display" command.
1224: */
1225:
1226: static int
1227: display(argc, argv)
1228: int argc;
1229: char *argv[];
1230: {
1231: struct togglelist *tl;
1232: struct setlist *sl;
1233:
1234: #define dotog(tl) if (tl->variable && tl->actionexplanation) { \
1235: if (*tl->variable) { \
1236: printf("will"); \
1237: } else { \
1238: printf("won't"); \
1239: } \
1240: printf(" %s.\n", tl->actionexplanation); \
1241: }
1242:
1243: #define doset(sl) if (sl->name && *sl->name != ' ') { \
1244: if (sl->handler == 0) \
1245: printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
1246: else \
1247: printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
1248: }
1249:
1250: if (argc == 1) {
1251: for (tl = Togglelist; tl->name; tl++) {
1252: dotog(tl);
1253: }
1254: printf("\n");
1255: for (sl = Setlist; sl->name; sl++) {
1256: doset(sl);
1257: }
1258: } else {
1259: int i;
1260:
1261: for (i = 1; i < argc; i++) {
1262: sl = getset(argv[i]);
1263: tl = GETTOGGLE(argv[i]);
1264: if (Ambiguous(sl) || Ambiguous(tl)) {
1265: printf("?Ambiguous argument '%s'.\n", argv[i]);
1266: return 0;
1267: } else if (!sl && !tl) {
1268: printf("?Unknown argument '%s'.\n", argv[i]);
1269: return 0;
1270: } else {
1271: if (tl) {
1272: dotog(tl);
1273: }
1274: if (sl) {
1275: doset(sl);
1276: }
1277: }
1278: }
1279: }
1280: /*@*/optionstatus();
1281: return 1;
1282: #undef doset
1283: #undef dotog
1284: }
1285:
1286: /*
1287: * The following are the data structures, and many of the routines,
1288: * relating to command processing.
1289: */
1290:
1291: /*
1292: * Set the escape character.
1293: */
1294: static int
1295: setescape(argc, argv)
1296: int argc;
1297: char *argv[];
1298: {
1299: register char *arg;
1300: char buf[50];
1301:
1302: printf(
1303: "Deprecated usage - please use 'set escape%s%s' in the future.\n",
1304: (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
1305: if (argc > 2)
1306: arg = argv[1];
1307: else {
1308: printf("new escape character: ");
1309: (void) fgets(buf, sizeof(buf), stdin);
1310: arg = buf;
1311: }
1312: if (arg[0] != '\0')
1313: escape = arg[0];
1314: if (!In3270) {
1315: printf("Escape character is '%s'.\n", control(escape));
1316: }
1317: (void) fflush(stdout);
1318: return 1;
1319: }
1320:
1321: /*VARARGS*/
1322: static int
1323: togcrmod()
1324: {
1325: crmod = !crmod;
1326: printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
1327: printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
1328: (void) fflush(stdout);
1329: return 1;
1330: }
1331:
1332: /*VARARGS*/
1333: int
1334: suspend()
1335: {
1336: #ifdef SIGTSTP
1337: setcommandmode();
1338: {
1339: long oldrows, oldcols, newrows, newcols, err;
1340:
1341: err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
1342: (void) kill(0, SIGTSTP);
1343: /*
1344: * If we didn't get the window size before the SUSPEND, but we
1.3 niklas 1345: * can get them now (?), then send the NAWS to make sure that
1.1 deraadt 1346: * we are set up for the right window size.
1347: */
1348: if (TerminalWindowSize(&newrows, &newcols) && connected &&
1349: (err || ((oldrows != newrows) || (oldcols != newcols)))) {
1350: sendnaws();
1351: }
1352: }
1353: /* reget parameters in case they were changed */
1354: TerminalSaveState();
1355: setconnmode(0);
1356: #else
1357: printf("Suspend is not supported. Try the '!' command instead\n");
1358: #endif
1359: return 1;
1360: }
1361:
1362: #if !defined(TN3270)
1363: /*ARGSUSED*/
1364: int
1365: shell(argc, argv)
1366: int argc;
1367: char *argv[];
1368: {
1369: long oldrows, oldcols, newrows, newcols, err;
1370:
1371: setcommandmode();
1372:
1373: err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
1374: switch(vfork()) {
1375: case -1:
1376: perror("Fork failed\n");
1377: break;
1378:
1379: case 0:
1380: {
1381: /*
1382: * Fire up the shell in the child.
1383: */
1384: register char *shellp, *shellname;
1.3 niklas 1385: extern char *strrchr();
1.1 deraadt 1386:
1387: shellp = getenv("SHELL");
1388: if (shellp == NULL)
1389: shellp = "/bin/sh";
1.3 niklas 1390: if ((shellname = strrchr(shellp, '/')) == 0)
1.1 deraadt 1391: shellname = shellp;
1392: else
1393: shellname++;
1394: if (argc > 1)
1395: execl(shellp, shellname, "-c", &saveline[1], 0);
1396: else
1397: execl(shellp, shellname, 0);
1398: perror("Execl");
1399: _exit(1);
1400: }
1401: default:
1402: (void)wait((int *)0); /* Wait for the shell to complete */
1403:
1404: if (TerminalWindowSize(&newrows, &newcols) && connected &&
1405: (err || ((oldrows != newrows) || (oldcols != newcols)))) {
1406: sendnaws();
1407: }
1408: break;
1409: }
1410: return 1;
1411: }
1412: #else /* !defined(TN3270) */
1413: extern int shell();
1414: #endif /* !defined(TN3270) */
1415:
1416: /*VARARGS*/
1417: static
1418: bye(argc, argv)
1419: int argc; /* Number of arguments */
1420: char *argv[]; /* arguments */
1421: {
1422: extern int resettermname;
1423:
1424: if (connected) {
1425: (void) shutdown(net, 2);
1426: printf("Connection closed.\n");
1427: (void) NetClose(net);
1428: connected = 0;
1429: resettermname = 1;
1430: #if defined(AUTHENTICATION)
1431: auth_encrypt_connect(connected);
1432: #endif /* defined(AUTHENTICATION) */
1433: /* reset options */
1434: tninit();
1435: #if defined(TN3270)
1436: SetIn3270(); /* Get out of 3270 mode */
1437: #endif /* defined(TN3270) */
1438: }
1439: if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
1440: longjmp(toplevel, 1);
1441: /* NOTREACHED */
1442: }
1443: return 1; /* Keep lint, etc., happy */
1444: }
1445:
1446: /*VARARGS*/
1447: quit()
1448: {
1449: (void) call(bye, "bye", "fromquit", 0);
1450: Exit(0);
1451: /*NOTREACHED*/
1452: }
1453:
1454: /*VARARGS*/
1455: int
1456: logout()
1457: {
1458: send_do(TELOPT_LOGOUT, 1);
1459: (void) netflush();
1460: return 1;
1461: }
1462:
1463:
1464: /*
1465: * The SLC command.
1466: */
1467:
1468: struct slclist {
1469: char *name;
1470: char *help;
1471: void (*handler)();
1472: int arg;
1473: };
1474:
1475: static void slc_help();
1476:
1477: struct slclist SlcList[] = {
1478: { "export", "Use local special character definitions",
1479: slc_mode_export, 0 },
1480: { "import", "Use remote special character definitions",
1481: slc_mode_import, 1 },
1482: { "check", "Verify remote special character definitions",
1483: slc_mode_import, 0 },
1484: { "help", 0, slc_help, 0 },
1485: { "?", "Print help information", slc_help, 0 },
1486: { 0 },
1487: };
1488:
1489: static void
1490: slc_help()
1491: {
1492: struct slclist *c;
1493:
1494: for (c = SlcList; c->name; c++) {
1495: if (c->help) {
1496: if (*c->help)
1497: printf("%-15s %s\n", c->name, c->help);
1498: else
1499: printf("\n");
1500: }
1501: }
1502: }
1503:
1504: static struct slclist *
1505: getslc(name)
1506: char *name;
1507: {
1508: return (struct slclist *)
1509: genget(name, (char **) SlcList, sizeof(struct slclist));
1510: }
1511:
1512: static
1513: slccmd(argc, argv)
1514: int argc;
1515: char *argv[];
1516: {
1517: struct slclist *c;
1518:
1519: if (argc != 2) {
1520: fprintf(stderr,
1521: "Need an argument to 'slc' command. 'slc ?' for help.\n");
1522: return 0;
1523: }
1524: c = getslc(argv[1]);
1525: if (c == 0) {
1.3 niklas 1526: fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
1.1 deraadt 1527: argv[1]);
1.3 niklas 1528: return 0;
1.1 deraadt 1529: }
1530: if (Ambiguous(c)) {
1.3 niklas 1531: fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
1.1 deraadt 1532: argv[1]);
1.3 niklas 1533: return 0;
1.1 deraadt 1534: }
1535: (*c->handler)(c->arg);
1536: slcstate();
1537: return 1;
1538: }
1539:
1540: /*
1541: * The ENVIRON command.
1542: */
1543:
1544: struct envlist {
1545: char *name;
1546: char *help;
1547: void (*handler)();
1548: int narg;
1549: };
1550:
1551: extern struct env_lst *
1552: env_define P((unsigned char *, unsigned char *));
1553: extern void
1554: env_undefine P((unsigned char *)),
1555: env_export P((unsigned char *)),
1556: env_unexport P((unsigned char *)),
1557: env_send P((unsigned char *)),
1558: #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1559: env_varval P((unsigned char *)),
1560: #endif
1561: env_list P((void));
1562: static void
1563: env_help P((void));
1564:
1565: struct envlist EnvList[] = {
1566: { "define", "Define an environment variable",
1567: (void (*)())env_define, 2 },
1568: { "undefine", "Undefine an environment variable",
1569: env_undefine, 1 },
1570: { "export", "Mark an environment variable for automatic export",
1571: env_export, 1 },
1572: { "unexport", "Don't mark an environment variable for automatic export",
1573: env_unexport, 1 },
1574: { "send", "Send an environment variable", env_send, 1 },
1575: { "list", "List the current environment variables",
1576: env_list, 0 },
1577: #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1578: { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
1579: env_varval, 1 },
1580: #endif
1581: { "help", 0, env_help, 0 },
1582: { "?", "Print help information", env_help, 0 },
1583: { 0 },
1584: };
1585:
1586: static void
1587: env_help()
1588: {
1589: struct envlist *c;
1590:
1591: for (c = EnvList; c->name; c++) {
1592: if (c->help) {
1593: if (*c->help)
1594: printf("%-15s %s\n", c->name, c->help);
1595: else
1596: printf("\n");
1597: }
1598: }
1599: }
1600:
1601: static struct envlist *
1602: getenvcmd(name)
1603: char *name;
1604: {
1605: return (struct envlist *)
1606: genget(name, (char **) EnvList, sizeof(struct envlist));
1607: }
1608:
1609: env_cmd(argc, argv)
1610: int argc;
1611: char *argv[];
1612: {
1613: struct envlist *c;
1614:
1615: if (argc < 2) {
1616: fprintf(stderr,
1617: "Need an argument to 'environ' command. 'environ ?' for help.\n");
1618: return 0;
1619: }
1620: c = getenvcmd(argv[1]);
1621: if (c == 0) {
1.3 niklas 1622: fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
1.1 deraadt 1623: argv[1]);
1.3 niklas 1624: return 0;
1.1 deraadt 1625: }
1626: if (Ambiguous(c)) {
1.3 niklas 1627: fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
1.1 deraadt 1628: argv[1]);
1.3 niklas 1629: return 0;
1.1 deraadt 1630: }
1631: if (c->narg + 2 != argc) {
1632: fprintf(stderr,
1633: "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n",
1634: c->narg < argc + 2 ? "only " : "",
1635: c->narg, c->narg == 1 ? "" : "s", c->name);
1636: return 0;
1637: }
1638: (*c->handler)(argv[2], argv[3]);
1639: return 1;
1640: }
1641:
1642: struct env_lst {
1643: struct env_lst *next; /* pointer to next structure */
1644: struct env_lst *prev; /* pointer to previous structure */
1645: unsigned char *var; /* pointer to variable name */
1646: unsigned char *value; /* pointer to variable value */
1647: int export; /* 1 -> export with default list of variables */
1648: int welldefined; /* A well defined variable */
1649: };
1650:
1651: struct env_lst envlisthead;
1652:
1653: struct env_lst *
1654: env_find(var)
1655: unsigned char *var;
1656: {
1657: register struct env_lst *ep;
1658:
1659: for (ep = envlisthead.next; ep; ep = ep->next) {
1660: if (strcmp((char *)ep->var, (char *)var) == 0)
1661: return(ep);
1662: }
1663: return(NULL);
1664: }
1665:
1666: void
1667: env_init()
1668: {
1669: extern char **environ;
1670: register char **epp, *cp;
1671: register struct env_lst *ep;
1.3 niklas 1672: extern char *strchr();
1.1 deraadt 1673:
1674: for (epp = environ; *epp; epp++) {
1.3 niklas 1675: if (cp = strchr(*epp, '=')) {
1.1 deraadt 1676: *cp = '\0';
1677: ep = env_define((unsigned char *)*epp,
1678: (unsigned char *)cp+1);
1679: ep->export = 0;
1680: *cp = '=';
1681: }
1682: }
1683: /*
1684: * Special case for DISPLAY variable. If it is ":0.0" or
1685: * "unix:0.0", we have to get rid of "unix" and insert our
1686: * hostname.
1687: */
1688: if ((ep = env_find("DISPLAY"))
1689: && ((*ep->value == ':')
1.3 niklas 1690: || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
1.1 deraadt 1691: char hbuf[256+1];
1.3 niklas 1692: char *cp2 = strchr((char *)ep->value, ':');
1.1 deraadt 1693:
1694: gethostname(hbuf, 256);
1695: hbuf[256] = '\0';
1696: cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
1697: sprintf((char *)cp, "%s%s", hbuf, cp2);
1698: free(ep->value);
1699: ep->value = (unsigned char *)cp;
1700: }
1701: /*
1702: * If USER is not defined, but LOGNAME is, then add
1703: * USER with the value from LOGNAME. By default, we
1704: * don't export the USER variable.
1705: */
1706: if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
1707: env_define((unsigned char *)"USER", ep->value);
1708: env_unexport((unsigned char *)"USER");
1709: }
1710: env_export((unsigned char *)"DISPLAY");
1711: env_export((unsigned char *)"PRINTER");
1712: }
1713:
1714: struct env_lst *
1715: env_define(var, value)
1716: unsigned char *var, *value;
1717: {
1718: register struct env_lst *ep;
1719:
1720: if (ep = env_find(var)) {
1721: if (ep->var)
1722: free(ep->var);
1723: if (ep->value)
1724: free(ep->value);
1725: } else {
1726: ep = (struct env_lst *)malloc(sizeof(struct env_lst));
1727: ep->next = envlisthead.next;
1728: envlisthead.next = ep;
1729: ep->prev = &envlisthead;
1730: if (ep->next)
1731: ep->next->prev = ep;
1732: }
1733: ep->welldefined = opt_welldefined(var);
1734: ep->export = 1;
1735: ep->var = (unsigned char *)strdup((char *)var);
1736: ep->value = (unsigned char *)strdup((char *)value);
1737: return(ep);
1738: }
1739:
1740: void
1741: env_undefine(var)
1742: unsigned char *var;
1743: {
1744: register struct env_lst *ep;
1745:
1746: if (ep = env_find(var)) {
1747: ep->prev->next = ep->next;
1748: if (ep->next)
1749: ep->next->prev = ep->prev;
1750: if (ep->var)
1751: free(ep->var);
1752: if (ep->value)
1753: free(ep->value);
1754: free(ep);
1755: }
1756: }
1757:
1758: void
1759: env_export(var)
1760: unsigned char *var;
1761: {
1762: register struct env_lst *ep;
1763:
1764: if (ep = env_find(var))
1765: ep->export = 1;
1766: }
1767:
1768: void
1769: env_unexport(var)
1770: unsigned char *var;
1771: {
1772: register struct env_lst *ep;
1773:
1774: if (ep = env_find(var))
1775: ep->export = 0;
1776: }
1777:
1778: void
1779: env_send(var)
1780: unsigned char *var;
1781: {
1782: register struct env_lst *ep;
1783:
1.3 niklas 1784: if (my_state_is_wont(TELOPT_NEW_ENVIRON)
1.1 deraadt 1785: #ifdef OLD_ENVIRON
1786: && my_state_is_wont(TELOPT_OLD_ENVIRON)
1787: #endif
1788: ) {
1789: fprintf(stderr,
1790: "Cannot send '%s': Telnet ENVIRON option not enabled\n",
1791: var);
1792: return;
1793: }
1794: ep = env_find(var);
1795: if (ep == 0) {
1796: fprintf(stderr, "Cannot send '%s': variable not defined\n",
1797: var);
1798: return;
1799: }
1800: env_opt_start_info();
1801: env_opt_add(ep->var);
1802: env_opt_end(0);
1803: }
1804:
1805: void
1806: env_list()
1807: {
1808: register struct env_lst *ep;
1809:
1810: for (ep = envlisthead.next; ep; ep = ep->next) {
1811: printf("%c %-20s %s\n", ep->export ? '*' : ' ',
1812: ep->var, ep->value);
1813: }
1814: }
1815:
1816: unsigned char *
1817: env_default(init, welldefined)
1818: int init;
1819: {
1820: static struct env_lst *nep = NULL;
1821:
1822: if (init) {
1823: nep = &envlisthead;
1824: return;
1825: }
1826: if (nep) {
1827: while (nep = nep->next) {
1828: if (nep->export && (nep->welldefined == welldefined))
1829: return(nep->var);
1830: }
1831: }
1832: return(NULL);
1833: }
1834:
1835: unsigned char *
1836: env_getvalue(var)
1837: unsigned char *var;
1838: {
1839: register struct env_lst *ep;
1840:
1841: if (ep = env_find(var))
1842: return(ep->value);
1843: return(NULL);
1844: }
1845:
1846: #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1847: void
1848: env_varval(what)
1849: unsigned char *what;
1850: {
1851: extern int old_env_var, old_env_value, env_auto;
1852: int len = strlen((char *)what);
1853:
1854: if (len == 0)
1855: goto unknown;
1856:
1857: if (strncasecmp((char *)what, "status", len) == 0) {
1858: if (env_auto)
1859: printf("%s%s", "VAR and VALUE are/will be ",
1860: "determined automatically\n");
1861: if (old_env_var == OLD_ENV_VAR)
1862: printf("VAR and VALUE set to correct definitions\n");
1863: else
1864: printf("VAR and VALUE definitions are reversed\n");
1865: } else if (strncasecmp((char *)what, "auto", len) == 0) {
1866: env_auto = 1;
1867: old_env_var = OLD_ENV_VALUE;
1868: old_env_value = OLD_ENV_VAR;
1869: } else if (strncasecmp((char *)what, "right", len) == 0) {
1870: env_auto = 0;
1871: old_env_var = OLD_ENV_VAR;
1872: old_env_value = OLD_ENV_VALUE;
1873: } else if (strncasecmp((char *)what, "wrong", len) == 0) {
1874: env_auto = 0;
1875: old_env_var = OLD_ENV_VALUE;
1876: old_env_value = OLD_ENV_VAR;
1877: } else {
1878: unknown:
1879: printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
1880: }
1881: }
1882: #endif
1883:
1884: #if defined(AUTHENTICATION)
1885: /*
1886: * The AUTHENTICATE command.
1887: */
1888:
1889: struct authlist {
1890: char *name;
1891: char *help;
1892: int (*handler)();
1893: int narg;
1894: };
1895:
1896: extern int
1.3 niklas 1897: auth_enable P((char *)),
1898: auth_disable P((char *)),
1.1 deraadt 1899: auth_status P((void));
1900: static int
1901: auth_help P((void));
1902:
1903: struct authlist AuthList[] = {
1904: { "status", "Display current status of authentication information",
1905: auth_status, 0 },
1906: { "disable", "Disable an authentication type ('auth disable ?' for more)",
1907: auth_disable, 1 },
1908: { "enable", "Enable an authentication type ('auth enable ?' for more)",
1909: auth_enable, 1 },
1910: { "help", 0, auth_help, 0 },
1911: { "?", "Print help information", auth_help, 0 },
1912: { 0 },
1913: };
1914:
1915: static int
1916: auth_help()
1917: {
1918: struct authlist *c;
1919:
1920: for (c = AuthList; c->name; c++) {
1921: if (c->help) {
1922: if (*c->help)
1923: printf("%-15s %s\n", c->name, c->help);
1924: else
1925: printf("\n");
1926: }
1927: }
1928: return 0;
1929: }
1930:
1931: auth_cmd(argc, argv)
1932: int argc;
1933: char *argv[];
1934: {
1935: struct authlist *c;
1936:
1.3 niklas 1937: if (argc < 2) {
1938: fprintf(stderr,
1939: "Need an argument to 'auth' command. 'auth ?' for help.\n");
1940: return 0;
1941: }
1942:
1.1 deraadt 1943: c = (struct authlist *)
1944: genget(argv[1], (char **) AuthList, sizeof(struct authlist));
1945: if (c == 0) {
1.3 niklas 1946: fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
1.1 deraadt 1947: argv[1]);
1.3 niklas 1948: return 0;
1.1 deraadt 1949: }
1950: if (Ambiguous(c)) {
1.3 niklas 1951: fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
1.1 deraadt 1952: argv[1]);
1.3 niklas 1953: return 0;
1.1 deraadt 1954: }
1955: if (c->narg + 2 != argc) {
1956: fprintf(stderr,
1957: "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n",
1958: c->narg < argc + 2 ? "only " : "",
1959: c->narg, c->narg == 1 ? "" : "s", c->name);
1960: return 0;
1961: }
1962: return((*c->handler)(argv[2], argv[3]));
1963: }
1964: #endif
1965:
1966:
1967: #if defined(unix) && defined(TN3270)
1968: static void
1969: filestuff(fd)
1970: int fd;
1971: {
1972: int res;
1973:
1974: #ifdef F_GETOWN
1975: setconnmode(0);
1976: res = fcntl(fd, F_GETOWN, 0);
1977: setcommandmode();
1978:
1979: if (res == -1) {
1980: perror("fcntl");
1981: return;
1982: }
1983: printf("\tOwner is %d.\n", res);
1984: #endif
1985:
1986: setconnmode(0);
1987: res = fcntl(fd, F_GETFL, 0);
1988: setcommandmode();
1989:
1990: if (res == -1) {
1991: perror("fcntl");
1992: return;
1993: }
1994: #ifdef notdef
1995: printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
1996: #endif
1997: }
1998: #endif /* defined(unix) && defined(TN3270) */
1999:
2000: /*
2001: * Print status about the connection.
2002: */
2003: /*ARGSUSED*/
2004: static
2005: status(argc, argv)
2006: int argc;
2007: char *argv[];
2008: {
2009: if (connected) {
2010: printf("Connected to %s.\n", hostname);
2011: if ((argc < 2) || strcmp(argv[1], "notmuch")) {
2012: int mode = getconnmode();
2013:
2014: if (my_want_state_is_will(TELOPT_LINEMODE)) {
2015: printf("Operating with LINEMODE option\n");
2016: printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
2017: printf("%s catching of signals\n",
2018: (mode&MODE_TRAPSIG) ? "Local" : "No");
2019: slcstate();
2020: #ifdef KLUDGELINEMODE
2021: } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
2022: printf("Operating in obsolete linemode\n");
2023: #endif
2024: } else {
2025: printf("Operating in single character mode\n");
2026: if (localchars)
2027: printf("Catching signals locally\n");
2028: }
2029: printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
2030: if (my_want_state_is_will(TELOPT_LFLOW))
2031: printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
2032: }
2033: } else {
2034: printf("No connection.\n");
2035: }
2036: # if !defined(TN3270)
2037: printf("Escape character is '%s'.\n", control(escape));
2038: (void) fflush(stdout);
2039: # else /* !defined(TN3270) */
2040: if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
2041: printf("Escape character is '%s'.\n", control(escape));
2042: }
2043: # if defined(unix)
2044: if ((argc >= 2) && !strcmp(argv[1], "everything")) {
2045: printf("SIGIO received %d time%s.\n",
2046: sigiocount, (sigiocount == 1)? "":"s");
2047: if (In3270) {
2048: printf("Process ID %d, process group %d.\n",
2049: getpid(), getpgrp(getpid()));
2050: printf("Terminal input:\n");
2051: filestuff(tin);
2052: printf("Terminal output:\n");
2053: filestuff(tout);
2054: printf("Network socket:\n");
2055: filestuff(net);
2056: }
2057: }
2058: if (In3270 && transcom) {
2059: printf("Transparent mode command is '%s'.\n", transcom);
2060: }
2061: # endif /* defined(unix) */
2062: (void) fflush(stdout);
2063: if (In3270) {
2064: return 0;
2065: }
2066: # endif /* defined(TN3270) */
2067: return 1;
2068: }
2069:
2070: #ifdef SIGINFO
2071: /*
2072: * Function that gets called when SIGINFO is received.
2073: */
2074: ayt_status()
2075: {
2076: (void) call(status, "status", "notmuch", 0);
2077: }
2078: #endif
2079:
2080: unsigned long inet_addr();
2081:
2082: int
2083: tn(argc, argv)
2084: int argc;
2085: char *argv[];
2086: {
2087: register struct hostent *host = 0;
2088: struct sockaddr_in sin;
2089: struct servent *sp = 0;
2090: unsigned long temp;
2091: extern char *inet_ntoa();
2092: #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2093: char *srp = 0, *strrchr();
2094: unsigned long sourceroute(), srlen;
2095: #endif
2096: char *cmd, *hostp = 0, *portp = 0, *user = 0;
2097:
2098: /* clear the socket address prior to use */
1.3 niklas 2099: memset((char *)&sin, 0, sizeof(sin));
1.1 deraadt 2100:
2101: if (connected) {
2102: printf("?Already connected to %s\n", hostname);
2103: setuid(getuid());
2104: return 0;
2105: }
2106: if (argc < 2) {
2107: (void) strcpy(line, "open ");
2108: printf("(to) ");
2109: (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
2110: makeargv();
2111: argc = margc;
2112: argv = margv;
2113: }
2114: cmd = *argv;
2115: --argc; ++argv;
2116: while (argc) {
1.3 niklas 2117: if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
1.1 deraadt 2118: goto usage;
2119: if (strcmp(*argv, "-l") == 0) {
2120: --argc; ++argv;
2121: if (argc == 0)
2122: goto usage;
2123: user = *argv++;
2124: --argc;
2125: continue;
2126: }
2127: if (strcmp(*argv, "-a") == 0) {
2128: --argc; ++argv;
2129: autologin = 1;
2130: continue;
2131: }
2132: if (hostp == 0) {
2133: hostp = *argv++;
2134: --argc;
2135: continue;
2136: }
2137: if (portp == 0) {
2138: portp = *argv++;
2139: --argc;
2140: continue;
2141: }
2142: usage:
2143: printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
2144: setuid(getuid());
2145: return 0;
2146: }
2147: if (hostp == 0)
2148: goto usage;
2149:
2150: #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2151: if (hostp[0] == '@' || hostp[0] == '!') {
2152: if ((hostname = strrchr(hostp, ':')) == NULL)
2153: hostname = strrchr(hostp, '@');
2154: hostname++;
2155: srp = 0;
2156: temp = sourceroute(hostp, &srp, &srlen);
2157: if (temp == 0) {
2158: herror(srp);
2159: setuid(getuid());
2160: return 0;
2161: } else if (temp == -1) {
2162: printf("Bad source route option: %s\n", hostp);
2163: setuid(getuid());
2164: return 0;
2165: } else {
2166: sin.sin_addr.s_addr = temp;
2167: sin.sin_family = AF_INET;
2168: }
2169: } else {
2170: #endif
2171: temp = inet_addr(hostp);
2172: if (temp != INADDR_NONE) {
2173: sin.sin_addr.s_addr = temp;
2174: sin.sin_family = AF_INET;
1.4 ! deraadt 2175: host = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET);
! 2176: if (host)
! 2177: (void) strcpy(_hostname, host->h_name);
! 2178: else
! 2179: (void) strcpy(_hostname, hostp);
1.1 deraadt 2180: hostname = _hostname;
2181: } else {
2182: host = gethostbyname(hostp);
2183: if (host) {
2184: sin.sin_family = host->h_addrtype;
2185: #if defined(h_addr) /* In 4.3, this is a #define */
1.3 niklas 2186: memmove((caddr_t)&sin.sin_addr,
1.1 deraadt 2187: host->h_addr_list[0], host->h_length);
2188: #else /* defined(h_addr) */
1.3 niklas 2189: memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
1.1 deraadt 2190: #endif /* defined(h_addr) */
2191: strncpy(_hostname, host->h_name, sizeof(_hostname));
2192: _hostname[sizeof(_hostname)-1] = '\0';
2193: hostname = _hostname;
2194: } else {
2195: herror(hostp);
1.3 niklas 2196: setuid(getuid());
1.1 deraadt 2197: return 0;
2198: }
2199: }
2200: #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2201: }
2202: #endif
2203: if (portp) {
2204: if (*portp == '-') {
2205: portp++;
2206: telnetport = 1;
2207: } else
2208: telnetport = 0;
2209: sin.sin_port = atoi(portp);
2210: if (sin.sin_port == 0) {
2211: sp = getservbyname(portp, "tcp");
2212: if (sp)
2213: sin.sin_port = sp->s_port;
2214: else {
2215: printf("%s: bad port number\n", portp);
1.3 niklas 2216: setuid(getuid());
1.1 deraadt 2217: return 0;
2218: }
2219: } else {
2220: #if !defined(htons)
2221: u_short htons P((unsigned short));
2222: #endif /* !defined(htons) */
2223: sin.sin_port = htons(sin.sin_port);
2224: }
2225: } else {
2226: if (sp == 0) {
2227: sp = getservbyname("telnet", "tcp");
2228: if (sp == 0) {
2229: fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
1.3 niklas 2230: setuid(getuid());
1.1 deraadt 2231: return 0;
2232: }
2233: sin.sin_port = sp->s_port;
2234: }
2235: telnetport = 1;
2236: }
2237: printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
2238: do {
2239: net = socket(AF_INET, SOCK_STREAM, 0);
2240: setuid(getuid());
2241: if (net < 0) {
2242: perror("telnet: socket");
2243: return 0;
2244: }
2245: #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2246: if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
2247: perror("setsockopt (IP_OPTIONS)");
2248: #endif
2249: #if defined(IPPROTO_IP) && defined(IP_TOS)
2250: {
2251: # if defined(HAS_GETTOS)
2252: struct tosent *tp;
2253: if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
2254: tos = tp->t_tos;
2255: # endif
2256: if (tos < 0)
1.3 niklas 2257: tos = IPTOS_LOWDELAY; /* Low Delay bit */
1.1 deraadt 2258: if (tos
2259: && (setsockopt(net, IPPROTO_IP, IP_TOS,
2260: (char *)&tos, sizeof(int)) < 0)
2261: && (errno != ENOPROTOOPT))
2262: perror("telnet: setsockopt (IP_TOS) (ignored)");
2263: }
2264: #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
2265:
2266: if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
2267: perror("setsockopt (SO_DEBUG)");
2268: }
2269:
2270: if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
2271: #if defined(h_addr) /* In 4.3, this is a #define */
2272: if (host && host->h_addr_list[1]) {
2273: int oerrno = errno;
2274:
2275: fprintf(stderr, "telnet: connect to address %s: ",
2276: inet_ntoa(sin.sin_addr));
2277: errno = oerrno;
2278: perror((char *)0);
2279: host->h_addr_list++;
1.3 niklas 2280: memmove((caddr_t)&sin.sin_addr,
1.1 deraadt 2281: host->h_addr_list[0], host->h_length);
2282: (void) NetClose(net);
2283: continue;
2284: }
2285: #endif /* defined(h_addr) */
2286: perror("telnet: Unable to connect to remote host");
2287: return 0;
2288: }
2289: connected++;
2290: #if defined(AUTHENTICATION)
2291: auth_encrypt_connect(connected);
2292: #endif /* defined(AUTHENTICATION) */
2293: } while (connected == 0);
2294: cmdrc(hostp, hostname);
2295: if (autologin && user == NULL) {
2296: struct passwd *pw;
2297:
2298: user = getenv("USER");
2299: if (user == NULL ||
2300: (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
2301: if (pw = getpwuid(getuid()))
2302: user = pw->pw_name;
2303: else
2304: user = NULL;
2305: }
2306: }
2307: if (user) {
2308: env_define((unsigned char *)"USER", (unsigned char *)user);
2309: env_export((unsigned char *)"USER");
2310: }
2311: (void) call(status, "status", "notmuch", 0);
2312: if (setjmp(peerdied) == 0)
2313: telnet(user);
2314: (void) NetClose(net);
2315: ExitString("Connection closed by foreign host.\n",1);
2316: /*NOTREACHED*/
2317: }
2318:
2319: #define HELPINDENT (sizeof ("connect"))
2320:
2321: static char
2322: openhelp[] = "connect to a site",
2323: closehelp[] = "close current connection",
2324: logouthelp[] = "forcibly logout remote user and close the connection",
2325: quithelp[] = "exit telnet",
2326: statushelp[] = "print status information",
2327: helphelp[] = "print help information",
2328: sendhelp[] = "transmit special characters ('send ?' for more)",
2329: sethelp[] = "set operating parameters ('set ?' for more)",
2330: unsethelp[] = "unset operating parameters ('unset ?' for more)",
2331: togglestring[] ="toggle operating parameters ('toggle ?' for more)",
2332: slchelp[] = "change state of special charaters ('slc ?' for more)",
2333: displayhelp[] = "display operating parameters",
2334: #if defined(TN3270) && defined(unix)
2335: transcomhelp[] = "specify Unix command for transparent mode pipe",
2336: #endif /* defined(TN3270) && defined(unix) */
2337: #if defined(AUTHENTICATION)
2338: authhelp[] = "turn on (off) authentication ('auth ?' for more)",
2339: #endif
2340: #if defined(unix)
2341: zhelp[] = "suspend telnet",
2342: #endif /* defined(unix) */
2343: shellhelp[] = "invoke a subshell",
2344: envhelp[] = "change environment variables ('environ ?' for more)",
2345: modestring[] = "try to enter line or character mode ('mode ?' for more)";
2346:
2347: static int help();
2348:
2349: static Command cmdtab[] = {
2350: { "close", closehelp, bye, 1 },
2351: { "logout", logouthelp, logout, 1 },
2352: { "display", displayhelp, display, 0 },
2353: { "mode", modestring, modecmd, 0 },
2354: { "open", openhelp, tn, 0 },
2355: { "quit", quithelp, quit, 0 },
2356: { "send", sendhelp, sendcmd, 0 },
2357: { "set", sethelp, setcmd, 0 },
2358: { "unset", unsethelp, unsetcmd, 0 },
2359: { "status", statushelp, status, 0 },
2360: { "toggle", togglestring, toggle, 0 },
2361: { "slc", slchelp, slccmd, 0 },
2362: #if defined(TN3270) && defined(unix)
2363: { "transcom", transcomhelp, settranscom, 0 },
2364: #endif /* defined(TN3270) && defined(unix) */
2365: #if defined(AUTHENTICATION)
2366: { "auth", authhelp, auth_cmd, 0 },
2367: #endif
2368: #if defined(unix)
2369: { "z", zhelp, suspend, 0 },
2370: #endif /* defined(unix) */
2371: #if defined(TN3270)
2372: { "!", shellhelp, shell, 1 },
2373: #else
2374: { "!", shellhelp, shell, 0 },
2375: #endif
2376: { "environ", envhelp, env_cmd, 0 },
2377: { "?", helphelp, help, 0 },
2378: 0
2379: };
2380:
2381: static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead";
2382: static char escapehelp[] = "deprecated command -- use 'set escape' instead";
2383:
2384: static Command cmdtab2[] = {
2385: { "help", 0, help, 0 },
2386: { "escape", escapehelp, setescape, 0 },
2387: { "crmod", crmodhelp, togcrmod, 0 },
2388: 0
2389: };
2390:
2391:
2392: /*
2393: * Call routine with argc, argv set from args (terminated by 0).
2394: */
2395:
2396: /*VARARGS1*/
2397: static
2398: call(va_alist)
2399: va_dcl
2400: {
2401: va_list ap;
2402: typedef int (*intrtn_t)();
2403: intrtn_t routine;
2404: char *args[100];
2405: int argno = 0;
2406:
2407: va_start(ap);
2408: routine = (va_arg(ap, intrtn_t));
2409: while ((args[argno++] = va_arg(ap, char *)) != 0) {
2410: ;
2411: }
2412: va_end(ap);
2413: return (*routine)(argno-1, args);
2414: }
2415:
2416:
2417: static Command *
2418: getcmd(name)
2419: char *name;
2420: {
2421: Command *cm;
2422:
2423: if (cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))
2424: return cm;
2425: return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
2426: }
2427:
2428: void
2429: command(top, tbuf, cnt)
2430: int top;
2431: char *tbuf;
2432: int cnt;
2433: {
2434: register Command *c;
2435:
2436: setcommandmode();
2437: if (!top) {
2438: putchar('\n');
2439: #if defined(unix)
2440: } else {
2441: (void) signal(SIGINT, SIG_DFL);
2442: (void) signal(SIGQUIT, SIG_DFL);
2443: #endif /* defined(unix) */
2444: }
2445: for (;;) {
2446: if (rlogin == _POSIX_VDISABLE)
2447: printf("%s> ", prompt);
2448: if (tbuf) {
2449: register char *cp;
2450: cp = line;
2451: while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
2452: cnt--;
2453: tbuf = 0;
2454: if (cp == line || *--cp != '\n' || cp == line)
2455: goto getline;
2456: *cp = '\0';
2457: if (rlogin == _POSIX_VDISABLE)
1.3 niklas 2458: printf("%s\n", line);
1.1 deraadt 2459: } else {
2460: getline:
2461: if (rlogin != _POSIX_VDISABLE)
2462: printf("%s> ", prompt);
2463: if (fgets(line, sizeof(line), stdin) == NULL) {
2464: if (feof(stdin) || ferror(stdin)) {
2465: (void) quit();
2466: /*NOTREACHED*/
2467: }
2468: break;
2469: }
2470: }
2471: if (line[0] == 0)
2472: break;
2473: makeargv();
2474: if (margv[0] == 0) {
2475: break;
2476: }
2477: c = getcmd(margv[0]);
2478: if (Ambiguous(c)) {
2479: printf("?Ambiguous command\n");
2480: continue;
2481: }
2482: if (c == 0) {
2483: printf("?Invalid command\n");
2484: continue;
2485: }
2486: if (c->needconnect && !connected) {
2487: printf("?Need to be connected first.\n");
2488: continue;
2489: }
2490: if ((*c->handler)(margc, margv)) {
2491: break;
2492: }
2493: }
2494: if (!top) {
2495: if (!connected) {
2496: longjmp(toplevel, 1);
2497: /*NOTREACHED*/
2498: }
2499: #if defined(TN3270)
2500: if (shell_active == 0) {
2501: setconnmode(0);
2502: }
2503: #else /* defined(TN3270) */
2504: setconnmode(0);
2505: #endif /* defined(TN3270) */
2506: }
2507: }
2508:
2509: /*
2510: * Help command.
2511: */
2512: static
2513: help(argc, argv)
2514: int argc;
2515: char *argv[];
2516: {
2517: register Command *c;
2518:
2519: if (argc == 1) {
2520: printf("Commands may be abbreviated. Commands are:\n\n");
2521: for (c = cmdtab; c->name; c++)
2522: if (c->help) {
2523: printf("%-*s\t%s\n", HELPINDENT, c->name,
2524: c->help);
2525: }
2526: return 0;
2527: }
2528: while (--argc > 0) {
2529: register char *arg;
2530: arg = *++argv;
2531: c = getcmd(arg);
2532: if (Ambiguous(c))
2533: printf("?Ambiguous help command %s\n", arg);
2534: else if (c == (Command *)0)
2535: printf("?Invalid help command %s\n", arg);
2536: else
2537: printf("%s\n", c->help);
2538: }
2539: return 0;
2540: }
2541:
2542: static char *rcname = 0;
2543: static char rcbuf[128];
2544:
2545: cmdrc(m1, m2)
2546: char *m1, *m2;
2547: {
2548: register Command *c;
2549: FILE *rcfile;
2550: int gotmachine = 0;
2551: int l1 = strlen(m1);
2552: int l2 = strlen(m2);
2553: char m1save[64];
2554:
2555: if (skiprc)
2556: return;
2557:
2558: strcpy(m1save, m1);
2559: m1 = m1save;
2560:
2561: if (rcname == 0) {
2562: rcname = getenv("HOME");
2563: if (rcname)
2564: strcpy(rcbuf, rcname);
2565: else
2566: rcbuf[0] = '\0';
2567: strcat(rcbuf, "/.telnetrc");
2568: rcname = rcbuf;
2569: }
2570:
2571: if ((rcfile = fopen(rcname, "r")) == 0) {
2572: return;
2573: }
2574:
2575: for (;;) {
2576: if (fgets(line, sizeof(line), rcfile) == NULL)
2577: break;
2578: if (line[0] == 0)
2579: break;
2580: if (line[0] == '#')
2581: continue;
2582: if (gotmachine) {
2583: if (!isspace(line[0]))
2584: gotmachine = 0;
2585: }
2586: if (gotmachine == 0) {
2587: if (isspace(line[0]))
2588: continue;
2589: if (strncasecmp(line, m1, l1) == 0)
2590: strncpy(line, &line[l1], sizeof(line) - l1);
2591: else if (strncasecmp(line, m2, l2) == 0)
2592: strncpy(line, &line[l2], sizeof(line) - l2);
2593: else if (strncasecmp(line, "DEFAULT", 7) == 0)
2594: strncpy(line, &line[7], sizeof(line) - 7);
2595: else
2596: continue;
2597: if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
2598: continue;
2599: gotmachine = 1;
2600: }
2601: makeargv();
2602: if (margv[0] == 0)
2603: continue;
2604: c = getcmd(margv[0]);
2605: if (Ambiguous(c)) {
2606: printf("?Ambiguous command: %s\n", margv[0]);
2607: continue;
2608: }
2609: if (c == 0) {
2610: printf("?Invalid command: %s\n", margv[0]);
2611: continue;
2612: }
2613: /*
2614: * This should never happen...
2615: */
2616: if (c->needconnect && !connected) {
2617: printf("?Need to be connected first for %s.\n", margv[0]);
2618: continue;
2619: }
2620: (*c->handler)(margc, margv);
2621: }
2622: fclose(rcfile);
2623: }
2624:
2625: #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2626:
2627: /*
2628: * Source route is handed in as
2629: * [!]@hop1@hop2...[@|:]dst
2630: * If the leading ! is present, it is a
2631: * strict source route, otherwise it is
2632: * assmed to be a loose source route.
2633: *
2634: * We fill in the source route option as
2635: * hop1,hop2,hop3...dest
2636: * and return a pointer to hop1, which will
2637: * be the address to connect() to.
2638: *
2639: * Arguments:
2640: * arg: pointer to route list to decipher
2641: *
2642: * cpp: If *cpp is not equal to NULL, this is a
2643: * pointer to a pointer to a character array
2644: * that should be filled in with the option.
2645: *
2646: * lenp: pointer to an integer that contains the
2647: * length of *cpp if *cpp != NULL.
2648: *
2649: * Return values:
2650: *
2651: * Returns the address of the host to connect to. If the
2652: * return value is -1, there was a syntax error in the
2653: * option, either unknown characters, or too many hosts.
2654: * If the return value is 0, one of the hostnames in the
2655: * path is unknown, and *cpp is set to point to the bad
2656: * hostname.
2657: *
2658: * *cpp: If *cpp was equal to NULL, it will be filled
2659: * in with a pointer to our static area that has
2660: * the option filled in. This will be 32bit aligned.
1.3 niklas 2661: *
1.1 deraadt 2662: * *lenp: This will be filled in with how long the option
2663: * pointed to by *cpp is.
1.3 niklas 2664: *
1.1 deraadt 2665: */
2666: unsigned long
2667: sourceroute(arg, cpp, lenp)
2668: char *arg;
2669: char **cpp;
2670: int *lenp;
2671: {
2672: static char lsr[44];
2673: #ifdef sysV88
2674: static IOPTN ipopt;
2675: #endif
2676: char *cp, *cp2, *lsrp, *lsrep;
2677: register int tmp;
2678: struct in_addr sin_addr;
2679: register struct hostent *host = 0;
2680: register char c;
2681:
2682: /*
2683: * Verify the arguments, and make sure we have
2684: * at least 7 bytes for the option.
2685: */
2686: if (cpp == NULL || lenp == NULL)
2687: return((unsigned long)-1);
2688: if (*cpp != NULL && *lenp < 7)
2689: return((unsigned long)-1);
2690: /*
2691: * Decide whether we have a buffer passed to us,
2692: * or if we need to use our own static buffer.
2693: */
2694: if (*cpp) {
2695: lsrp = *cpp;
2696: lsrep = lsrp + *lenp;
2697: } else {
2698: *cpp = lsrp = lsr;
2699: lsrep = lsrp + 44;
2700: }
2701:
2702: cp = arg;
2703:
2704: /*
2705: * Next, decide whether we have a loose source
2706: * route or a strict source route, and fill in
2707: * the begining of the option.
2708: */
2709: #ifndef sysV88
2710: if (*cp == '!') {
2711: cp++;
2712: *lsrp++ = IPOPT_SSRR;
2713: } else
2714: *lsrp++ = IPOPT_LSRR;
2715: #else
2716: if (*cp == '!') {
2717: cp++;
2718: ipopt.io_type = IPOPT_SSRR;
2719: } else
2720: ipopt.io_type = IPOPT_LSRR;
2721: #endif
2722:
2723: if (*cp != '@')
2724: return((unsigned long)-1);
2725:
2726: #ifndef sysV88
2727: lsrp++; /* skip over length, we'll fill it in later */
2728: *lsrp++ = 4;
2729: #endif
2730:
2731: cp++;
2732:
2733: sin_addr.s_addr = 0;
2734:
2735: for (c = 0;;) {
2736: if (c == ':')
2737: cp2 = 0;
2738: else for (cp2 = cp; c = *cp2; cp2++) {
2739: if (c == ',') {
2740: *cp2++ = '\0';
2741: if (*cp2 == '@')
2742: cp2++;
2743: } else if (c == '@') {
2744: *cp2++ = '\0';
2745: } else if (c == ':') {
2746: *cp2++ = '\0';
2747: } else
2748: continue;
2749: break;
2750: }
2751: if (!c)
2752: cp2 = 0;
2753:
2754: if ((tmp = inet_addr(cp)) != INADDR_NONE) {
2755: sin_addr.s_addr = tmp;
2756: } else if (host = gethostbyname(cp)) {
2757: #if defined(h_addr)
1.3 niklas 2758: memmove((caddr_t)&sin_addr,
1.1 deraadt 2759: host->h_addr_list[0], host->h_length);
2760: #else
1.3 niklas 2761: memmove((caddr_t)&sin_addr, host->h_addr, host->h_length);
1.1 deraadt 2762: #endif
2763: } else {
2764: *cpp = cp;
2765: return(0);
2766: }
1.3 niklas 2767: memmove(lsrp, (char *)&sin_addr, 4);
1.1 deraadt 2768: lsrp += 4;
2769: if (cp2)
2770: cp = cp2;
2771: else
2772: break;
2773: /*
2774: * Check to make sure there is space for next address
2775: */
2776: if (lsrp + 4 > lsrep)
2777: return((unsigned long)-1);
2778: }
2779: #ifndef sysV88
2780: if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
2781: *cpp = 0;
2782: *lenp = 0;
2783: return((unsigned long)-1);
2784: }
2785: *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
2786: *lenp = lsrp - *cpp;
2787: #else
2788: ipopt.io_len = lsrp - *cpp;
2789: if (ipopt.io_len <= 5) { /* Is 3 better ? */
2790: *cpp = 0;
2791: *lenp = 0;
2792: return((unsigned long)-1);
2793: }
2794: *lenp = sizeof(ipopt);
2795: *cpp = (char *) &ipopt;
2796: #endif
2797: return(sin_addr.s_addr);
2798: }
2799: #endif