2 * Copyright (c) 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 static char sccsid
[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
41 #ifdef HAVE_SYS_PARAM_H
42 # include <sys/param.h>
44 #ifdef HAVE_SYS_TYPES_H
45 # include <sys/types.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
61 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
68 #if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
75 #include <arpa/telnet.h>
85 #if !defined(CRAY) && !defined(sysV88)
86 #ifdef HAVE_NETINET_IN_SYSTM_H
87 #include <netinet/in_systm.h>
89 # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
90 # include <machine/endian.h>
92 #endif /* !defined(CRAY) && !defined(sysV88) */
94 #ifdef HAVE_NETINET_IP_H
95 #include <netinet/ip.h>
98 #if defined(IPPROTO_IP) && defined(IP_TOS)
100 #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
103 static char *_hostname
= 0;
105 extern char *getenv
__P((const char *));
107 extern int isprefix
__P((register char *s1
, register char *s2
));
108 extern char **genget
__P((char *, char **, int ));
109 extern int Ambiguous
__P(());
111 typedef int (*intrtn_t
) __P((int, char *[]));
112 static int call
__P((intrtn_t
, ...));
115 const char *name
; /* command name */
116 const char *help
; /* help string (NULL for no help) */
117 int (*handler
) ();/* routine which executes command */
118 int needconnect
; /* Do we need to be connected to execute? */
121 static char line
[256];
122 static char saveline
[256];
124 static char *margv
[20];
129 register char *cp
, *cp2
, c
;
130 register char **argp
= margv
;
134 if (*cp
== '!') { /* Special case shell escape */
135 strcpy(saveline
, line
); /* save for shell command */
136 *argp
++ = "!"; /* No room in string to get this */
141 register int inquote
= 0;
148 for (cp2
= cp
; c
!= '\0'; c
= *++cp
) {
156 if ((c
= *++cp
) == '\0')
158 } else if (c
== '"') {
161 } else if (c
== '\'') {
164 } else if (isspace(c
))
178 * Make a character string into a number.
180 * Todo: 1. Could take random integers (12, 0x12, 012, 0b1).
184 special(register char *s
)
193 c
= b
| 0x40; /* DEL */
206 * Construct a control character sequence
207 * for a special character.
210 control(register cc_t c
)
214 * The only way I could get the Sun 3.5 compiler
216 * if ((unsigned int)c >= 0x80)
217 * was to assign "c" to an unsigned int variable...
220 register unsigned int uic
= (unsigned int)c
;
224 if (c
== (cc_t
)_POSIX_VDISABLE
) {
229 buf
[1] = ((c
>>6)&07) + '0';
230 buf
[2] = ((c
>>3)&07) + '0';
231 buf
[3] = (c
&07) + '0';
233 } else if (uic
>= 0x20) {
247 * The following are data structures and routines for
248 * the "send" command.
253 const char *name
; /* How user refers to it (case independent) */
254 const char *help
; /* Help information (0 ==> no help) */
255 int needconnect
; /* Need to be connected */
256 int narg
; /* Number of arguments */
257 int (*handler
)(); /* Routine to perform (for special ops) */
258 int nbyte
; /* Number of bytes to send this command */
259 int what
; /* Character to be sent (<0 ==> special) */
266 send_docmd
P((char *)),
267 send_dontcmd
P((char *)),
268 send_willcmd
P((char *)),
269 send_wontcmd
P((char *));
271 static struct sendlist Sendlist
[] = {
272 { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO
},
273 { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT
},
274 { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK
},
275 { "break", 0, 1, 0, 0, 2, BREAK
},
276 { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC
},
277 { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL
},
278 { "escape", "Send current escape character", 1, 0, send_esc
, 1, 0 },
279 { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA
},
280 { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP
},
281 { "intp", 0, 1, 0, 0, 2, IP
},
282 { "interrupt", 0, 1, 0, 0, 2, IP
},
283 { "intr", 0, 1, 0, 0, 2, IP
},
284 { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP
},
285 { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR
},
286 { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT
},
287 { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP
},
288 { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF
},
289 { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch
, 2, 0 },
290 { "getstatus", "Send request for STATUS", 1, 0, get_status
, 6, 0 },
291 { "?", "Display send options", 0, 0, send_help
, 0, 0 },
292 { "help", 0, 0, 0, send_help
, 0, 0 },
293 { "do", 0, 0, 1, send_docmd
, 3, 0 },
294 { "dont", 0, 0, 1, send_dontcmd
, 3, 0 },
295 { "will", 0, 0, 1, send_willcmd
, 3, 0 },
296 { "wont", 0, 0, 1, send_wontcmd
, 3, 0 },
297 { NULL
, 0, 0, 0, NULL
, 0, 0 }
300 #define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
301 sizeof(struct sendlist)))
304 sendcmd(int argc
, char **argv
)
306 int count
; /* how many bytes we are going to need to send */
308 int question
= 0; /* was at least one argument a question */
309 struct sendlist
*s
; /* pointer to current command */
314 printf("need at least one argument for 'send' command\n");
315 printf("'send ?' for help\n");
319 * First, validate all the send arguments.
320 * In addition, we see how much space we are going to need, and
321 * whether or not we will be doing a "SYNCH" operation (which
322 * flushes the network queue).
325 for (i
= 1; i
< argc
; i
++) {
326 s
= GETSEND(argv
[i
]);
328 printf("Unknown send argument '%s'\n'send ?' for help.\n",
331 } else if (Ambiguous(s
)) {
332 printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
336 if (i
+ s
->narg
>= argc
) {
338 "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n",
339 s
->narg
, s
->narg
== 1 ? "" : "s", s
->name
, s
->name
);
343 if (s
->handler
== send_help
) {
349 needconnect
+= s
->needconnect
;
351 if (!connected
&& needconnect
) {
352 printf("?Need to be connected first.\n");
353 printf("'send ?' for help\n");
356 /* Now, do we have enough room? */
357 if (NETROOM() < count
) {
358 printf("There is not enough room in the buffer TO the network\n");
359 printf("to process your request. Nothing will be done.\n");
360 printf("('send synch' will throw away most data in the network\n");
361 printf("buffer, if this might help.)\n");
364 /* OK, they are all OK, now go through again and actually send */
366 for (i
= 1; i
< argc
; i
++) {
367 if ((s
= GETSEND(argv
[i
])) == 0) {
368 fprintf(stderr
, "Telnet 'send' error - argument disappeared!\n");
374 success
+= (*s
->handler
)((s
->narg
> 0) ? argv
[i
+1] : 0,
375 (s
->narg
> 1) ? argv
[i
+2] : 0);
378 NET2ADD(IAC
, s
->what
);
379 printoption("SENT", IAC
, s
->what
);
382 return (count
== success
);
393 send_docmd(char *name
)
395 return(send_tncmd(send_do
, "do", name
));
399 send_dontcmd(char *name
)
401 return(send_tncmd(send_dont
, "dont", name
));
405 send_willcmd(char *name
)
407 return(send_tncmd(send_will
, "will", name
));
411 send_wontcmd(char *name
)
413 return(send_tncmd(send_wont
, "wont", name
));
417 send_tncmd(void (*func
)(), char *cmd
, char *name
)
420 extern char *telopts
[];
421 register int val
= 0;
423 if (isprefix(name
, "help") || isprefix(name
, "?")) {
424 register int col
, len
;
426 printf("Usage: send %s <value|option>\n", cmd
);
427 printf("\"value\" must be from 0 to 255\n");
428 printf("Valid options are:\n\t");
431 for (cpp
= telopts
; *cpp
; cpp
++) {
432 len
= strlen(*cpp
) + 3;
433 if (col
+ len
> 65) {
437 printf(" \"%s\"", *cpp
);
443 cpp
= (char **)genget(name
, telopts
, sizeof(char *));
444 if (Ambiguous(cpp
)) {
445 fprintf(stderr
,"'%s': ambiguous argument ('send %s ?' for help).\n",
452 register char *cp
= name
;
454 while (*cp
>= '0' && *cp
<= '9') {
460 fprintf(stderr
, "'%s': unknown argument ('send %s ?' for help).\n",
463 } else if (val
< 0 || val
> 255) {
464 fprintf(stderr
, "'%s': bad value ('send %s ?' for help).\n",
470 printf("?Need to be connected first.\n");
480 struct sendlist
*s
; /* pointer to current command */
481 for (s
= Sendlist
; s
->name
; s
++) {
483 printf("%-15s %s\n", s
->name
, s
->help
);
489 * The following are the routines and data structures referred
490 * to by the arguments to the "toggle" command.
505 (SetSockOpt(net
, SOL_SOCKET
, SO_DEBUG
, debug
)) < 0) {
506 perror("setsockopt (SO_DEBUG)");
510 if (net
> 0 && SetSockOpt(net
, SOL_SOCKET
, SO_DEBUG
, 0, 0) < 0)
511 perror("setsockopt (SO_DEBUG)");
513 printf("Cannot turn off socket debugging\n");
523 printf("Will send carriage returns as telnet <CR><LF>.\n");
525 printf("Will send carriage returns as telnet <CR><NUL>.\n");
535 donebinarytoggle
= 1;
540 if (my_want_state_is_will(TELOPT_BINARY
) &&
541 my_want_state_is_do(TELOPT_BINARY
)) {
543 } else if (my_want_state_is_wont(TELOPT_BINARY
) &&
544 my_want_state_is_dont(TELOPT_BINARY
)) {
547 val
= binmode
? 0 : 1;
551 if (my_want_state_is_will(TELOPT_BINARY
) &&
552 my_want_state_is_do(TELOPT_BINARY
)) {
553 printf("Already operating in binary mode with remote host.\n");
555 printf("Negotiating binary mode with remote host.\n");
559 if (my_want_state_is_wont(TELOPT_BINARY
) &&
560 my_want_state_is_dont(TELOPT_BINARY
)) {
561 printf("Already in network ascii mode with remote host.\n");
563 printf("Negotiating network ascii mode with remote host.\n");
573 donebinarytoggle
= 1;
576 val
= my_want_state_is_do(TELOPT_BINARY
) ? 0 : 1;
579 if (my_want_state_is_do(TELOPT_BINARY
)) {
580 printf("Already receiving in binary mode.\n");
582 printf("Negotiating binary mode on input.\n");
586 if (my_want_state_is_dont(TELOPT_BINARY
)) {
587 printf("Already receiving in network ascii mode.\n");
589 printf("Negotiating network ascii mode on input.\n");
599 donebinarytoggle
= 1;
602 val
= my_want_state_is_will(TELOPT_BINARY
) ? 0 : 1;
605 if (my_want_state_is_will(TELOPT_BINARY
)) {
606 printf("Already transmitting in binary mode.\n");
608 printf("Negotiating binary mode on output.\n");
612 if (my_want_state_is_wont(TELOPT_BINARY
)) {
613 printf("Already transmitting in network ascii mode.\n");
615 printf("Negotiating network ascii mode on output.\n");
623 static int togglehelp
P((void));
624 #if defined(AUTHENTICATION)
625 extern int auth_togdebug
P((int));
628 extern int EncryptAutoEnc
P((int));
629 extern int EncryptAutoDec
P((int));
630 extern int EncryptDebug
P((int));
631 extern int EncryptVerbose
P((int));
632 #endif /* ENCRYPTION */
635 const char *name
; /* name of toggle */
636 const char *help
; /* help message */
637 int (*handler
)(); /* routine to do actual setting */
639 const char *actionexplanation
;
642 static struct togglelist Togglelist
[] = {
644 "flushing of output when sending interrupt characters",
647 "flush output when sending interrupt characters" },
649 "automatic sending of interrupt characters in urgent mode",
652 "send interrupt characters in urgent mode" },
653 #if defined(AUTHENTICATION)
655 "automatic sending of login and/or authentication info",
658 "send login name and/or authentication information" },
660 "Toggle authentication debugging",
663 "print authentication debugging information" },
667 "automatic encryption of data stream",
670 "automatically encrypt output" },
672 "automatic decryption of data stream",
675 "automatically decrypt input" },
677 "Toggle verbose encryption output",
680 "print verbose encryption output" },
682 "Toggle encryption debugging",
685 "print encryption debugging information" },
686 #endif /* ENCRYPTION */
688 "don't read ~/.telnetrc file",
691 "skip reading of ~/.telnetrc file" },
693 "sending and receiving of binary data",
698 "receiving of binary data",
703 "sending of binary data",
708 "sending carriage returns as telnet <CR><LF>",
713 "mapping of received carriage returns",
716 "map carriage return on output" },
718 "local recognition of certain control characters",
721 "recognize certain control characters" },
722 { " ", "", 0 }, /* empty line */
723 #if defined(unix) && defined(TN3270)
725 "(debugging) toggle tracing of API transactions",
728 "trace API transactions" },
730 "(debugging) toggle printing of hexadecimal curses data",
733 "print hexadecimal representation of curses data" },
734 #endif /* defined(unix) && defined(TN3270) */
739 "turn on socket level debugging" },
741 "printing of hexadecimal network data (debugging)",
744 "print hexadecimal representation of network traffic" },
746 "output of \"netdata\" to user readable format (debugging)",
749 "print user readable output for \"netdata\"" },
751 "viewing of options processing (debugging)",
754 "show option processing" },
756 "(debugging) toggle printing of hexadecimal terminal data",
759 "print hexadecimal representation of terminal traffic" },
772 struct togglelist
*c
;
774 for (c
= Togglelist
; c
->name
; c
++) {
777 printf("%-15s toggle %s\n", c
->name
, c
->help
);
783 printf("%-15s %s\n", "?", "display help information");
788 settogglehelp(int set
)
790 struct togglelist
*c
;
792 for (c
= Togglelist
; c
->name
; c
++) {
795 printf("%-15s %s %s\n", c
->name
, set
? "enable" : "disable",
803 #define GETTOGGLE(name) (struct togglelist *) \
804 genget(name, (char **) Togglelist, sizeof(struct togglelist))
807 toggle(int argc
, char *argv
[])
811 struct togglelist
*c
;
815 "Need an argument to 'toggle' command. 'toggle ?' for help.\n");
824 fprintf(stderr
, "'%s': ambiguous argument ('toggle ?' for help).\n",
828 fprintf(stderr
, "'%s': unknown argument ('toggle ?' for help).\n",
833 *c
->variable
= !*c
->variable
; /* invert it */
834 if (c
->actionexplanation
) {
835 printf("%s %s.\n", *c
->variable
? "Will" : "Won't",
836 c
->actionexplanation
);
840 retval
&= (*c
->handler
)(-1);
848 * The following perform the "set" command.
852 struct termio new_tc
= { 0 };
856 const char *name
; /* name */
857 const char *help
; /* help information */
859 cc_t
*charp
; /* where it is located at */
862 static struct setlist Setlist
[] = {
863 #ifdef KLUDGELINEMODE
864 { "echo", "character to toggle local echoing on/off", 0, &echoc
},
866 { "escape", "character to escape back to telnet command mode", 0, &escape
},
867 { "rlogin", "rlogin escape character", 0, &rlogin
},
868 { "tracefile", "file to write trace information to", SetNetTrace
, (cc_t
*)NetTraceFile
},
870 { " ", "The following need 'localchars' to be toggled true", 0, 0 },
871 { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp
},
872 { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp
},
873 { "quit", "character to cause an Abort process", 0, termQuitCharp
},
874 { "eof", "character to cause an EOF ", 0, termEofCharp
},
876 { " ", "The following are for local editing in linemode", 0, 0 },
877 { "erase", "character to use to erase a character", 0, termEraseCharp
},
878 { "kill", "character to use to erase a line", 0, termKillCharp
},
879 { "lnext", "character to use for literal next", 0, termLiteralNextCharp
},
880 { "susp", "character to cause a Suspend Process", 0, termSuspCharp
},
881 { "reprint", "character to use for line reprint", 0, termRprntCharp
},
882 { "worderase", "character to use to erase a word", 0, termWerasCharp
},
883 { "start", "character to use for XON", 0, termStartCharp
},
884 { "stop", "character to use for XOFF", 0, termStopCharp
},
885 { "forw1", "alternate end of line character", 0, termForw1Charp
},
886 { "forw2", "alternate end of line character", 0, termForw2Charp
},
887 { "ayt", "alternate AYT character", 0, termAytCharp
},
891 #if defined(CRAY) && !defined(__STDC__)
892 /* Work around compiler bug in pcc 4.1.5 */
896 #ifndef KLUDGELINEMODE
901 Setlist
[N
+0].charp
= &termFlushChar
;
902 Setlist
[N
+1].charp
= &termIntChar
;
903 Setlist
[N
+2].charp
= &termQuitChar
;
904 Setlist
[N
+3].charp
= &termEofChar
;
905 Setlist
[N
+6].charp
= &termEraseChar
;
906 Setlist
[N
+7].charp
= &termKillChar
;
907 Setlist
[N
+8].charp
= &termLiteralNextChar
;
908 Setlist
[N
+9].charp
= &termSuspChar
;
909 Setlist
[N
+10].charp
= &termRprntChar
;
910 Setlist
[N
+11].charp
= &termWerasChar
;
911 Setlist
[N
+12].charp
= &termStartChar
;
912 Setlist
[N
+13].charp
= &termStopChar
;
913 Setlist
[N
+14].charp
= &termForw1Char
;
914 Setlist
[N
+15].charp
= &termForw2Char
;
915 Setlist
[N
+16].charp
= &termAytChar
;
918 #endif /* defined(CRAY) && !defined(__STDC__) */
920 static struct setlist
*
923 return (struct setlist
*)
924 genget(name
, (char **) Setlist
, sizeof(struct setlist
));
928 set_escape_char(char *s
)
930 if (rlogin
!= _POSIX_VDISABLE
) {
931 rlogin
= (s
&& *s
) ? special(s
) : _POSIX_VDISABLE
;
932 printf("Telnet rlogin escape character is '%s'.\n",
935 escape
= (s
&& *s
) ? special(s
) : _POSIX_VDISABLE
;
936 printf("Telnet escape character is '%s'.\n", control(escape
));
941 setcmd(int argc
, char *argv
[])
945 struct togglelist
*c
;
947 if (argc
< 2 || argc
> 3) {
948 printf("Format is 'set Name Value'\n'set ?' for help.\n");
951 if ((argc
== 2) && (isprefix(argv
[1], "?") || isprefix(argv
[1], "help"))) {
952 for (ct
= Setlist
; ct
->name
; ct
++)
953 printf("%-15s %s\n", ct
->name
, ct
->help
);
956 printf("%-15s %s\n", "?", "display help information");
960 ct
= getset(argv
[1]);
962 c
= GETTOGGLE(argv
[1]);
964 fprintf(stderr
, "'%s': unknown argument ('set ?' for help).\n",
967 } else if (Ambiguous(c
)) {
968 fprintf(stderr
, "'%s': ambiguous argument ('set ?' for help).\n",
973 if ((argc
== 2) || (strcmp("on", argv
[2]) == 0))
975 else if (strcmp("off", argv
[2]) == 0)
978 printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
981 if (c
->actionexplanation
) {
982 printf("%s %s.\n", *c
->variable
? "Will" : "Won't",
983 c
->actionexplanation
);
988 } else if (argc
!= 3) {
989 printf("Format is 'set Name Value'\n'set ?' for help.\n");
991 } else if (Ambiguous(ct
)) {
992 fprintf(stderr
, "'%s': ambiguous argument ('set ?' for help).\n",
995 } else if (ct
->handler
) {
996 (*ct
->handler
)(argv
[2]);
997 printf("%s set to \"%s\".\n", ct
->name
, (char *)ct
->charp
);
999 if (strcmp("off", argv
[2])) {
1000 value
= special(argv
[2]);
1002 value
= _POSIX_VDISABLE
;
1004 *(ct
->charp
) = (cc_t
)value
;
1005 printf("%s character is '%s'.\n", ct
->name
, control(*(ct
->charp
)));
1012 unsetcmd(int argc
, char *argv
[])
1015 struct togglelist
*c
;
1016 register char *name
;
1020 "Need an argument to 'unset' command. 'unset ?' for help.\n");
1023 if (isprefix(argv
[1], "?") || isprefix(argv
[1], "help")) {
1024 for (ct
= Setlist
; ct
->name
; ct
++)
1025 printf("%-15s %s\n", ct
->name
, ct
->help
);
1028 printf("%-15s %s\n", "?", "display help information");
1038 c
= GETTOGGLE(name
);
1040 fprintf(stderr
, "'%s': unknown argument ('unset ?' for help).\n",
1043 } else if (Ambiguous(c
)) {
1044 fprintf(stderr
, "'%s': ambiguous argument ('unset ?' for help).\n",
1050 if (c
->actionexplanation
) {
1051 printf("%s %s.\n", *c
->variable
? "Will" : "Won't",
1052 c
->actionexplanation
);
1057 } else if (Ambiguous(ct
)) {
1058 fprintf(stderr
, "'%s': ambiguous argument ('unset ?' for help).\n",
1061 } else if (ct
->handler
) {
1063 printf("%s reset to \"%s\".\n", ct
->name
, (char *)ct
->charp
);
1065 *(ct
->charp
) = _POSIX_VDISABLE
;
1066 printf("%s character is '%s'.\n", ct
->name
, control(*(ct
->charp
)));
1073 * The following are the data structures and routines for the
1076 #ifdef KLUDGELINEMODE
1077 extern int kludgelinemode
;
1083 send_wont(TELOPT_LINEMODE
, 1);
1084 send_dont(TELOPT_SGA
, 1);
1085 send_dont(TELOPT_ECHO
, 1);
1092 #ifdef KLUDGELINEMODE
1094 send_dont(TELOPT_SGA
, 1);
1096 send_will(TELOPT_LINEMODE
, 1);
1097 send_dont(TELOPT_ECHO
, 1);
1104 #ifdef KLUDGELINEMODE
1106 send_do(TELOPT_SGA
, 1);
1109 send_wont(TELOPT_LINEMODE
, 1);
1110 send_do(TELOPT_ECHO
, 1);
1119 extern int linemode
;
1121 if (my_want_state_is_wont(TELOPT_LINEMODE
)) {
1122 printf("?Need to have LINEMODE option enabled first.\n");
1123 printf("'mode ?' for help.\n");
1128 c
= (linemode
| bit
);
1130 c
= (linemode
& ~bit
);
1138 return dolmmode(bit
, 1);
1144 return dolmmode(bit
, 0);
1148 const char *name
; /* command name */
1149 const char *help
; /* help string */
1150 int (*handler
)(); /* routine which executes command */
1151 int needconnect
; /* Do we need to be connected to execute? */
1155 extern int modehelp();
1157 static struct modelist ModeList
[] = {
1158 { "character", "Disable LINEMODE option", docharmode
, 1 },
1159 #ifdef KLUDGELINEMODE
1160 { "", "(or disable obsolete line-by-line mode)", 0 },
1162 { "line", "Enable LINEMODE option", dolinemode
, 1 },
1163 #ifdef KLUDGELINEMODE
1164 { "", "(or enable obsolete line-by-line mode)", 0 },
1167 { "", "These require the LINEMODE option to be enabled", 0 },
1168 { "isig", "Enable signal trapping", set_mode
, 1, MODE_TRAPSIG
},
1169 { "+isig", 0, set_mode
, 1, MODE_TRAPSIG
},
1170 { "-isig", "Disable signal trapping", clear_mode
, 1, MODE_TRAPSIG
},
1171 { "edit", "Enable character editing", set_mode
, 1, MODE_EDIT
},
1172 { "+edit", 0, set_mode
, 1, MODE_EDIT
},
1173 { "-edit", "Disable character editing", clear_mode
, 1, MODE_EDIT
},
1174 { "softtabs", "Enable tab expansion", set_mode
, 1, MODE_SOFT_TAB
},
1175 { "+softtabs", 0, set_mode
, 1, MODE_SOFT_TAB
},
1176 { "-softtabs", "Disable character editing", clear_mode
, 1, MODE_SOFT_TAB
},
1177 { "litecho", "Enable literal character echo", set_mode
, 1, MODE_LIT_ECHO
},
1178 { "+litecho", 0, set_mode
, 1, MODE_LIT_ECHO
},
1179 { "-litecho", "Disable literal character echo", clear_mode
, 1, MODE_LIT_ECHO
},
1180 { "help", 0, modehelp
, 0 },
1181 #ifdef KLUDGELINEMODE
1182 { "kludgeline", 0, dokludgemode
, 1 },
1185 { "?", "Print help information", modehelp
, 0 },
1193 struct modelist
*mt
;
1195 printf("format is: 'mode Mode', where 'Mode' is one of:\n\n");
1196 for (mt
= ModeList
; mt
->name
; mt
++) {
1199 printf("%-15s %s\n", mt
->name
, mt
->help
);
1207 #define GETMODECMD(name) (struct modelist *) \
1208 genget(name, (char **) ModeList, sizeof(struct modelist))
1211 modecmd(int argc
, char *argv
[])
1213 struct modelist
*mt
;
1216 printf("'mode' command requires an argument\n");
1217 printf("'mode ?' for help.\n");
1218 } else if ((mt
= GETMODECMD(argv
[1])) == 0) {
1219 fprintf(stderr
, "Unknown mode '%s' ('mode ?' for help).\n", argv
[1]);
1220 } else if (Ambiguous(mt
)) {
1221 fprintf(stderr
, "Ambiguous mode '%s' ('mode ?' for help).\n", argv
[1]);
1222 } else if (mt
->needconnect
&& !connected
) {
1223 printf("?Need to be connected first.\n");
1224 printf("'mode ?' for help.\n");
1225 } else if (mt
->handler
) {
1226 return (*mt
->handler
)(mt
->arg1
);
1232 * The following data structures and routines implement the
1233 * "display" command.
1237 display(int argc
, char *argv
[])
1239 struct togglelist
*tl
;
1242 #define dotog(tl) if (tl->variable && tl->actionexplanation) { \
1243 if (*tl->variable) { \
1248 printf(" %s.\n", tl->actionexplanation); \
1251 #define doset(sl) if (sl->name && *sl->name != ' ') { \
1252 if (sl->handler == 0) \
1253 printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
1255 printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
1259 for (tl
= Togglelist
; tl
->name
; tl
++) {
1263 for (sl
= Setlist
; sl
->name
; sl
++) {
1269 for (i
= 1; i
< argc
; i
++) {
1270 sl
= getset(argv
[i
]);
1271 tl
= GETTOGGLE(argv
[i
]);
1272 if (Ambiguous(sl
) || Ambiguous(tl
)) {
1273 printf("?Ambiguous argument '%s'.\n", argv
[i
]);
1275 } else if (!sl
&& !tl
) {
1276 printf("?Unknown argument '%s'.\n", argv
[i
]);
1288 /*@*/optionstatus();
1291 #endif /* ENCRYPTION */
1298 * The following are the data structures, and many of the routines,
1299 * relating to command processing.
1303 * Set the escape character.
1306 setescape(int argc
, char *argv
[])
1312 "Deprecated usage - please use 'set escape%s%s' in the future.\n",
1313 (argc
> 2)? " ":"", (argc
> 2)? argv
[1]: "");
1317 printf("new escape character: ");
1318 (void) fgets(buf
, sizeof(buf
), stdin
);
1324 printf("Escape character is '%s'.\n", control(escape
));
1326 (void) fflush(stdout
);
1335 printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
1336 printf("%s map carriage return on output.\n", crmod
? "Will" : "Won't");
1337 (void) fflush(stdout
);
1348 long oldrows
, oldcols
, newrows
, newcols
, err
;
1350 err
= (TerminalWindowSize(&oldrows
, &oldcols
) == 0) ? 1 : 0;
1351 (void) kill(0, SIGTSTP
);
1353 * If we didn't get the window size before the SUSPEND, but we
1354 * can get them now (?), then send the NAWS to make sure that
1355 * we are set up for the right window size.
1357 if (TerminalWindowSize(&newrows
, &newcols
) && connected
&&
1358 (err
|| ((oldrows
!= newrows
) || (oldcols
!= newcols
)))) {
1362 /* reget parameters in case they were changed */
1363 TerminalSaveState();
1366 printf("Suspend is not supported. Try the '!' command instead\n");
1371 #if !defined(TN3270)
1374 shell(int argc
, char *argv
[])
1376 long oldrows
, oldcols
, newrows
, newcols
, err
;
1380 err
= (TerminalWindowSize(&oldrows
, &oldcols
) == 0) ? 1 : 0;
1383 perror("Fork failed\n");
1389 * Fire up the shell in the child.
1391 register char *shellp
, *shellname
;
1393 extern char *strrchr();
1396 shellp
= getenv("SHELL");
1399 if ((shellname
= strrchr(shellp
, '/')) == 0)
1404 execl(shellp
, shellname
, "-c", &saveline
[1], 0);
1406 execl(shellp
, shellname
, 0);
1411 (void)wait((int *)0); /* Wait for the shell to complete */
1413 if (TerminalWindowSize(&newrows
, &newcols
) && connected
&&
1414 (err
|| ((oldrows
!= newrows
) || (oldcols
!= newcols
)))) {
1421 #else /* !defined(TN3270) */
1423 #endif /* !defined(TN3270) */
1426 /* int argc; Number of arguments */
1427 /* char *argv[]; arguments */
1429 bye(int argc
, char *argv
[])
1431 extern int resettermname
;
1434 (void) shutdown(net
, 2);
1435 printf("Connection closed.\n");
1436 (void) NetClose(net
);
1439 #if defined(AUTHENTICATION) || defined(ENCRYPTION)
1440 auth_encrypt_connect(connected
);
1441 #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1445 SetIn3270(); /* Get out of 3270 mode */
1446 #endif /* defined(TN3270) */
1448 if ((argc
!= 2) || (strcmp(argv
[1], "fromquit") != 0)) {
1449 longjmp(toplevel
, 1);
1452 return 1; /* Keep lint, etc., happy */
1459 (void) call(bye
, "bye", "fromquit", 0);
1468 send_do(TELOPT_LOGOUT
, 1);
1485 static void slc_help();
1487 struct slclist SlcList
[] = {
1488 { "export", "Use local special character definitions",
1489 slc_mode_export
, 0 },
1490 { "import", "Use remote special character definitions",
1491 slc_mode_import
, 1 },
1492 { "check", "Verify remote special character definitions",
1493 slc_mode_import
, 0 },
1494 { "help", 0, slc_help
, 0 },
1495 { "?", "Print help information", slc_help
, 0 },
1504 for (c
= SlcList
; c
->name
; c
++) {
1507 printf("%-15s %s\n", c
->name
, c
->help
);
1514 static struct slclist
*
1518 return (struct slclist
*)
1519 genget(name
, (char **) SlcList
, sizeof(struct slclist
));
1531 "Need an argument to 'slc' command. 'slc ?' for help.\n");
1534 c
= getslc(argv
[1]);
1536 fprintf(stderr
, "'%s': unknown argument ('slc ?' for help).\n",
1541 fprintf(stderr
, "'%s': ambiguous argument ('slc ?' for help).\n",
1545 (*c
->handler
)(c
->arg
);
1551 * The ENVIRON command.
1561 extern struct env_lst
*
1562 env_define
P((unsigned char *, unsigned char *));
1564 env_undefine
P((unsigned char *)),
1565 env_export
P((unsigned char *)),
1566 env_unexport
P((unsigned char *)),
1567 env_send
P((unsigned char *)),
1568 #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1569 env_varval
P((unsigned char *)),
1575 struct envlist EnvList
[] = {
1576 { "define", "Define an environment variable",
1577 (void (*)())env_define
, 2 },
1578 { "undefine", "Undefine an environment variable",
1580 { "export", "Mark an environment variable for automatic export",
1582 { "unexport", "Don't mark an environment variable for automatic export",
1584 { "send", "Send an environment variable", env_send
, 1 },
1585 { "list", "List the current environment variables",
1587 #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1588 { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
1591 { "help", 0, env_help
, 0 },
1592 { "?", "Print help information", env_help
, 0 },
1601 for (c
= EnvList
; c
->name
; c
++) {
1604 printf("%-15s %s\n", c
->name
, c
->help
);
1611 static struct envlist
*
1612 getenvcmd(char *name
)
1614 return (struct envlist
*)
1615 genget(name
, (char **) EnvList
, sizeof(struct envlist
));
1619 env_cmd(int argc
, char *argv
[])
1625 "Need an argument to 'environ' command. 'environ ?' for help.\n");
1628 c
= getenvcmd(argv
[1]);
1630 fprintf(stderr
, "'%s': unknown argument ('environ ?' for help).\n",
1635 fprintf(stderr
, "'%s': ambiguous argument ('environ ?' for help).\n",
1639 if (c
->narg
+ 2 != argc
) {
1641 "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n",
1642 c
->narg
< argc
+ 2 ? "only " : "",
1643 c
->narg
, c
->narg
== 1 ? "" : "s", c
->name
);
1646 (*c
->handler
)(argv
[2], argv
[3]);
1651 struct env_lst
*next
; /* pointer to next structure */
1652 struct env_lst
*prev
; /* pointer to previous structure */
1653 unsigned char *var
; /* pointer to variable name */
1654 unsigned char *value
; /* pointer to variable value */
1655 int export
; /* 1 -> export with default list of variables */
1656 int welldefined
; /* A well defined variable */
1659 struct env_lst envlisthead
;
1662 env_find(unsigned char *var
)
1664 register struct env_lst
*ep
;
1666 for (ep
= envlisthead
.next
; ep
; ep
= ep
->next
) {
1667 if (strcmp((char *)ep
->var
, (char *)var
) == 0)
1676 extern char **environ
;
1677 register char **epp
, *cp
;
1678 register struct env_lst
*ep
;
1680 extern char *strchr();
1683 for (epp
= environ
; *epp
; epp
++) {
1684 if (cp
= strchr(*epp
, '=')) {
1686 ep
= env_define((unsigned char *)*epp
,
1687 (unsigned char *)cp
+1);
1693 * Special case for DISPLAY variable. If it is ":0.0" or
1694 * "unix:0.0", we have to get rid of "unix" and insert our
1697 if ((ep
= env_find("DISPLAY"))
1698 && ((*ep
->value
== ':')
1699 || (strncmp((char *)ep
->value
, "unix:", 5) == 0))) {
1700 extern char *localhost ();
1701 char *hostname
= localhost ();
1702 char *cp2
= strchr((char *)ep
->value
, ':');
1704 cp
= malloc(strlen(hostname
) + strlen(cp2
) + 1);
1705 sprintf(cp
, "%s%s", hostname
, cp2
);
1708 ep
->value
= (unsigned char *)cp
;
1713 * If USER is not defined, but LOGNAME is, then add
1714 * USER with the value from LOGNAME. By default, we
1715 * don't export the USER variable.
1717 if ((env_find("USER") == NULL
) && (ep
= env_find("LOGNAME"))) {
1718 env_define((unsigned char *)"USER", ep
->value
);
1719 env_unexport((unsigned char *)"USER");
1721 env_export((unsigned char *)"DISPLAY");
1722 env_export((unsigned char *)"PRINTER");
1726 env_define(unsigned char *var
, unsigned char *value
)
1728 register struct env_lst
*ep
;
1730 if (ep
= env_find(var
)) {
1736 ep
= (struct env_lst
*)malloc(sizeof(struct env_lst
));
1737 ep
->next
= envlisthead
.next
;
1738 envlisthead
.next
= ep
;
1739 ep
->prev
= &envlisthead
;
1741 ep
->next
->prev
= ep
;
1743 ep
->welldefined
= opt_welldefined(var
);
1745 ep
->var
= (unsigned char *)strdup((char *)var
);
1746 ep
->value
= (unsigned char *)strdup((char *)value
);
1751 env_undefine(unsigned char *var
)
1753 register struct env_lst
*ep
;
1755 if (ep
= env_find(var
)) {
1756 ep
->prev
->next
= ep
->next
;
1758 ep
->next
->prev
= ep
->prev
;
1768 env_export(unsigned char *var
)
1770 register struct env_lst
*ep
;
1772 if (ep
= env_find(var
))
1777 env_unexport(unsigned char *var
)
1779 register struct env_lst
*ep
;
1781 if (ep
= env_find(var
))
1786 env_send(unsigned char *var
)
1788 register struct env_lst
*ep
;
1790 if (my_state_is_wont(TELOPT_NEW_ENVIRON
)
1792 && my_state_is_wont(TELOPT_OLD_ENVIRON
)
1796 "Cannot send '%s': Telnet ENVIRON option not enabled\n",
1802 fprintf(stderr
, "Cannot send '%s': variable not defined\n",
1806 env_opt_start_info();
1807 env_opt_add(ep
->var
);
1814 register struct env_lst
*ep
;
1816 for (ep
= envlisthead
.next
; ep
; ep
= ep
->next
) {
1817 printf("%c %-20s %s\n", ep
->export
? '*' : ' ',
1818 ep
->var
, ep
->value
);
1823 env_default(int init
, int welldefined
)
1825 static struct env_lst
*nep
= NULL
;
1832 while (nep
= nep
->next
) {
1833 if (nep
->export
&& (nep
->welldefined
== welldefined
))
1841 env_getvalue(unsigned char *var
)
1843 register struct env_lst
*ep
;
1845 if (ep
= env_find(var
))
1850 #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1852 env_varval(unsigned char *what
)
1854 extern int old_env_var
, old_env_value
, env_auto
;
1855 int len
= strlen((char *)what
);
1860 if (strncasecmp((char *)what
, "status", len
) == 0) {
1862 printf("%s%s", "VAR and VALUE are/will be ",
1863 "determined automatically\n");
1864 if (old_env_var
== OLD_ENV_VAR
)
1865 printf("VAR and VALUE set to correct definitions\n");
1867 printf("VAR and VALUE definitions are reversed\n");
1868 } else if (strncasecmp((char *)what
, "auto", len
) == 0) {
1870 old_env_var
= OLD_ENV_VALUE
;
1871 old_env_value
= OLD_ENV_VAR
;
1872 } else if (strncasecmp((char *)what
, "right", len
) == 0) {
1874 old_env_var
= OLD_ENV_VAR
;
1875 old_env_value
= OLD_ENV_VALUE
;
1876 } else if (strncasecmp((char *)what
, "wrong", len
) == 0) {
1878 old_env_var
= OLD_ENV_VALUE
;
1879 old_env_value
= OLD_ENV_VAR
;
1882 printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
1887 #if defined(AUTHENTICATION)
1889 * The AUTHENTICATE command.
1900 auth_enable
P((char *)),
1901 auth_disable
P((char *)),
1902 auth_status
P((void));
1904 auth_help
P((void));
1906 struct authlist AuthList
[] = {
1907 { "status", "Display current status of authentication information",
1909 { "disable", "Disable an authentication type ('auth disable ?' for more)",
1911 { "enable", "Enable an authentication type ('auth enable ?' for more)",
1913 { "help", 0, auth_help
, 0 },
1914 { "?", "Print help information", auth_help
, 0 },
1923 for (c
= AuthList
; c
->name
; c
++) {
1926 printf("%-15s %s\n", c
->name
, c
->help
);
1935 auth_cmd(int argc
, char *argv
[])
1941 "Need an argument to 'auth' command. 'auth ?' for help.\n");
1945 c
= (struct authlist
*)
1946 genget(argv
[1], (char **) AuthList
, sizeof(struct authlist
));
1948 fprintf(stderr
, "'%s': unknown argument ('auth ?' for help).\n",
1953 fprintf(stderr
, "'%s': ambiguous argument ('auth ?' for help).\n",
1957 if (c
->narg
+ 2 != argc
) {
1959 "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n",
1960 c
->narg
< argc
+ 2 ? "only " : "",
1961 c
->narg
, c
->narg
== 1 ? "" : "s", c
->name
);
1964 return((*c
->handler
)(argv
[2], argv
[3]));
1970 * The ENCRYPT command.
1973 struct encryptlist
{
1983 EncryptEnable
P((char *, char *)),
1984 EncryptDisable
P((char *, char *)),
1985 EncryptType
P((char *, char *)),
1986 EncryptStart
P((char *)),
1987 EncryptStartInput
P((void)),
1988 EncryptStartOutput
P((void)),
1989 EncryptStop
P((char *)),
1990 EncryptStopInput
P((void)),
1991 EncryptStopOutput
P((void)),
1992 EncryptStatus
P((void));
1994 EncryptHelp
P((void));
1996 struct encryptlist EncryptList
[] = {
1997 { "enable", "Enable encryption. ('encrypt enable ?' for more)",
1998 EncryptEnable
, 1, 1, 2 },
1999 { "disable", "Disable encryption. ('encrypt enable ?' for more)",
2000 EncryptDisable
, 0, 1, 2 },
2001 { "type", "Set encryption type. ('encrypt type ?' for more)",
2002 EncryptType
, 0, 1, 1 },
2003 { "start", "Start encryption. ('encrypt start ?' for more)",
2004 EncryptStart
, 1, 0, 1 },
2005 { "stop", "Stop encryption. ('encrypt stop ?' for more)",
2006 EncryptStop
, 1, 0, 1 },
2007 { "input", "Start encrypting the input stream",
2008 EncryptStartInput
, 1, 0, 0 },
2009 { "-input", "Stop encrypting the input stream",
2010 EncryptStopInput
, 1, 0, 0 },
2011 { "output", "Start encrypting the output stream",
2012 EncryptStartOutput
, 1, 0, 0 },
2013 { "-output", "Stop encrypting the output stream",
2014 EncryptStopOutput
, 1, 0, 0 },
2016 { "status", "Display current status of authentication information",
2017 EncryptStatus
, 0, 0, 0 },
2018 { "help", 0, EncryptHelp
, 0, 0, 0 },
2019 { "?", "Print help information", EncryptHelp
, 0, 0, 0 },
2026 struct encryptlist
*c
;
2028 for (c
= EncryptList
; c
->name
; c
++) {
2031 printf("%-15s %s\n", c
->name
, c
->help
);
2040 encrypt_cmd(int argc
, char *argv
[])
2042 struct encryptlist
*c
;
2046 "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n");
2050 c
= (struct encryptlist
*)
2051 genget(argv
[1], (char **) EncryptList
, sizeof(struct encryptlist
));
2053 fprintf(stderr
, "'%s': unknown argument ('encrypt ?' for help).\n",
2058 fprintf(stderr
, "'%s': ambiguous argument ('encrypt ?' for help).\n",
2063 if (argc
< c
->minarg
|| argc
> c
->maxarg
) {
2064 if (c
->minarg
== c
->maxarg
) {
2065 fprintf(stderr
, "Need %s%d argument%s ",
2066 c
->minarg
< argc
? "only " : "", c
->minarg
,
2067 c
->minarg
== 1 ? "" : "s");
2069 fprintf(stderr
, "Need %s%d-%d arguments ",
2070 c
->maxarg
< argc
? "only " : "", c
->minarg
, c
->maxarg
);
2072 fprintf(stderr
, "to 'encrypt %s' command. 'encrypt ?' for help.\n",
2076 if (c
->needconnect
&& !connected
) {
2077 if (!(argc
&& (isprefix(argv
[2], "help") || isprefix(argv
[2], "?")))) {
2078 printf("?Need to be connected first.\n");
2082 return ((*c
->handler
)(argc
> 0 ? argv
[2] : 0,
2083 argc
> 1 ? argv
[3] : 0,
2084 argc
> 2 ? argv
[4] : 0));
2086 #endif /* ENCRYPTION */
2088 #if defined(unix) && defined(TN3270)
2096 res
= fcntl(fd
, F_GETOWN
, 0);
2103 printf("\tOwner is %d.\n", res
);
2107 res
= fcntl(fd
, F_GETFL
, 0);
2115 printf("\tFlags are 0x%x: %s\n", res
, decodeflags(res
));
2118 #endif /* defined(unix) && defined(TN3270) */
2121 * Print status about the connection.
2125 status(int argc
, char *argv
[])
2128 printf("Connected to %s.\n", hostname
);
2129 if ((argc
< 2) || strcmp(argv
[1], "notmuch")) {
2130 int mode
= getconnmode();
2132 if (my_want_state_is_will(TELOPT_LINEMODE
)) {
2133 printf("Operating with LINEMODE option\n");
2134 printf("%s line editing\n", (mode
&MODE_EDIT
) ? "Local" : "No");
2135 printf("%s catching of signals\n",
2136 (mode
&MODE_TRAPSIG
) ? "Local" : "No");
2138 #ifdef KLUDGELINEMODE
2139 } else if (kludgelinemode
&& my_want_state_is_dont(TELOPT_SGA
)) {
2140 printf("Operating in obsolete linemode\n");
2143 printf("Operating in single character mode\n");
2145 printf("Catching signals locally\n");
2147 printf("%s character echo\n", (mode
&MODE_ECHO
) ? "Local" : "Remote");
2148 if (my_want_state_is_will(TELOPT_LFLOW
))
2149 printf("%s flow control\n", (mode
&MODE_FLOW
) ? "Local" : "No");
2152 #endif /* ENCRYPTION */
2155 printf("No connection.\n");
2157 # if !defined(TN3270)
2158 printf("Escape character is '%s'.\n", control(escape
));
2159 (void) fflush(stdout
);
2160 # else /* !defined(TN3270) */
2161 if ((!In3270
) && ((argc
< 2) || strcmp(argv
[1], "notmuch"))) {
2162 printf("Escape character is '%s'.\n", control(escape
));
2165 if ((argc
>= 2) && !strcmp(argv
[1], "everything")) {
2166 printf("SIGIO received %d time%s.\n",
2167 sigiocount
, (sigiocount
== 1)? "":"s");
2169 printf("Process ID %d, process group %d.\n",
2170 getpid(), getpgrp(getpid()));
2171 printf("Terminal input:\n");
2173 printf("Terminal output:\n");
2175 printf("Network socket:\n");
2179 if (In3270
&& transcom
) {
2180 printf("Transparent mode command is '%s'.\n", transcom
);
2182 # endif /* defined(unix) */
2183 (void) fflush(stdout
);
2187 # endif /* defined(TN3270) */
2193 * Function that gets called when SIGINFO is received.
2198 (void) call(status
, "status", "notmuch", 0);
2202 unsigned long inet_addr();
2205 tn(int argc
, char *argv
[])
2207 register struct hostent
*host
= 0;
2208 struct sockaddr_in sin
;
2209 struct servent
*sp
= 0;
2211 extern char *inet_ntoa();
2212 #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2217 unsigned long sourceroute(), srlen
;
2219 char *cmd
, *hostp
= 0, *portp
= 0, *user
= 0;
2221 /* clear the socket address prior to use */
2222 memset((char *)&sin
, 0, sizeof(sin
));
2225 printf("?Already connected to %s\n", hostname
);
2230 (void) strcpy(line
, "open ");
2232 (void) fgets(&line
[strlen(line
)], sizeof(line
) - strlen(line
), stdin
);
2240 if (strcmp(*argv
, "help") == 0 || isprefix(*argv
, "?"))
2242 if (strcmp(*argv
, "-l") == 0) {
2250 if (strcmp(*argv
, "-a") == 0) {
2266 printf("usage: %s [-l user] [-a] host-name [port]\n", cmd
);
2273 #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2274 if (hostp
[0] == '@' || hostp
[0] == '!') {
2275 if ((hostname
= strrchr(hostp
, ':')) == NULL
)
2276 hostname
= strrchr(hostp
, '@');
2279 temp
= sourceroute(hostp
, &srp
, &srlen
);
2284 } else if (temp
== -1) {
2285 printf("Bad source route option: %s\n", hostp
);
2289 sin
.sin_addr
.s_addr
= temp
;
2290 sin
.sin_family
= AF_INET
;
2294 temp
= inet_addr(hostp
);
2295 if (temp
!= (unsigned long) -1) {
2296 sin
.sin_addr
.s_addr
= temp
;
2297 sin
.sin_family
= AF_INET
;
2301 _hostname
= malloc (strlen (hostp
) + 1);
2303 strcpy (_hostname
, hostp
);
2304 hostname
= _hostname
;
2306 printf ("Can't allocate memory to copy hostname\n");
2311 host
= gethostbyname(hostp
);
2313 sin
.sin_family
= host
->h_addrtype
;
2314 #if defined(h_addr) /* In 4.3, this is a #define */
2315 memmove((caddr_t
)&sin
.sin_addr
,
2316 host
->h_addr_list
[0], host
->h_length
);
2317 #else /* defined(h_addr) */
2318 memmove((caddr_t
)&sin
.sin_addr
, host
->h_addr
, host
->h_length
);
2319 #endif /* defined(h_addr) */
2323 _hostname
= malloc (strlen (host
->h_name
) + 1);
2325 strcpy (_hostname
, host
->h_name
);
2326 hostname
= _hostname
;
2328 printf ("Can't allocate memory to copy hostname\n");
2338 #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2342 if (*portp
== '-') {
2347 sin
.sin_port
= atoi(portp
);
2348 if (sin
.sin_port
== 0) {
2349 sp
= getservbyname(portp
, "tcp");
2351 sin
.sin_port
= sp
->s_port
;
2353 printf("%s: bad port number\n", portp
);
2358 #if !HAVE_DECL_HTONS
2360 u_short htons
__P((unsigned short));
2363 sin
.sin_port
= htons (sin
.sin_port
);
2367 sp
= getservbyname("telnet", "tcp");
2369 fprintf(stderr
, "telnet: tcp/telnet: unknown service\n");
2373 sin
.sin_port
= sp
->s_port
;
2377 printf("Trying %s...\n", inet_ntoa(sin
.sin_addr
));
2379 net
= socket(AF_INET
, SOCK_STREAM
, 0);
2382 perror("telnet: socket");
2385 #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2386 if (srp
&& setsockopt(net
, IPPROTO_IP
, IP_OPTIONS
, (char *)srp
, srlen
) < 0)
2387 perror("setsockopt (IP_OPTIONS)");
2389 #if defined(IPPROTO_IP) && defined(IP_TOS)
2391 # if defined(HAS_GETTOS)
2393 if (tos
< 0 && (tp
= gettosbyname("telnet", "tcp")))
2397 tos
= 020; /* Low Delay bit */
2399 && (setsockopt(net
, IPPROTO_IP
, IP_TOS
,
2400 (char *)&tos
, sizeof(int)) < 0)
2401 && (errno
!= ENOPROTOOPT
))
2402 perror("telnet: setsockopt (IP_TOS) (ignored)");
2404 #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
2406 if (debug
&& SetSockOpt(net
, SOL_SOCKET
, SO_DEBUG
, 1) < 0) {
2407 perror("setsockopt (SO_DEBUG)");
2410 if (connect(net
, (struct sockaddr
*)&sin
, sizeof (sin
)) < 0) {
2411 #if defined(h_addr) /* In 4.3, this is a #define */
2412 if (host
&& host
->h_addr_list
[1]) {
2415 fprintf(stderr
, "telnet: connect to address %s: ",
2416 inet_ntoa(sin
.sin_addr
));
2419 host
->h_addr_list
++;
2420 memmove((caddr_t
)&sin
.sin_addr
,
2421 host
->h_addr_list
[0], host
->h_length
);
2422 (void) NetClose(net
);
2425 #endif /* defined(h_addr) */
2426 perror("telnet: Unable to connect to remote host");
2430 #if defined(AUTHENTICATION) || defined(ENCRYPTION)
2431 auth_encrypt_connect(connected
);
2432 #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
2433 } while (connected
== 0);
2434 cmdrc(hostp
, hostname
);
2435 if (autologin
&& user
== NULL
) {
2438 user
= getenv("USER");
2440 (pw
= getpwnam(user
)) && pw
->pw_uid
!= getuid()) {
2441 if (pw
= getpwuid(getuid()))
2448 env_define((unsigned char *)"USER", (unsigned char *)user
);
2449 env_export((unsigned char *)"USER");
2451 (void) call(status
, "status", "notmuch", 0);
2452 if (setjmp(peerdied
) == 0)
2454 (void) NetClose(net
);
2455 ExitString("Connection closed by foreign host.\n",1);
2459 #define HELPINDENT (sizeof ("connect"))
2462 openhelp
[] = "connect to a site",
2463 closehelp
[] = "close current connection",
2464 logouthelp
[] = "forcibly logout remote user and close the connection",
2465 quithelp
[] = "exit telnet",
2466 statushelp
[] = "print status information",
2467 helphelp
[] = "print help information",
2468 sendhelp
[] = "transmit special characters ('send ?' for more)",
2469 sethelp
[] = "set operating parameters ('set ?' for more)",
2470 unsethelp
[] = "unset operating parameters ('unset ?' for more)",
2471 togglestring
[] ="toggle operating parameters ('toggle ?' for more)",
2472 slchelp
[] = "change state of special charaters ('slc ?' for more)",
2473 displayhelp
[] = "display operating parameters",
2474 #if defined(TN3270) && defined(unix)
2475 transcomhelp
[] = "specify Unix command for transparent mode pipe",
2476 #endif /* defined(TN3270) && defined(unix) */
2477 #if defined(AUTHENTICATION)
2478 authhelp
[] = "turn on (off) authentication ('auth ?' for more)",
2481 encrypthelp
[] = "turn on (off) encryption ('encrypt ?' for more)",
2482 #endif /* ENCRYPTION */
2484 zhelp
[] = "suspend telnet",
2485 #endif /* defined(unix) */
2486 shellhelp
[] = "invoke a subshell",
2487 envhelp
[] = "change environment variables ('environ ?' for more)",
2488 modestring
[] = "try to enter line or character mode ('mode ?' for more)";
2492 static Command cmdtab
[] = {
2493 { "close", closehelp
, bye
, 1 },
2494 { "logout", logouthelp
, logout
, 1 },
2495 { "display", displayhelp
, display
, 0 },
2496 { "mode", modestring
, modecmd
, 0 },
2497 { "open", openhelp
, tn
, 0 },
2498 { "quit", quithelp
, quit
, 0 },
2499 { "send", sendhelp
, sendcmd
, 0 },
2500 { "set", sethelp
, setcmd
, 0 },
2501 { "unset", unsethelp
, unsetcmd
, 0 },
2502 { "status", statushelp
, status
, 0 },
2503 { "toggle", togglestring
, toggle
, 0 },
2504 { "slc", slchelp
, slccmd
, 0 },
2505 #if defined(TN3270) && defined(unix)
2506 { "transcom", transcomhelp
, settranscom
, 0 },
2507 #endif /* defined(TN3270) && defined(unix) */
2508 #if defined(AUTHENTICATION)
2509 { "auth", authhelp
, auth_cmd
, 0 },
2512 { "encrypt", encrypthelp
, encrypt_cmd
, 0 },
2513 #endif /* ENCRYPTION */
2515 { "z", zhelp
, suspend
, 0 },
2516 #endif /* defined(unix) */
2518 { "!", shellhelp
, shell
, 1 },
2520 { "!", shellhelp
, shell
, 0 },
2522 { "environ", envhelp
, env_cmd
, 0 },
2523 { "?", helphelp
, help
, 0 },
2527 static char crmodhelp
[] = "deprecated command -- use 'toggle crmod' instead";
2528 static char escapehelp
[] = "deprecated command -- use 'set escape' instead";
2530 static Command cmdtab2
[] = {
2531 { "help", 0, help
, 0 },
2532 { "escape", escapehelp
, setescape
, 0 },
2533 { "crmod", crmodhelp
, togcrmod
, 0 },
2539 * Call routine with argc, argv set from args (terminated by 0).
2544 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
2545 call(intrtn_t routine
, ...)
2552 #if !(defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__)
2558 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
2559 va_start(ap
, routine
);
2562 routine
= (va_arg(ap
, intrtn_t
));
2564 while ((args
[argno
++] = va_arg(ap
, char *)) != 0) {
2568 return (*routine
)(argno
-1, args
);
2577 if (cm
= (Command
*) genget(name
, (char **) cmdtab
, sizeof(Command
)))
2579 return (Command
*) genget(name
, (char **) cmdtab2
, sizeof(Command
));
2583 command(int top
, char *tbuf
, int cnt
)
2585 register Command
*c
;
2592 (void) signal(SIGINT
, SIG_DFL
);
2593 (void) signal(SIGQUIT
, SIG_DFL
);
2594 #endif /* defined(unix) */
2597 if (rlogin
== _POSIX_VDISABLE
)
2598 printf("%s> ", prompt
);
2602 while (cnt
> 0 && (*cp
++ = *tbuf
++) != '\n')
2605 if (cp
== line
|| *--cp
!= '\n' || cp
== line
)
2608 if (rlogin
== _POSIX_VDISABLE
)
2609 printf("%s\n", line
);
2612 if (rlogin
!= _POSIX_VDISABLE
)
2613 printf("%s> ", prompt
);
2614 if (fgets(line
, sizeof(line
), stdin
) == NULL
) {
2615 if (feof(stdin
) || ferror(stdin
)) {
2625 if (margv
[0] == 0) {
2628 c
= getcmd(margv
[0]);
2630 printf("?Ambiguous command\n");
2634 printf("?Invalid command\n");
2637 if (c
->needconnect
&& !connected
) {
2638 printf("?Need to be connected first.\n");
2641 if ((*c
->handler
)(margc
, margv
)) {
2647 longjmp(toplevel
, 1);
2651 if (shell_active
== 0) {
2654 #else /* defined(TN3270) */
2656 #endif /* defined(TN3270) */
2664 help(int argc
, char *argv
[])
2666 register Command
*c
;
2669 printf("Commands may be abbreviated. Commands are:\n\n");
2670 for (c
= cmdtab
; c
->name
; c
++)
2672 printf("%-*s\t%s\n", HELPINDENT
, c
->name
,
2677 while (--argc
> 0) {
2682 printf("?Ambiguous help command %s\n", arg
);
2683 else if (c
== (Command
*)0)
2684 printf("?Invalid help command %s\n", arg
);
2686 printf("%s\n", c
->help
);
2691 static char *rcname
= 0;
2692 static char rcbuf
[128];
2695 cmdrc(char *m1
, char *m2
)
2697 register Command
*c
;
2700 int l1
= strlen(m1
);
2701 int l2
= strlen(m2
);
2711 rcname
= getenv("HOME");
2713 strcpy(rcbuf
, rcname
);
2716 strcat(rcbuf
, "/.telnetrc");
2720 if ((rcfile
= fopen(rcname
, "r")) == 0) {
2725 if (fgets(line
, sizeof(line
), rcfile
) == NULL
)
2732 if (!isspace(line
[0]))
2735 if (gotmachine
== 0) {
2736 if (isspace(line
[0]))
2738 if (strncasecmp(line
, m1
, l1
) == 0)
2739 strncpy(line
, &line
[l1
], sizeof(line
) - l1
);
2740 else if (strncasecmp(line
, m2
, l2
) == 0)
2741 strncpy(line
, &line
[l2
], sizeof(line
) - l2
);
2742 else if (strncasecmp(line
, "DEFAULT", 7) == 0)
2743 strncpy(line
, &line
[7], sizeof(line
) - 7);
2746 if (line
[0] != ' ' && line
[0] != '\t' && line
[0] != '\n')
2753 c
= getcmd(margv
[0]);
2755 printf("?Ambiguous command: %s\n", margv
[0]);
2759 printf("?Invalid command: %s\n", margv
[0]);
2763 * This should never happen...
2765 if (c
->needconnect
&& !connected
) {
2766 printf("?Need to be connected first for %s.\n", margv
[0]);
2769 (*c
->handler
)(margc
, margv
);
2774 #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2777 * Source route is handed in as
2778 * [!]@hop1@hop2...[@|:]dst
2779 * If the leading ! is present, it is a
2780 * strict source route, otherwise it is
2781 * assmed to be a loose source route.
2783 * We fill in the source route option as
2784 * hop1,hop2,hop3...dest
2785 * and return a pointer to hop1, which will
2786 * be the address to connect() to.
2789 * arg: pointer to route list to decipher
2791 * cpp: If *cpp is not equal to NULL, this is a
2792 * pointer to a pointer to a character array
2793 * that should be filled in with the option.
2795 * lenp: pointer to an integer that contains the
2796 * length of *cpp if *cpp != NULL.
2800 * Returns the address of the host to connect to. If the
2801 * return value is -1, there was a syntax error in the
2802 * option, either unknown characters, or too many hosts.
2803 * If the return value is 0, one of the hostnames in the
2804 * path is unknown, and *cpp is set to point to the bad
2807 * *cpp: If *cpp was equal to NULL, it will be filled
2808 * in with a pointer to our static area that has
2809 * the option filled in. This will be 32bit aligned.
2811 * *lenp: This will be filled in with how long the option
2812 * pointed to by *cpp is.
2816 sourceroute(char *arg
, char **cpp
, int *lenp
)
2818 static char lsr
[44];
2822 char *cp
, *cp2
, *lsrp
, *lsrep
;
2824 struct in_addr sin_addr
;
2825 register struct hostent
*host
= 0;
2829 * Verify the arguments, and make sure we have
2830 * at least 7 bytes for the option.
2832 if (cpp
== NULL
|| lenp
== NULL
)
2833 return((unsigned long)-1);
2834 if (*cpp
!= NULL
&& *lenp
< 7)
2835 return((unsigned long)-1);
2837 * Decide whether we have a buffer passed to us,
2838 * or if we need to use our own static buffer.
2842 lsrep
= lsrp
+ *lenp
;
2851 * Next, decide whether we have a loose source
2852 * route or a strict source route, and fill in
2853 * the begining of the option.
2858 *lsrp
++ = IPOPT_SSRR
;
2860 *lsrp
++ = IPOPT_LSRR
;
2864 ipopt
.io_type
= IPOPT_SSRR
;
2866 ipopt
.io_type
= IPOPT_LSRR
;
2870 return((unsigned long)-1);
2873 lsrp
++; /* skip over length, we'll fill it in later */
2879 sin_addr
.s_addr
= 0;
2884 else for (cp2
= cp
; c
= *cp2
; cp2
++) {
2889 } else if (c
== '@') {
2891 } else if (c
== ':') {
2900 if ((tmp
= inet_addr(cp
)) != -1) {
2901 sin_addr
.s_addr
= tmp
;
2902 } else if (host
= gethostbyname(cp
)) {
2904 memmove((caddr_t
)&sin_addr
,
2905 host
->h_addr_list
[0], host
->h_length
);
2907 memmove((caddr_t
)&sin_addr
, host
->h_addr
, host
->h_length
);
2913 memmove(lsrp
, (char *)&sin_addr
, 4);
2920 * Check to make sure there is space for next address
2922 if (lsrp
+ 4 > lsrep
)
2923 return((unsigned long)-1);
2926 if ((*(*cpp
+IPOPT_OLEN
) = lsrp
- *cpp
) <= 7) {
2929 return((unsigned long)-1);
2931 *lsrp
++ = IPOPT_NOP
; /* 32 bit word align it */
2932 *lenp
= lsrp
- *cpp
;
2934 ipopt
.io_len
= lsrp
- *cpp
;
2935 if (ipopt
.io_len
<= 5) { /* Is 3 better ? */
2938 return((unsigned long)-1);
2940 *lenp
= sizeof(ipopt
);
2941 *cpp
= (char *) &ipopt
;
2943 return(sin_addr
.s_addr
);