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