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