This is the complete diff from the internal linux netkit source repository from 0.06 (when I took over as upstream) to head (head is 0.18pre1 or shortly after it, circa 2002) (extracted with cvs diff -uwN) cvs diff: Diffing . Index: .cvsignore =================================================================== RCS file: .cvsignore diff -N .cvsignore --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ .cvsignore 17 Aug 1999 22:45:18 -0000 1.1 @@ -0,0 +1 @@ +telnet Index: Makefile =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/Makefile,v retrieving revision 1.4 retrieving revision 1.22 diff -w -u -r1.4 -r1.22 --- Makefile 16 Jul 1996 08:21:01 -0000 1.4 +++ Makefile 11 Aug 2002 23:22:32 -0000 1.22 @@ -3,24 +3,27 @@ include ../MCONFIG include ../MRULES -CFLAGS += '-DISSUE_FILE="/etc/issue.net"' -DAUTHENTICATE -I.. \ - -DTERMCAP -DUSE_TERMIO -DKLUDGELINEMODE -DDIAGNOSTICS -LDLIBS = -lbsd -ltermcap -ltelnet -L ../libtelnet +#CXXFLAGS:=$(patsubst -O2, -g, $(CXXFLAGS)) -OBJS = authenc.o commands.o main.o network.o ring.o sys_bsd.o telnet.o \ - terminal.o tn3270.o utilities.o +# -DAUTHENTICATE +CFLAGS += -DUSE_TERMIO -DKLUDGELINEMODE +LIBS += $(LIBTERMCAP) -# Warning. If you link it with ncurses instead of libtermcap it will crash. -# This will be fixed in a future release. +SRCS=carray.c commands.c main.c network.c ring.c sys_bsd.c telnet.c \ + terminal.c tn3270.c utilities.c genget.c environ.c netlink.c + +OBJS=$(patsubst %.c, %.o, $(SRCS)) telnet: $(OBJS) - $(CC) $(LDFLAGS) $^ $(LIBS) -L../libtelnet -ltelnet -ltermcap -o $@ + $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ -$(OBJS): defines.h externs.h fdset.h general.h proto.h ring.h types.h +include depend.mk +depend: + $(CC) $(CFLAGS) -MM $(SRCS) >depend.mk install: telnet - install -s telnet /usr/bin - install -m644 telnet.1 /usr/man/man1 + install -s -m$(BINMODE) telnet $(INSTALLROOT)$(BINDIR) + install -m$(MANMODE) telnet.1 $(INSTALLROOT)$(MANDIR)/man1 clean: rm -f *.o telnet Index: NetKit-B-0.06-telnet.patch =================================================================== RCS file: NetKit-B-0.06-telnet.patch diff -N NetKit-B-0.06-telnet.patch --- NetKit-B-0.06-telnet.patch 16 Jul 1996 05:17:22 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,27 +0,0 @@ -diff -ur NetKit-B-0.06.orig/telnet/defines.h NetKit-B-0.06/telnet/defines.h ---- NetKit-B-0.06.orig/telnet/defines.h Fri Dec 17 07:18:16 1993 -+++ NetKit-B-0.06/telnet/defines.h Mon Jun 5 15:34:51 1995 -@@ -34,6 +34,10 @@ - * $Id: NetKit-B-0.06-telnet.patch,v 1.1 1996/07/16 05:17:22 dholland Exp $ - */ - -+#define ENV_VAR NEW_ENV_VAR -+#define ENV_VALUE NEW_ENV_VALUE -+#define TELOPT_ENVIRON TELOPT_NEW_ENVIRON -+ - #define settimer(x) clocks.x = clocks.system++ - - #if !defined(TN3270) -diff -ur NetKit-B-0.06.orig/telnetd/defs.h NetKit-B-0.06/telnetd/defs.h ---- NetKit-B-0.06.orig/telnetd/defs.h Mon May 23 09:11:57 1994 -+++ NetKit-B-0.06/telnetd/defs.h Mon Jun 5 15:34:39 1995 -@@ -40,6 +40,9 @@ - #include - #include - -+#define ENV_VAR NEW_ENV_VAR -+#define ENV_VALUE NEW_ENV_VALUE -+#define TELOPT_ENVIRON TELOPT_NEW_ENVIRON - - #ifndef BSD - # define BSD 43 Index: README =================================================================== RCS file: README diff -N README --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ README 11 Aug 2002 22:56:08 -0000 1.4 @@ -0,0 +1,37 @@ +Telnet is back to compiling in C for this release (netkit 0.18). + +The attempt to clean up telnet failed utterly. While this code base +will still be maintained, features or major changes will not be +accepted. (Unless they're substantial cleanups... but don't waste your +time.) + +If you feel the urge to hack the telnet protocol, write a new +implementation. The world will thank you. + +------------------------------------------------------------ + +Telnet has been massively hacked up for this release. + +It presently requires a C++ compiler (gcc 2.7.2 or higher +recommended), but not libg++ or libstdc++. That is, unless you went to +special effort to not install the C++ compiler when you installed gcc, +you'll be fine. + +Large amounts of further hacking are expected. If you're interested in +working on it, please contact me, as diffs are likely to become +useless very quickly. + +Support for assorted old/broken systems has been dropped. Some such +support may be reinstated in the future once the code has been cleaned +up sufficiently. On the other hand, it may not. + +Known bugs/shortcomings at this point: + + - Under some circumstances it can theoretically encounter a + buffer overflow condition and drop data on the floor. If + anyone actually observes this ``in the wild'' I'd appreciate + knowing the circumstances. I'm also not convinced the old + behavior was any better. + - Various of the debug/trace modes don't work. This probably + doesn't matter to anyone not actually coding on it. + Index: TODO =================================================================== RCS file: TODO diff -N TODO --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TODO 11 Aug 2002 18:33:43 -0000 1.2 @@ -0,0 +1,21 @@ +This program should really be considered dead. If anyone is motivated +to care about it, time should be spent on a new implementation. + + +The old TODO list follows: + +------------------------------------------------------------ + +eliminate global variables + clean up command processing + fix "send" command + clean up option processing + +add empty encrypt hooks (layer over ring buffers) +flushout --> use nullsink + +fix ring buffer so it allocates more buf instead of overflowing + +put tracing back in + +authentication? Index: authenc.cc =================================================================== RCS file: authenc.cc diff -N authenc.cc --- authenc.cc 16 Jul 1996 07:57:25 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,116 +0,0 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * From: @(#)authenc.c 5.1 (Berkeley) 3/1/91 - */ -char au_rcsid[] = - "$Id: authenc.cc,v 1.2 1996/07/16 07:57:25 dholland Exp $"; - -#include -#if defined(ENCRYPT) || defined(AUTHENTICATE) -#include -#include -#include -#include - -#include "general.h" -#include "ring.h" -#include "externs.h" -#include "defines.h" -#include "types.h" -#include "proto.h" - - int -net_write(str, len) - unsigned char *str; - int len; -{ - if (NETROOM() > len) { - ring_supply_data(&netoring, str, len); - if (str[0] == IAC && str[1] == SE) - printsub('>', &str[2], len-2); - return(len); - } - return(0); -} - - void -net_encrypt() -{ -#if defined(ENCRYPT) - if (encrypt_output) - ring_encrypt(&netoring, encrypt_output); - else - ring_clearto(&netoring); -#endif -} - - int -telnet_spin() -{ - return(-1); -} - - char * -telnet_getenv(val) - char *val; -{ - return((char *)env_getvalue((unsigned char *)val)); -} - - char * -telnet_gets(prompt, result, length, echo) - char *prompt; - char *result; - int length; - int echo; -{ - extern char *getpass(); - extern int globalmode; - int om = globalmode; - char *res; - - TerminalNewMode(-1); - if (echo) { - printf("%s", prompt); - res = fgets(result, length, stdin); - } - else if ((res = getpass(prompt))!=NULL) { - strncpy(result, res, length); - res = result; - } - TerminalNewMode(om); - return(res); -} -#endif Index: carray.c =================================================================== RCS file: carray.c diff -N carray.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ carray.c 11 Aug 2002 23:01:05 -0000 1.1 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2000, 2001 + * The President and Fellows of Harvard College. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * C array of void pointers. See carray.h. + */ +#include +#include +#include +#include +#include "carray.h" + +struct array { + int num; + int max; + void **v; +}; + +struct array * +array_create(void) +{ + struct array *a = malloc(sizeof(struct array)); + if (a==NULL) { + return NULL; + } + a->v = NULL; + a->num = 0; + a->max = 0; + return a; +} + +int +array_getnum(struct array *a) +{ + return a->num; +} + +void * +array_getguy(struct array *a, int index) +{ + assert(a->num <= a->max); + assert(index >=0 && index < a->num); + return a->v[index]; +} + +int +array_preallocate(struct array *a, int nguys) +{ + void **newv; + int i; + int newmax = a->max; + + assert(a->num >=0 && a->num <= a->max); + + while (nguys > newmax) { + newmax = (newmax+1)*2; + } + newv = malloc(newmax * sizeof(void *)); + if (newv==NULL) { + return ENOMEM; + } + a->max = newmax; + for (i=0; inum; i++) newv[i] = a->v[i]; + if (a->v!=NULL) { + free(a->v); + } + a->v = newv; + return 0; +} + +int +array_setsize(struct array *a, int nguys) +{ + int result; + + assert(a->num >=0 && a->num <= a->max); + + if (nguys > a->max) { + result = array_preallocate(a, nguys); + if (result) { + return result; + } + } + else if (nguys==0 && a->max > 16) { + assert(a->v!=NULL); + free(a->v); + a->v = NULL; + a->max = 0; + } + a->num = nguys; + + return 0; +} + +void +array_setguy(struct array *a, int index, void *ptr) +{ + assert(a->num <= a->max); + assert(index >=0 && index < a->num); + a->v[index] = ptr; +} + +int +array_add(struct array *a, void *guy) +{ + int ix, result; + + ix = a->num; + + result = array_setsize(a, ix+1); + if (result) { + return result; + } + + a->v[ix] = guy; + + return 0; +} + +void +array_remove(struct array *a, int index) +{ + int nmove; + + assert(a->num <= a->max); + assert(index >=0 && index < a->num); + + nmove = a->num - (index + 1); + memmove(a->v+index, a->v+index+1, nmove*sizeof(void *)); + a->num--; +} + +void +array_destroy(struct array *a) +{ + if (a->v) free(a->v); + free(a); +} Index: carray.h =================================================================== RCS file: carray.h diff -N carray.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ carray.h 11 Aug 2002 23:01:05 -0000 1.1 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2000, 2001 + * The President and Fellows of Harvard College. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CARRAY_H +#define CARRAY_H + +/* + * Resizeable array of void pointers. + * + * Functions: + * array_create - allocate a new array object. Returns NULL if out + * of memory. + * array_preallocate - allocate enough space for at least NUM elements, + * without changing the visible size of the array. Can + * be used to prevent anticipated calls to setsize from + * failing. Returns an error code. + * array_getnum - return the size of the array. + * array_getguy - return the specified element from the array. + * array_setsize - alter the size of the array. If shrunk, excess + * elements are dropped. If expanded, the new elements + * are *not* initialized. Returns an error number on + * failure. + * array_setguy - set the specified element in the array to the passed + * pointer. The element must be within range. + * array_add - add one pointer to the end of the array, increasing + * the size. Returns an error number on failure. + * array_remove - remove one pointer from anywhere in the array. The + * portion of the array after the index is moved down, + * collapsing the resulting hole. + * array_destroy - dispose of an array. If not empty, the contents are + * lost. + */ + +struct array; /* Opaque. */ + +struct array *array_create(void); +int array_preallocate(struct array *, int nguys); +int array_getnum(struct array *); +void *array_getguy(struct array *, int index); +int array_setsize(struct array *, int nguys); +void array_setguy(struct array *, int index, void *ptr); +int array_add(struct array *, void *guy); +void array_remove(struct array *, int index); +void array_destroy(struct array *); + +#endif /* CARRAY_H */ Index: commands.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/commands.c,v retrieving revision 1.5 retrieving revision 1.43 diff -w -u -r1.5 -r1.43 --- commands.c 16 Jul 1996 09:23:59 -0000 1.5 +++ commands.c 11 Aug 2002 23:35:27 -0000 1.43 @@ -35,48 +35,51 @@ * From: @(#)commands.c 5.5 (Berkeley) 3/22/91 */ char cmd_rcsid[] = - "$Id: commands.c,v 1.5 1996/07/16 09:23:59 dholland Exp $"; + "$Id: commands.c,v 1.43 2002/08/11 23:35:27 dholland Exp $"; #include -#include -#if defined(unix) #include -#ifdef CRAY -#include -#endif #include -#else #include -#endif /* defined(unix) */ #include #include +#include /* Required for netinet/ip.h on BSD */ +#include + #ifdef CRAY #include #endif /* CRAY */ #include -#include +#include #include #include #include -#include +#include #include #include #include -#include #include #include -#include "general.h" - #include "ring.h" #include "externs.h" #include "defines.h" #include "types.h" - +#include "genget.h" +#include "environ.h" #include "proto.h" +#include "netlink.h" + +/* This ought to be declared by , but isn't */ +extern char *telopts[]; + +/* In Linux, this is an enum */ +#if defined(__linux__) || defined(IPPROTO_IP) +#define HAS_IPPROTO_IP +#endif #ifndef CRAY # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) @@ -84,43 +87,51 @@ # endif /* vax */ #endif /* CRAY */ +#define HELPINDENT ((int) sizeof ("connect")) #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 -#endif MAXHOSTNAMELEN +#endif -#if defined(IPPROTO_IP) && defined(IP_TOS) +#if defined(HAS_IPPROTO_IP) && defined(IP_TOS) int tos = -1; -#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ +#endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */ + +static unsigned long sourceroute(char *arg, char **cpp, int *lenp); + char *hostname; static char _hostname[MAXHOSTNAMELEN]; -extern char *getenv(); +//////////////////////////////////////////////////////////// +// +// New command table declarations 8/2002 +// -extern int isprefix(); -extern char **genget(); -extern int Ambiguous(); - -static call(); +typedef struct { + const char *name; /* command name */ + const char *help; /* help string (or NULL) */ + int (*handler)(int ac, const char **av); +} command_entry; typedef struct { - char *name; /* command name */ - char *help; /* help string (NULL for no help) */ - int (*handler)(); /* routine which executes command */ - int needconnect; /* Do we need to be connected to execute? */ -} Command; + const command_entry *entries; +} command_table; + +static int process_command(const command_table *tab, + int argc, const char **argv); + +// +//////////////////////////////////////////////////////////// static char line[256]; static char saveline[256]; static int margc; -static char *margv[20]; +static const char *margv[20]; - static void -makeargv() -{ +static void makeargv(void) { register char *cp, *cp2, c; - register char **argp = margv; + register const char **argp = margv; margc = 0; cp = line; @@ -173,9 +184,7 @@ * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). */ -static int -special(char *s) -{ +static int special(const char *s) { char c; char b; @@ -184,7 +193,8 @@ b = *++s; if (b == '?') { c = b | 0x40; /* DEL */ - } else { + } + else { c = b & 0x1f; } break; @@ -199,9 +209,7 @@ * Construct a control character sequence * for a special character. */ - static char * -control(c) - register cc_t c; +static const char *control(cc_t c) { static char buf[5]; /* @@ -244,26 +252,28 @@ */ struct sendlist { - char *name; /* How user refers to it (case independent) */ - char *help; /* Help information (0 ==> no help) */ + const char *name; /* How user refers to it (case independent) */ + const char *help; /* Help information (0 ==> no help) */ int needconnect; /* Need to be connected */ int narg; /* Number of arguments */ - int (*handler)(); /* Routine to perform (for special ops) */ + int (*handler)(const char *, const char *); + /* Routine to perform (for special ops) */ int nbyte; /* Number of bytes to send this command */ int what; /* Character to be sent (<0 ==> special) */ }; -static int send_esc(void); -static int send_help(void); -static int send_docmd(char *); -static int send_dontcmd(char *); -static int send_willcmd(char *); -static int send_wontcmd(char *); - -extern int send_do(int, int); -extern int send_dont(int, int); -extern int send_will(int, int); -extern int send_wont(int, int); +static int send_esc(const char *, const char *); +static int send_help(const char *, const char *); +static int send_docmd(const char *, const char *); +static int send_dontcmd(const char *, const char *); +static int send_willcmd(const char *, const char *); +static int send_wontcmd(const char *, const char *); + +static int dosynch1(const char *x, const char *y) { + (void)x; + (void)y; + return dosynch(); +} static struct sendlist Sendlist[] = { { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, @@ -283,7 +293,7 @@ { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, - { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, + { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch1, 2, 0 }, { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, { "?", "Display send options", 0, 0, send_help, 0, 0 }, { "help", 0, 0, 0, send_help, 0, 0 }, @@ -291,15 +301,13 @@ { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, { "will", 0, 0, 1, send_willcmd, 3, 0 }, { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, - { 0 } + { 0, 0, 0, 0, 0, 0, 0 } }; #define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ sizeof(struct sendlist))) -static int -sendcmd(int argc, char *argv[]) -{ +static int sendcmd(int argc, const char *argv[]) { int count; /* how many bytes we are going to need to send */ int i; /* int question = 0;*/ /* was at least one argument a question */ @@ -325,7 +333,8 @@ printf("Unknown send argument '%s'\n'send ?' for help.\n", argv[i]); return 0; - } else if (Ambiguous(s)) { + } + else if (s == AMBIGUOUS) { printf("Ambiguous send argument '%s'\n'send ?' for help.\n", argv[i]); return 0; @@ -338,7 +347,7 @@ } count += s->nbyte; if (s->handler == send_help) { - send_help(); + send_help(NULL, NULL); return 0; } @@ -351,7 +360,7 @@ return 0; } /* Now, do we have enough room? */ - if (NETROOM() < count) { + if (ringbuf_empty_count(netoring) < count) { printf("There is not enough room in the buffer TO the network\n"); printf("to process your request. Nothing will be done.\n"); printf("('send synch' will throw away most data in the network\n"); @@ -371,7 +380,8 @@ success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, (s->narg > 1) ? argv[i+2] : 0); i += s->narg; - } else { + } + else { NET2ADD(IAC, s->what); printoption("SENT", IAC, s->what); } @@ -379,34 +389,35 @@ return (count == success); } - static int -send_esc() -{ - NETADD(escape); +static int send_esc(const char *x, const char *y) { + (void)x; + (void)y; + NETADD(escapechar); return 1; } -static int send_docmd(char *name) { +static int send_docmd(const char *name, const char *crap) { + (void)crap; return send_tncmd(send_do, "do", name); } -static int send_dontcmd(char *name) { +static int send_dontcmd(const char *name, const char *crap) { + (void)crap; return(send_tncmd(send_dont, "dont", name)); } -static int send_willcmd(char *name) { +static int send_willcmd(const char *name, const char *crap) { + (void)crap; return(send_tncmd(send_will, "will", name)); } -static int send_wontcmd(char *name) { +static int send_wontcmd(const char *name, const char *crap) { + (void)crap; return(send_tncmd(send_wont, "wont", name)); } -int -send_tncmd(int (*func)(), char *cmd, char *name) -{ +int send_tncmd(void (*func)(int, int), const char *cmd, const char *name) { char **cpp; - extern char *telopts[]; if (isprefix(name, "help") || isprefix(name, "?")) { register int col, len; @@ -427,8 +438,8 @@ printf("\n"); return 0; } - cpp = (char **)genget(name, telopts, sizeof(char *)); - if (Ambiguous(cpp)) { + cpp = genget(name, telopts, sizeof(char *)); + if (cpp == AMBIGUOUS) { fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", name, cmd); return 0; @@ -446,10 +457,12 @@ return 1; } - static int -send_help() -{ +static int send_help(const char *x, const char *y) { struct sendlist *s; /* pointer to current command */ + + (void)x; + (void)y; + for (s = Sendlist; s->name; s++) { if (s->help) printf("%-15s %s\n", s->name, s->help); @@ -462,38 +475,24 @@ * to by the arguments to the "toggle" command. */ - static int -lclchars() -{ +static int lclchars(int junk) { + (void) junk; donelclchars = 1; return 1; } - static int -togdebug() -{ -#ifndef NOT43 - if (net > 0 && - (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { - perror("setsockopt (SO_DEBUG)"); - } -#else /* NOT43 */ - if (debug) { - if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) - perror("setsockopt (SO_DEBUG)"); - } else - printf("Cannot turn off socket debugging\n"); -#endif /* NOT43 */ - return 1; +static int togdebug(int junk) { + (void) junk; + return nlink_setdebug(debug); } - static int -togcrlf() -{ +static int togcrlf(int junk) { + (void)junk; if (crlf) { printf("Will send carriage returns as telnet .\n"); - } else { + } + else { printf("Will send carriage returns as telnet .\n"); } return 1; @@ -501,10 +500,7 @@ int binmode; - static int -togbinary(val) - int val; -{ +static int togbinary(int val) { donebinarytoggle = 1; if (val >= 0) { @@ -540,10 +536,7 @@ return 1; } - static int -togrbinary(val) - int val; -{ +static int togrbinary(int val) { donebinarytoggle = 1; if (val == -1) @@ -552,11 +545,13 @@ if (val == 1) { if (my_want_state_is_do(TELOPT_BINARY)) { printf("Already receiving in binary mode.\n"); - } else { + } + else { printf("Negotiating binary mode on input.\n"); tel_enter_binary(1); } - } else { + } + else { if (my_want_state_is_dont(TELOPT_BINARY)) { printf("Already receiving in network ascii mode.\n"); } else { @@ -567,10 +562,7 @@ return 1; } - static int -togxbinary(val) - int val; -{ +static int togxbinary(int val) { donebinarytoggle = 1; if (val == -1) @@ -579,14 +571,17 @@ if (val == 1) { if (my_want_state_is_will(TELOPT_BINARY)) { printf("Already transmitting in binary mode.\n"); - } else { + } + else { printf("Negotiating binary mode on output.\n"); tel_enter_binary(2); } - } else { + } + else { if (my_want_state_is_wont(TELOPT_BINARY)) { printf("Already transmitting in network ascii mode.\n"); - } else { + } + else { printf("Negotiating network ascii mode on output.\n"); tel_leave_binary(2); } @@ -595,159 +590,111 @@ } -static int togglehelp P((void)); -#if defined(AUTHENTICATE) -extern int auth_togdebug P((int)); -#endif -#if defined(ENCRYPT) -extern int EncryptAutoEnc P((int)); -extern int EncryptAutoDec P((int)); -extern int EncryptDebug P((int)); -extern int EncryptVerbose P((int)); -#endif +static int netdata; /* Print out network data flow */ +static int prettydump; /* Print "netdata" output in user readable format */ +static int termdata; /* Print out terminal data flow */ + +static int togglehelp(int); struct togglelist { - char *name; /* name of toggle */ - char *help; /* help message */ - int (*handler)(); /* routine to do actual setting */ + const char *name; /* name of toggle */ + const char *help; /* help message */ + int (*handler)(int); /* routine to do actual setting */ int *variable; - char *actionexplanation; + const char *actionexplanation; }; static struct togglelist Togglelist[] = { - { "autoflush", - "flushing of output when sending interrupt characters", - 0, - &autoflush, + { "autoflush", "flushing of output when sending interrupt characters", + NULL, &autoflush, "flush output when sending interrupt characters" }, - { "autosynch", - "automatic sending of interrupt characters in urgent mode", - 0, - &autosynch, + + { "autosynch", "automatic sending of interrupt characters in urgent mode", + NULL, &autosynch, "send interrupt characters in urgent mode" }, -#if defined(AUTHENTICATE) - { "autologin", - "automatic sending of login and/or authentication info", - 0, - &autologin, + +#if 0 + { "autologin", "automatic sending of login and/or authentication info", + NULL, &autologin, "send login name and/or authentication information" }, - { "authdebug", - "Toggle authentication debugging", - auth_togdebug, - 0, + { "authdebug", "Toggle authentication debugging", + auth_togdebug, NULL, "print authentication debugging information" }, -#endif -#if defined(ENCRYPT) - { "autoencrypt", - "automatic encryption of data stream", - EncryptAutoEnc, - 0, + { "autoencrypt", "automatic encryption of data stream", + EncryptAutoEnc, NULL, "automatically encrypt output" }, - { "autodecrypt", - "automatic decryption of data stream", - EncryptAutoDec, - 0, + { "autodecrypt", "automatic decryption of data stream", + EncryptAutoDec, NULL, "automatically decrypt input" }, - { "verbose_encrypt", - "Toggle verbose encryption output", - EncryptVerbose, - 0, + { "verbose_encrypt", "Toggle verbose encryption output", + EncryptVerbose, NULL, "print verbose encryption output" }, - { "encdebug", - "Toggle encryption debugging", - EncryptDebug, - 0, + { "encdebug", "Toggle encryption debugging", + EncryptDebug, NULL, "print encryption debugging information" }, #endif - { "skiprc", - "don't read ~/.telnetrc file", - 0, - &skiprc, + + { "skiprc", "don't read ~/.telnetrc file", + NULL, &skiprc, "read ~/.telnetrc file" }, { "binary", "sending and receiving of binary data", - togbinary, - 0, - 0 }, - { "inbinary", - "receiving of binary data", - togrbinary, - 0, - 0 }, - { "outbinary", - "sending of binary data", - togxbinary, - 0, - 0 }, - { "crlf", - "sending carriage returns as telnet ", - togcrlf, - &crlf, - 0 }, - { "crmod", - "mapping of received carriage returns", - 0, - &crmod, + togbinary, NULL, + NULL }, + { "inbinary", "receiving of binary data", + togrbinary, NULL, + NULL }, + { "outbinary", "sending of binary data", + togxbinary, 0, + NULL }, + { "crlf", "sending carriage returns as telnet ", + togcrlf, &crlf, + NULL }, + { "crmod", "mapping of received carriage returns", + NULL, &crmod, "map carriage return on output" }, - { "localchars", - "local recognition of certain control characters", - lclchars, - &localchars, + { "localchars", "local recognition of certain control characters", + lclchars, &localchars, "recognize certain control characters" }, - { " ", "", 0 }, /* empty line */ -#if defined(unix) && defined(TN3270) && !defined(__linux__) - { "apitrace", - "(debugging) toggle tracing of API transactions", - 0, - &apitrace, + + { " ", "", 0, 0, 0 }, /* empty line */ + +#if defined(TN3270) && !defined(__linux__) + { "apitrace", "(debugging) toggle tracing of API transactions", + NULL, &apitrace, "trace API transactions" }, - { "cursesdata", - "(debugging) toggle printing of hexadecimal curses data", - 0, - &cursesdata, + { "cursesdata", "(debugging) toggle printing of hexadecimal curses data", + NULL, &cursesdata, "print hexadecimal representation of curses data" }, -#endif /* defined(unix) && defined(TN3270) */ - { "debug", - "debugging", - togdebug, - &debug, +#endif /* TN3270 and not linux */ + + { "debug", "debugging", + togdebug, &debug, "turn on socket level debugging" }, - { "netdata", - "printing of hexadecimal network data (debugging)", - 0, - &netdata, + { "netdata", "printing of hexadecimal network data (debugging)", + NULL, &netdata, "print hexadecimal representation of network traffic" }, - { "prettydump", - "output of \"netdata\" to user readable format (debugging)", - 0, - &prettydump, + { "prettydump","output of \"netdata\" to user readable format (debugging)", + NULL, &prettydump, "print user readable output for \"netdata\"" }, - { "options", - "viewing of options processing (debugging)", - 0, - &showoptions, + { "options", "viewing of options processing (debugging)", + NULL, &showoptions, "show option processing" }, -#if defined(unix) - { "termdata", - "(debugging) toggle printing of hexadecimal terminal data", - 0, - &termdata, + + { "termdata", "(debugging) toggle printing of hexadecimal terminal data", + NULL, &termdata, "print hexadecimal representation of terminal traffic" }, -#endif /* defined(unix) */ - { "?", - 0, - togglehelp }, - { "help", - 0, - togglehelp }, - { 0 } + + { "?", NULL, togglehelp, 0, 0 }, + { "help", NULL, togglehelp, 0, 0 }, + { 0, 0, 0, 0, 0 } }; - static int -togglehelp() -{ +static int togglehelp(int junk) { struct togglelist *c; + (void)junk; + for (c = Togglelist; c->name; c++) { if (c->help) { if (*c->help) @@ -761,10 +708,7 @@ return 0; } - static void -settogglehelp(set) - int set; -{ +static void settogglehelp(int set) { struct togglelist *c; for (c = Togglelist; c->name; c++) { @@ -781,13 +725,9 @@ #define GETTOGGLE(name) (struct togglelist *) \ genget(name, (char **) Togglelist, sizeof(struct togglelist)) - static int -toggle(argc, argv) - int argc; - char *argv[]; -{ +static int toggle(int argc, const char *argv[]) { int retval = 1; - char *name; + const char *name; struct togglelist *c; if (argc < 2) { @@ -800,15 +740,17 @@ while (argc--) { name = *argv++; c = GETTOGGLE(name); - if (Ambiguous(c)) { + if (c == AMBIGUOUS) { fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", name); return 0; - } else if (c == 0) { + } + else if (c == 0) { fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", name); return 0; - } else { + } + else { if (c->variable) { *c->variable = !*c->variable; /* invert it */ if (c->actionexplanation) { @@ -828,14 +770,10 @@ * The following perform the "set" command. */ -#ifdef USE_TERMIO -struct termios new_tc = { 0 }; -#endif - struct setlist { - char *name; /* name */ - char *help; /* help information */ - void (*handler)(); + const char *name; /* name */ + const char *help; /* help information */ + void (*handler)(const char *); cc_t *charp; /* where it is located at */ }; @@ -843,16 +781,16 @@ #ifdef KLUDGELINEMODE { "echo", "character to toggle local echoing on/off", 0, &echoc }, #endif - { "escape", "character to escape back to telnet command mode", 0, &escape }, + { "escape", "character to escape back to telnet command mode", 0, &escapechar }, { "rlogin", "rlogin escape character", 0, &rlogin }, { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, - { " ", "" }, + { " ", "", 0, 0 }, { " ", "The following need 'localchars' to be toggled true", 0, 0 }, { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp }, { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, { "quit", "character to cause an Abort process", 0, termQuitCharp }, { "eof", "character to cause an EOF ", 0, termEofCharp }, - { " ", "" }, + { " ", "", 0, 0 }, { " ", "The following are for local editing in linemode", 0, 0 }, { "erase", "character to use to erase a character", 0, termEraseCharp }, { "kill", "character to use to erase a line", 0, termKillCharp }, @@ -865,7 +803,7 @@ { "forw1", "alternate end of line character", 0, termForw1Charp }, { "forw2", "alternate end of line character", 0, termForw2Charp }, { "ayt", "alternate AYT character", 0, termAytCharp }, - { 0 } + { 0, 0, 0, 0 } }; #if defined(CRAY) && !defined(__STDC__) @@ -898,30 +836,25 @@ #endif /* defined(CRAY) && !defined(__STDC__) */ static struct setlist * -getset(char *name) +getset(const char *name) { return (struct setlist *) genget(name, (char **) Setlist, sizeof(struct setlist)); } -void -set_escape_char(char *s) -{ +void set_escape_char(char *s) { if (rlogin != _POSIX_VDISABLE) { rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; printf("Telnet rlogin escape character is '%s'.\n", control(rlogin)); - } else { - escape = (s && *s) ? special(s) : _POSIX_VDISABLE; - printf("Telnet escape character is '%s'.\n", control(escape)); + } + else { + escapechar = (s && *s) ? special(s) : _POSIX_VDISABLE; + printf("Telnet escape character is '%s'.\n", control(escapechar)); } } - static int -setcmd(argc, argv) - int argc; - char *argv[]; -{ +static int setcmd(int argc, const char *argv[]) { int value; struct setlist *ct; struct togglelist *c; @@ -946,7 +879,8 @@ fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", argv[1]); return 0; - } else if (Ambiguous(c)) { + } + else if (c == AMBIGUOUS) { fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); return 0; @@ -967,17 +901,21 @@ } if (c->handler) (*c->handler)(1); - } else if (argc != 3) { + } + else if (argc != 3) { printf("Format is 'set Name Value'\n'set ?' for help.\n"); return 0; - } else if (Ambiguous(ct)) { + } + else if (ct == AMBIGUOUS) { fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); return 0; - } else if (ct->handler) { + } + else if (ct->handler) { (*ct->handler)(argv[2]); printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); - } else { + } + else { if (strcmp("off", argv[2])) { value = special(argv[2]); } else { @@ -990,14 +928,10 @@ return 1; } - static int -unsetcmd(argc, argv) - int argc; - char *argv[]; -{ +static int unsetcmd(int argc, const char *argv[]) { struct setlist *ct; struct togglelist *c; - register char *name; + const char *name; if (argc < 2) { fprintf(stderr, @@ -1024,7 +958,8 @@ fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", name); return 0; - } else if (Ambiguous(c)) { + } + else if (c == AMBIGUOUS) { fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", name); return 0; @@ -1038,14 +973,17 @@ } if (c->handler) (*c->handler)(0); - } else if (Ambiguous(ct)) { + } + else if (ct == AMBIGUOUS) { fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", name); return 0; - } else if (ct->handler) { + } + else if (ct->handler) { (*ct->handler)(0); printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); - } else { + } + else { *(ct->charp) = _POSIX_VDISABLE; printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); } @@ -1060,9 +998,8 @@ #ifdef KLUDGELINEMODE extern int kludgelinemode; -static int -dokludgemode(void) -{ +static int dokludgemode(int junk) { + (void) junk; kludgelinemode = 1; send_wont(TELOPT_LINEMODE, 1); send_dont(TELOPT_SGA, 1); @@ -1071,9 +1008,8 @@ } #endif - static int -dolinemode() -{ +static int dolinemode(int junk) { + (void)junk; #ifdef KLUDGELINEMODE if (kludgelinemode) send_dont(TELOPT_SGA, 1); @@ -1083,9 +1019,8 @@ return 1; } - static int -docharmode() -{ +static int docharmode(int junk) { + (void)junk; #ifdef KLUDGELINEMODE if (kludgelinemode) send_do(TELOPT_SGA, 1); @@ -1096,12 +1031,8 @@ return 1; } - static int -dolmmode(bit, on) - int bit, on; -{ +static int dolmmode(int bit, int on) { unsigned char c; - extern int linemode; if (my_want_state_is_wont(TELOPT_LINEMODE)) { printf("?Need to have LINEMODE option enabled first.\n"); @@ -1117,66 +1048,62 @@ return 1; } - int -setmode(bit) -{ +static int mysetmode(int bit) { return dolmmode(bit, 1); } - int -clearmode(bit) -{ +static int myclearmode(int bit) { return dolmmode(bit, 0); } struct modelist { - char *name; /* command name */ - char *help; /* help string */ - int (*handler)(); /* routine which executes command */ + const char *name; /* command name */ + const char *help; /* help string */ + int (*handler)(int); /* routine which executes command */ int needconnect; /* Do we need to be connected to execute? */ int arg1; }; -extern int modehelp(); +extern int modehelp(int); static struct modelist ModeList[] = { - { "character", "Disable LINEMODE option", docharmode, 1 }, + { "character", "Disable LINEMODE option", docharmode, 1,0}, #ifdef KLUDGELINEMODE - { "", "(or disable obsolete line-by-line mode)", 0 }, + { "", "(or disable obsolete line-by-line mode)", NULL, 0,0 }, #endif - { "line", "Enable LINEMODE option", dolinemode, 1 }, + { "line", "Enable LINEMODE option", dolinemode, 1,0}, #ifdef KLUDGELINEMODE - { "", "(or enable obsolete line-by-line mode)", 0 }, + { "", "(or enable obsolete line-by-line mode)", NULL, 0,0 }, #endif - { "", "", 0 }, - { "", "These require the LINEMODE option to be enabled", 0 }, - { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, - { "+isig", 0, setmode, 1, MODE_TRAPSIG }, - { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, - { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, - { "+edit", 0, setmode, 1, MODE_EDIT }, - { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, - { "softtabs", "Enable tab expansion", setmode, 1, MODE_SOFT_TAB }, - { "+softtabs", 0, setmode, 1, MODE_SOFT_TAB }, - { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, - { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO }, - { "+litecho", 0, setmode, 1, MODE_LIT_ECHO }, - { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, - { "help", 0, modehelp, 0 }, + { "", "", NULL, 0, 0 }, + { "", "These require the LINEMODE option to be enabled", NULL, 0, 0}, + { "isig", "Enable signal trapping", mysetmode, 1, MODE_TRAPSIG }, + { "+isig", 0, mysetmode, 1, MODE_TRAPSIG }, + { "-isig", "Disable signal trapping", myclearmode, 1, MODE_TRAPSIG }, + { "edit", "Enable character editing", mysetmode, 1, MODE_EDIT }, + { "+edit", 0, mysetmode, 1, MODE_EDIT }, + { "-edit", "Disable character editing", myclearmode, 1, MODE_EDIT }, + { "softtabs", "Enable tab expansion", mysetmode, 1, MODE_SOFT_TAB }, + { "+softtabs", 0, mysetmode, 1, MODE_SOFT_TAB }, + { "-softtabs", "Disable character editing", myclearmode,1, MODE_SOFT_TAB }, + { "litecho", "Enable literal character echo", mysetmode,1, MODE_LIT_ECHO }, + { "+litecho", 0, mysetmode, 1, MODE_LIT_ECHO }, + { "-litecho","Disable literal character echo",myclearmode,1,MODE_LIT_ECHO}, + { "help", 0, modehelp, 0, 0 }, #ifdef KLUDGELINEMODE - { "kludgeline", 0, dokludgemode, 1 }, + { "kludgeline", 0, dokludgemode, 1, 0 }, #endif - { "", "", 0 }, - { "?", "Print help information", modehelp, 0 }, - { 0 }, + { "", "", 0, 0, 0 }, + { "?", "Print help information", modehelp, 0, 0 }, + { 0, 0, 0, 0, 0 }, }; - int -modehelp() -{ +int modehelp(int junk) { struct modelist *mt; + (void)junk; + printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); for (mt = ModeList; mt->name; mt++) { if (mt->help) { @@ -1192,24 +1119,21 @@ #define GETMODECMD(name) (struct modelist *) \ genget(name, (char **) ModeList, sizeof(struct modelist)) - static int -modecmd(argc, argv) - int argc; - char *argv[]; -{ +static int modecmd(const char *arg) { struct modelist *mt; - if (argc != 2) { - printf("'mode' command requires an argument\n"); - printf("'mode ?' for help.\n"); - } else if ((mt = GETMODECMD(argv[1])) == 0) { - fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); - } else if (Ambiguous(mt)) { - fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); - } else if (mt->needconnect && !connected) { + mt = GETMODECMD(arg); + if (mt == 0) { + fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", arg); + } + else if (mt == AMBIGUOUS) { + fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", arg); + } + else if (mt->needconnect && !connected) { printf("?Need to be connected first.\n"); printf("'mode ?' for help.\n"); - } else if (mt->handler) { + } + else if (mt->handler) { return (*mt->handler)(mt->arg1); } return 0; @@ -1220,29 +1144,32 @@ * "display" command. */ - static int -display(argc, argv) - int argc; - char *argv[]; -{ - struct togglelist *tl; - struct setlist *sl; - -#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ - if (*tl->variable) { \ - printf("will"); \ - } else { \ - printf("won't"); \ - } \ - printf(" %s.\n", tl->actionexplanation); \ +static void dotog(struct togglelist *tl) { + if (tl->variable && tl->actionexplanation) { + if (*tl->variable) { + printf("will"); + } + else { + printf("won't"); + } + printf(" %s.\n", tl->actionexplanation); + } } -#define doset(sl) if (sl->name && *sl->name != ' ') { \ - if (sl->handler == 0) \ - printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ - else \ - printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ +static void doset(struct setlist *sl) { + if (sl->name && *sl->name != ' ') { + if (sl->handler == 0) { + printf("%-15s [%s]\n", sl->name, control(*sl->charp)); + } + else { + printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); + } } +} + +static int display(int argc, const char *argv[]) { + struct togglelist *tl; + struct setlist *sl; if (argc == 1) { for (tl = Togglelist; tl->name; tl++) { @@ -1252,19 +1179,22 @@ for (sl = Setlist; sl->name; sl++) { doset(sl); } - } else { + } + else { int i; for (i = 1; i < argc; i++) { sl = getset(argv[i]); tl = GETTOGGLE(argv[i]); - if (Ambiguous(sl) || Ambiguous(tl)) { + if (sl == AMBIGUOUS || tl == AMBIGUOUS) { printf("?Ambiguous argument '%s'.\n", argv[i]); return 0; - } else if (!sl && !tl) { + } + else if (!sl && !tl) { printf("?Unknown argument '%s'.\n", argv[i]); return 0; - } else { + } + else { if (tl) { dotog(tl); } @@ -1274,13 +1204,8 @@ } } } -/*@*/optionstatus(); -#if defined(ENCRYPT) - EncryptStatus(); -#endif + optionstatus(); return 1; -#undef doset -#undef dotog } /* @@ -1291,48 +1216,39 @@ /* * Set the escape character. */ - static int -setescape(argc, argv) - int argc; - char *argv[]; -{ - register char *arg; +static int setescape(int argc, const char *argv[]) { + const char *arg; char buf[50]; printf( "Deprecated usage - please use 'set escape%s%s' in the future.\n", (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); - if (argc > 2) + if (argc > 2) { arg = argv[1]; + } else { printf("new escape character: "); (void) fgets(buf, sizeof(buf), stdin); arg = buf; } if (arg[0] != '\0') - escape = arg[0]; + escapechar = arg[0]; if (!In3270) { - printf("Escape character is '%s'.\n", control(escape)); + printf("Escape character is '%s'.\n", control(escapechar)); } (void) fflush(stdout); return 1; } - /*VARARGS*/ - static int -togcrmod() -{ +static int togcrmod(void) { crmod = !crmod; printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); - (void) fflush(stdout); + fflush(stdout); return 1; } - /*VARARGS*/ - int -suspend() -{ +static int suspend(void) { #ifdef SIGTSTP setcommandmode(); { @@ -1356,12 +1272,9 @@ } #if !defined(TN3270) - /*ARGSUSED*/ - int -shell(argc, argv) - int argc; - char *argv[]; -{ +static int shell(int argc, const char **argv) { + (void)argv; + setcommandmode(); switch(vfork()) { case -1: @@ -1373,8 +1286,7 @@ /* * Fire up the shell in the child. */ - register char *shellp, *shellname; - extern char *rindex(); + const char *shellp, *shellname; shellp = getenv("SHELL"); if (shellp == NULL) @@ -1391,125 +1303,52 @@ _exit(1); } default: - (void)wait((int *)0); /* Wait for the shell to complete */ + wait(NULL); /* Wait for the shell to complete */ } return 1; } #endif /* !defined(TN3270) */ -static int -bye(int argc, char *argv[]) -{ - extern int resettermname; - +static int dobye(int isfromquit) { if (connected) { - (void) shutdown(net, 2); + nlink_close(1); printf("Connection closed.\n"); - (void) NetClose(net); connected = 0; resettermname = 1; -#if defined(AUTHENTICATE) || defined(ENCRYPT) - auth_encrypt_connect(connected); -#endif + /* reset options */ tninit(); #if defined(TN3270) SetIn3270(); /* Get out of 3270 mode */ #endif /* defined(TN3270) */ } - if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { - longjmp(toplevel, 1); + if (!isfromquit) { + siglongjmp(toplevel, 1); /* NOTREACHED */ } return 1; /* Keep lint, etc., happy */ } -void quit(void) -{ - call(bye, "bye", "fromquit", 0); - Exit(0); -} - -int -logout(void) -{ - send_do(TELOPT_LOGOUT, 1); - netflush(); - return 1; -} - - -/* - * The SLC command. - */ - -struct slclist { - char *name; - char *help; - void (*handler)(); - int arg; -}; - -static void slc_help(); - -struct slclist SlcList[] = { - { "export", "Use local special character definitions", - slc_mode_export, 0 }, - { "import", "Use remote special character definitions", - slc_mode_import, 1 }, - { "check", "Verify remote special character definitions", - slc_mode_import, 0 }, - { "help", 0, slc_help, 0 }, - { "?", "Print help information", slc_help, 0 }, - { 0 }, -}; - - static void -slc_help() -{ - struct slclist *c; - - for (c = SlcList; c->name; c++) { - if (c->help) { - if (*c->help) - printf("%-15s %s\n", c->name, c->help); - else - printf("\n"); - } +static int bye(void) { + if (!connected) { + printf("Need to be connected first for `bye'.\n"); + return 0; } + return dobye(0); } - static struct slclist * -getslc(name) - char *name; -{ - return (struct slclist *) - genget(name, (char **) SlcList, sizeof(struct slclist)); +void quit(void) { + dobye(1); + Exit(0); } -static int -slccmd(int argc, char *argv[]) -{ - struct slclist *c; - - if (argc != 2) { - fprintf(stderr, - "Need an argument to 'slc' command. 'slc ?' for help.\n"); - return 0; - } - c = getslc(argv[1]); - if (c == 0) { - fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", - argv[1]); - return 0; - } - if (Ambiguous(c)) { - fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", - argv[1]); +static int logout(void) { + if (!connected) { + printf("Need to be connected first for `logout'.\n"); return 0; } - (*c->handler)(c->arg); - slcstate(); + send_do(TELOPT_LOGOUT, 1); + netflush(); return 1; } @@ -1517,45 +1356,39 @@ * The ENVIRON command. */ -struct envlist { - char *name; - char *help; - void (*handler)(); +struct envcmd { + const char *name; + const char *help; + void (*handler)(const char *, const char *); int narg; }; -extern struct env_lst * - env_define P((unsigned char *, unsigned char *)); -extern void - env_undefine P((unsigned char *)), - env_export P((unsigned char *)), - env_unexport P((unsigned char *)), - env_send P((unsigned char *)), - env_list P((void)); -static void - env_help P((void)); +static void env_help(const char *, const char *); + +typedef void (*envfunc)(const char *, const char *); -struct envlist EnvList[] = { +struct envcmd EnvList[] = { { "define", "Define an environment variable", - (void (*)())env_define, 2 }, + env_define, 2 }, { "undefine", "Undefine an environment variable", - env_undefine, 1 }, + (envfunc) env_undefine, 1 }, { "export", "Mark an environment variable for automatic export", - env_export, 1 }, + (envfunc) env_export, 1 }, { "unexport", "Don't mark an environment variable for automatic export", - env_unexport, 1 }, - { "send", "Send an environment variable", env_send, 1 }, + (envfunc) env_unexport, 1 }, + { "send", "Send an environment variable", (envfunc) env_send, 1 }, { "list", "List the current environment variables", - env_list, 0 }, + (envfunc) env_list, 0 }, { "help", 0, env_help, 0 }, { "?", "Print help information", env_help, 0 }, - { 0 }, + { 0, 0, 0, 0 }, }; - static void -env_help() -{ - struct envlist *c; +static void env_help(const char *junk1, const char *junk2) { + struct envcmd *c; + + (void)junk1; + (void)junk2; for (c = EnvList; c->name; c++) { if (c->help) { @@ -1567,18 +1400,13 @@ } } - static struct envlist * -getenvcmd(name) - char *name; -{ - return (struct envlist *) - genget(name, (char **) EnvList, sizeof(struct envlist)); +static struct envcmd *getenvcmd(const char *name) { + return (struct envcmd *) + genget(name, (char **) EnvList, sizeof(struct envcmd)); } -int -env_cmd(int argc, char *argv[]) -{ - struct envlist *c; +static int env_cmd(int argc, const char *argv[]) { + struct envcmd *c; if (argc < 2) { fprintf(stderr, @@ -1591,7 +1419,7 @@ argv[1]); return 0; } - if (Ambiguous(c)) { + if (c == AMBIGUOUS) { fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", argv[1]); return 0; @@ -1607,434 +1435,66 @@ return 1; } -struct env_lst { - struct env_lst *next; /* pointer to next structure */ - struct env_lst *prev; /* pointer to next structure */ - unsigned char *var; /* pointer to variable name */ - unsigned char *value; /* pointer to varialbe value */ - int export; /* 1 -> export with default list of variables */ -}; - -struct env_lst envlisthead; - - struct env_lst * -env_find(var) - unsigned char *var; -{ - register struct env_lst *ep; - - for (ep = envlisthead.next; ep; ep = ep->next) { - if (strcmp((char *)ep->var, (char *)var) == 0) - return(ep); - } - return(NULL); -} - - void -env_init() -{ - extern char **environ; - register char **epp, *cp; - register struct env_lst *ep; - extern char *index(); - for (epp = environ; *epp; epp++) { - if ((cp = strchr(*epp, '='))!=NULL) { - *cp = '\0'; - ep = env_define((unsigned char *)*epp, - (unsigned char *)cp+1); - ep->export = 0; - *cp = '='; - } - } /* - * Special case for DISPLAY variable. If it is ":0.0" or - * "unix:0.0", we have to get rid of "unix" and insert our - * hostname. + * The AUTHENTICATE command. + * + * auth status Display status + * auth disable Disable an authentication type + * auth enable Enable an authentication type + * + * The ENCRYPT command. + * + * encrypt enable Enable encryption + * encrypt disable Disable encryption + * encrypt type foo Set encryption type + * encrypt start Start encryption + * encrypt stop Stop encryption + * encrypt input Start encrypting input stream + * encrypt -input Stop encrypting input stream + * encrypt output Start encrypting output stream + * encrypt -output Stop encrypting output stream + * encrypt status Print status */ - if ((ep = env_find("DISPLAY")) - && ((*ep->value == ':') - || (strncmp((char *)ep->value, "unix:", 5) == 0))) { - char hbuf[256+1]; - char *cp2 = index((char *)ep->value, ':'); - - gethostname(hbuf, 256); - hbuf[256] = '\0'; - cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); - sprintf((char *)cp, "%s%s", hbuf, cp2); - free(ep->value); - ep->value = (unsigned char *)cp; - } - /* - * If USER is not defined, but LOGNAME is, then add - * USER with the value from LOGNAME. By default, we - * don't export the USER variable. - */ - if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { - env_define((unsigned char *)"USER", ep->value); - env_unexport((unsigned char *)"USER"); - } - env_export((unsigned char *)"DISPLAY"); - env_export((unsigned char *)"PRINTER"); -} - - struct env_lst * -env_define(var, value) - unsigned char *var, *value; -{ - register struct env_lst *ep; - - if ((ep = env_find(var))!=NULL) { - if (ep->var) - free(ep->var); - if (ep->value) - free(ep->value); - } else { - ep = (struct env_lst *)malloc(sizeof(struct env_lst)); - ep->next = envlisthead.next; - envlisthead.next = ep; - ep->prev = &envlisthead; - if (ep->next) - ep->next->prev = ep; - } - ep->export = 1; - ep->var = (unsigned char *)strdup((char *)var); - ep->value = (unsigned char *)strdup((char *)value); - return(ep); -} - - void -env_undefine(var) - unsigned char *var; -{ - register struct env_lst *ep; - if ((ep = env_find(var))!=NULL) { - ep->prev->next = ep->next; - if (ep->next) - ep->next->prev = ep->prev; - if (ep->var) - free(ep->var); - if (ep->value) - free(ep->value); - free(ep); - } -} - void -env_export(var) - unsigned char *var; -{ - register struct env_lst *ep; +#ifdef TN3270 +char *oflgs[] = { "read-only", "write-only", "read-write" }; - if ((ep = env_find(var))!=NULL) - ep->export = 1; -} +static void filestuff(int fd) { + int res; - void -env_unexport(var) - unsigned char *var; -{ - register struct env_lst *ep; +#ifdef F_GETOWN + setconnmode(0); + res = fcntl(fd, F_GETOWN, 0); + setcommandmode(); - if ((ep = env_find(var))!=NULL) - ep->export = 0; + if (res == -1) { + perror("fcntl"); + return; } + printf("\tOwner is %d.\n", res); +#endif - void -env_send(var) - unsigned char *var; -{ - register struct env_lst *ep; + setconnmode(0); + res = fcntl(fd, F_GETFL, 0); + setcommandmode(); - if (my_state_is_wont(TELOPT_ENVIRON)) { - fprintf(stderr, - "Cannot send '%s': Telnet ENVIRON option not enabled\n", - var); + if (res == -1) { + perror("fcntl"); return; } - ep = env_find(var); - if (ep == 0) { - fprintf(stderr, "Cannot send '%s': variable not defined\n", - var); - return; + printf("\tFlags are 0x%x: %s\n", res, oflgs[res]); } - env_opt_start_info(); - env_opt_add(ep->var); - env_opt_end(0); -} - - void -env_list() -{ - register struct env_lst *ep; - - for (ep = envlisthead.next; ep; ep = ep->next) { - printf("%c %-20s %s\n", ep->export ? '*' : ' ', - ep->var, ep->value); - } -} - - unsigned char * -env_default(init) - int init; -{ - static struct env_lst *nep = NULL; - - if (init) { - nep = &envlisthead; - return NULL; /* was just return... (?) */ - } - if (nep) { - while ((nep = nep->next)!=NULL) { - if (nep->export) - return(nep->var); - } - } - return(NULL); -} - - unsigned char * -env_getvalue(var) - unsigned char *var; -{ - register struct env_lst *ep; - - if ((ep = env_find(var))!=NULL) - return(ep->value); - return(NULL); -} - -#if defined(AUTHENTICATE) -/* - * The AUTHENTICATE command. - */ - -struct authlist { - char *name; - char *help; - int (*handler)(); - int narg; -}; - -extern int - auth_enable(char *), - auth_disable(char *), - auth_status P((void)); -static int - auth_help P((void)); - -struct authlist AuthList[] = { - { "status", "Display current status of authentication information", - auth_status, 0 }, - { "disable", "Disable an authentication type ('auth disable ?' for more)", - auth_disable, 1 }, - { "enable", "Enable an authentication type ('auth enable ?' for more)", - auth_enable, 1 }, - { "help", 0, auth_help, 0 }, - { "?", "Print help information", auth_help, 0 }, - { 0 }, -}; - - static int -auth_help() -{ - struct authlist *c; - - for (c = AuthList; c->name; c++) { - if (c->help) { - if (*c->help) - printf("%-15s %s\n", c->name, c->help); - else - printf("\n"); - } - } - return 0; -} - -int -auth_cmd(int argc, char *argv[]) -{ - struct authlist *c; - - c = (struct authlist *) - genget(argv[1], (char **) AuthList, sizeof(struct authlist)); - if (c == 0) { - fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", - argv[1]); - return 0; - } - if (Ambiguous(c)) { - fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", - argv[1]); - return 0; - } - if (c->narg + 2 != argc) { - fprintf(stderr, - "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", - c->narg < argc + 2 ? "only " : "", - c->narg, c->narg == 1 ? "" : "s", c->name); - return 0; - } - return((*c->handler)(argv[2], argv[3])); -} -#endif - -#if defined(ENCRYPT) -/* - * The ENCRYPT command. - */ - -struct encryptlist { - char *name; - char *help; - int (*handler)(); - int needconnect; - int minarg; - int maxarg; -}; - -extern int - EncryptEnable P((char *, char *)), - EncryptDisable P((char *, char *)), - EncryptType P((char *, char *)), - EncryptStart P((char *)), - EncryptStartInput P((void)), - EncryptStartOutput P((void)), - EncryptStop P((char *)), - EncryptStopInput P((void)), - EncryptStopOutput P((void)), - EncryptStatus P((void)), - EncryptHelp P((void)); - -struct encryptlist EncryptList[] = { - { "enable", "Enable encryption. ('encrypt enable ?' for more)", - EncryptEnable, 1, 1, 2 }, - { "disable", "Disable encryption. ('encrypt enable ?' for more)", - EncryptDisable, 0, 1, 2 }, - { "type", "Set encryptiong type. ('encrypt type ?' for more)", - EncryptType, 0, 1, 1 }, - { "start", "Start encryption. ('encrypt start ?' for more)", - EncryptStart, 1, 0, 1 }, - { "stop", "Stop encryption. ('encrypt stop ?' for more)", - EncryptStop, 1, 0, 1 }, - { "input", "Start encrypting the input stream", - EncryptStartInput, 1, 0, 0 }, - { "-input", "Stop encrypting the input stream", - EncryptStopInput, 1, 0, 0 }, - { "output", "Start encrypting the output stream", - EncryptStartOutput, 1, 0, 0 }, - { "-output", "Stop encrypting the output stream", - EncryptStopOutput, 1, 0, 0 }, - - { "status", "Display current status of authentication information", - EncryptStatus, 0, 0, 0 }, - { "help", 0, EncryptHelp, 0, 0, 0 }, - { "?", "Print help information", EncryptHelp, 0, 0, 0 }, - { 0 }, -}; - - static int -EncryptHelp() -{ - struct encryptlist *c; - - for (c = EncryptList; c->name; c++) { - if (c->help) { - if (*c->help) - printf("%-15s %s\n", c->name, c->help); - else - printf("\n"); - } - } - return 0; -} - -encrypt_cmd(argc, argv) - int argc; - char *argv[]; -{ - struct encryptlist *c; - - c = (struct encryptlist *) - genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); - if (c == 0) { - fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", - argv[1]); - return 0; - } - if (Ambiguous(c)) { - fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", - argv[1]); - return 0; - } - argc -= 2; - if (argc < c->minarg || argc > c->maxarg) { - if (c->minarg == c->maxarg) { - fprintf(stderr, "Need %s%d argument%s ", - c->minarg < argc ? "only " : "", c->minarg, - c->minarg == 1 ? "" : "s"); - } else { - fprintf(stderr, "Need %s%d-%d arguments ", - c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); - } - fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", - c->name); - return 0; - } - if (c->needconnect && !connected) { - if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { - printf("?Need to be connected first.\n"); - return 0; - } - } - return ((*c->handler)(argc > 0 ? argv[2] : 0, - argc > 1 ? argv[3] : 0, - argc > 2 ? argv[4] : 0)); -} -#endif - -#if defined(unix) && defined(TN3270) -char *oflgs[] = { "read-only", "write-only", "read-write" }; - static void -filestuff(fd) - int fd; -{ - int res; - -#ifdef F_GETOWN - setconnmode(0); - res = fcntl(fd, F_GETOWN, 0); - setcommandmode(); - - if (res == -1) { - perror("fcntl"); - return; - } - printf("\tOwner is %d.\n", res); -#endif - - setconnmode(0); - res = fcntl(fd, F_GETFL, 0); - setcommandmode(); - - if (res == -1) { - perror("fcntl"); - return; - } - printf("\tFlags are 0x%x: %s\n", res, oflgs[res]); -} -#endif /* defined(unix) && defined(TN3270) */ +#endif /* TN3270 */ /* * Print status about the connection. */ -static int -status(int argc, char *argv[]) -{ +static int dostatus(int notmuch) { if (connected) { printf("Connected to %s.\n", hostname); - if ((argc < 2) || strcmp(argv[1], "notmuch")) { + if (!notmuch) { int mode = getconnmode(); if (my_want_state_is_will(TELOPT_LINEMODE)) { @@ -2044,10 +1504,12 @@ (mode&MODE_TRAPSIG) ? "Local" : "No"); slcstate(); #ifdef KLUDGELINEMODE - } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { + } + else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { printf("Operating in obsolete linemode\n"); #endif - } else { + } + else { printf("Operating in single character mode\n"); if (localchars) printf("Catching signals locally\n"); @@ -2055,21 +1517,18 @@ printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); if (my_want_state_is_will(TELOPT_LFLOW)) printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); -#if defined(ENCRYPT) - encrypt_display(); -#endif } - } else { + } + else { printf("No connection.\n"); } # if !defined(TN3270) - printf("Escape character is '%s'.\n", control(escape)); + printf("Escape character is '%s'.\n", control(escapechar)); (void) fflush(stdout); # else /* !defined(TN3270) */ - if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { + if ((!In3270) && !notmuch) { printf("Escape character is '%s'.\n", control(escape)); } -# if defined(unix) if ((argc >= 2) && !strcmp(argv[1], "everything")) { printf("SIGIO received %d time%s.\n", sigiocount, (sigiocount == 1)? "":"s"); @@ -2087,45 +1546,45 @@ if (In3270 && transcom) { printf("Transparent mode command is '%s'.\n", transcom); } -# endif /* defined(unix) */ - (void) fflush(stdout); + fflush(stdout); if (In3270) { return 0; } -# endif /* defined(TN3270) */ +#endif /* TN3270 */ return 1; } +static int status(void) { + int notmuch = 1; + return dostatus(notmuch); +} + #ifdef SIGINFO /* * Function that gets called when SIGINFO is received. */ -ayt_status() -{ - (void) call(status, "status", "notmuch", 0); +void ayt_status(int junk) { + (void) junk; + dostatus(1); } #endif -int -tn(int argc, char *argv[]) -{ +int tn(int argc, const char *argv[]) { register struct hostent *host = 0; - struct sockaddr_in sin; + struct sockaddr_in sn; struct servent *sp = 0; - unsigned int temp; - extern char *inet_ntoa(); -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) - char *srp = 0, *strrchr(); - unsigned long sourceroute(), srlen; -#endif - char *cmd, *hostp = 0, *portp = 0, *volatile user = 0; + char *srp = NULL; + int srlen; + + const char *cmd, *volatile user = 0; + const char *portp = NULL; + char *hostp = NULL; /* clear the socket address prior to use */ - bzero((char *)&sin, sizeof(sin)); + memset(&sn, 0, sizeof(sn)); if (connected) { printf("?Already connected to %s\n", hostname); - setuid(getuid()); return 0; } if (argc < 2) { @@ -2139,7 +1598,11 @@ cmd = *argv; --argc; ++argv; while (argc) { - if (isprefix(*argv, "help") || isprefix(*argv, "?")) + /* + * Having "telnet h" print usage is really stupid... + * suppose your hostname is h? + */ + if (/*isprefix(*argv, "help") ||*/ isprefix(*argv, "?")) goto usage; if (strcmp(*argv, "-l") == 0) { --argc; ++argv; @@ -2155,7 +1618,8 @@ continue; } if (hostp == 0) { - hostp = *argv++; + /* this leaks memory - FIXME */ + hostp = strdup(*argv++); --argc; continue; } @@ -2166,59 +1630,61 @@ } usage: printf("usage: %s [-l user] [-a] host-name [port]\n", cmd); - setuid(getuid()); return 0; } if (hostp == 0) goto usage; -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) +#if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) if (hostp[0] == '@' || hostp[0] == '!') { + int temp; + if ((hostname = strrchr(hostp, ':')) == NULL) hostname = strrchr(hostp, '@'); hostname++; srp = 0; + temp = sourceroute(hostp, &srp, &srlen); if (temp == 0) { herror(srp); - setuid(getuid()); return 0; } else if (temp == -1) { printf("Bad source route option: %s\n", hostp); - setuid(getuid()); return 0; } else { - sin.sin_addr.s_addr = temp; - sin.sin_family = AF_INET; + sn.sin_addr.s_addr = temp; + sn.sin_family = AF_INET; } - } else { + } + else { #endif - temp = inet_addr(hostp); - if (temp != (unsigned int) -1) { - sin.sin_addr.s_addr = temp; - sin.sin_family = AF_INET; - (void) strcpy(_hostname, hostp); + if (inet_aton(hostp, &sn.sin_addr)) { + sn.sin_family = AF_INET; + strcpy(_hostname, hostp); hostname = _hostname; - } else { + } + else { host = gethostbyname(hostp); if (host) { - sin.sin_family = host->h_addrtype; + sn.sin_family = host->h_addrtype; + if (host->h_length > (int)sizeof(sn.sin_addr)) { + host->h_length = sizeof(sn.sin_addr); + } #if defined(h_addr) /* In 4.3, this is a #define */ - memcpy((caddr_t)&sin.sin_addr, + memcpy((caddr_t)&sn.sin_addr, host->h_addr_list[0], host->h_length); #else /* defined(h_addr) */ - memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); + memcpy((caddr_t)&sn.sin_addr, host->h_addr, host->h_length); #endif /* defined(h_addr) */ strncpy(_hostname, host->h_name, sizeof(_hostname)); _hostname[sizeof(_hostname)-1] = '\0'; hostname = _hostname; } else { herror(hostp); - setuid(getuid()); return 0; } } -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) +#if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) } #endif if (portp) { @@ -2227,89 +1693,37 @@ telnetport = 1; } else telnetport = 0; - sin.sin_port = atoi(portp); - if (sin.sin_port == 0) { + sn.sin_port = atoi(portp); + if (sn.sin_port == 0) { sp = getservbyname(portp, "tcp"); if (sp) - sin.sin_port = sp->s_port; + sn.sin_port = sp->s_port; else { printf("%s: bad port number\n", portp); - setuid(getuid()); return 0; } - } else { -#if !defined(htons) - u_short htons(); -#endif /* !defined(htons) */ - sin.sin_port = htons(sin.sin_port); } - } else { + else { + sn.sin_port = htons(sn.sin_port); + } + } + else { if (sp == 0) { sp = getservbyname("telnet", "tcp"); if (sp == 0) { fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); - setuid(getuid()); return 0; } - sin.sin_port = sp->s_port; + sn.sin_port = sp->s_port; } telnetport = 1; } - printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); + printf("Trying %s...\n", inet_ntoa(sn.sin_addr)); do { - net = socket(AF_INET, SOCK_STREAM, 0); - setuid(getuid()); - if (net < 0) { - perror("telnet: socket"); - return 0; - } -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) - if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) - perror("setsockopt (IP_OPTIONS)"); -#endif -#if defined(IPPROTO_IP) && defined(IP_TOS) - { -# if defined(HAS_GETTOS) - struct tosent *tp; - if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) - tos = tp->t_tos; -# endif - if (tos < 0) - tos = 020; /* Low Delay bit */ - if (tos - && (setsockopt(net, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) - && (errno != ENOPROTOOPT)) - perror("telnet: setsockopt (IP_TOS) (ignored)"); - } -#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ - - if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { - perror("setsockopt (SO_DEBUG)"); - } - - if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { -#if defined(h_addr) /* In 4.3, this is a #define */ - if (host && host->h_addr_list[1]) { - int oerrno = errno; - - fprintf(stderr, "telnet: connect to address %s: ", - inet_ntoa(sin.sin_addr)); - errno = oerrno; - perror((char *)0); - host->h_addr_list++; - memcpy((caddr_t)&sin.sin_addr, - host->h_addr_list[0], host->h_length); - (void) NetClose(net); - continue; - } -#endif /* defined(h_addr) */ - perror("telnet: Unable to connect to remote host"); - return 0; - } + int x = nlink_connect(debug, host, &sn, srp, srlen, tos); + if (!x) return 0; + else if (x==1) continue; connected++; -#if defined(AUTHENTICATE) || defined(ENCRYPT) - auth_encrypt_connect(connected); -#endif } while (connected == 0); cmdrc(hostp, hostname); if (autologin && user == NULL) { @@ -2325,162 +1739,260 @@ } } if (user) { - env_define((unsigned char *)"USER", (unsigned char *)user); - env_export((unsigned char *)"USER"); + env_define("USER", user); + env_export("USER"); } - (void) call(status, "status", "notmuch", 0); - if (setjmp(peerdied) == 0) + dostatus(1); + if (sigsetjmp(peerdied, 1) == 0) telnet(user); - (void) NetClose(net); + nlink_close(0); ExitString("Connection closed by foreign host.\n",1); /*NOTREACHED*/ return 0; } -#define HELPINDENT (sizeof ("connect")) - static char openhelp[] = "connect to a site", closehelp[] = "close current connection", logouthelp[] = "forcibly logout remote user and close the connection", quithelp[] = "exit telnet", statushelp[] = "print status information", - helphelp[] = "print help information", sendhelp[] = "transmit special characters ('send ?' for more)", sethelp[] = "set operating parameters ('set ?' for more)", unsethelp[] = "unset operating parameters ('unset ?' for more)", togglestring[] ="toggle operating parameters ('toggle ?' for more)", - slchelp[] = "change state of special charaters ('slc ?' for more)", displayhelp[] = "display operating parameters", -#if defined(TN3270) && defined(unix) +#ifdef TN3270 transcomhelp[] = "specify Unix command for transparent mode pipe", -#endif /* defined(TN3270) && defined(unix) */ -#if defined(AUTHENTICATE) - authhelp[] = "turn on (off) authentication ('auth ?' for more)", -#endif -#if defined(ENCRYPT) - encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", -#endif -#if defined(unix) +#endif /* TN3270 */ zhelp[] = "suspend telnet", -#endif /* defined(unix) */ -/* shellhelp[] = "invoke a subshell", */ + shellhelp[] = "invoke a subshell", envhelp[] = "change environment variables ('environ ?' for more)", modestring[] = "try to enter line or character mode ('mode ?' for more)"; -static int help(); +static const char slcexporthelp[] = \ + "Use local special character definitions"; -static int -doquit(int ign1, char *ign2[]) -{ +static const char slcimporthelp[] = \ + "Use remote special character definitions"; + +static const char slccheckhelp[] = \ + "Verify remote special character definitions"; + + +static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; +static char escapehelp[] = "deprecated command -- use 'set escape' instead"; + +static int help(const command_table *, int, const char **); + +static int doquit(void) { quit(); return 0; } -static Command cmdtab[] = { - { "close", closehelp, bye, 1 }, - { "logout", logouthelp, logout, 1 }, - { "display", displayhelp, display, 0 }, - { "mode", modestring, modecmd, 0 }, - { "open", openhelp, tn, 0 }, - { "quit", quithelp, doquit, 0 }, - { "send", sendhelp, sendcmd, 0 }, - { "set", sethelp, setcmd, 0 }, - { "unset", unsethelp, unsetcmd, 0 }, - { "status", statushelp, status, 0 }, - { "toggle", togglestring, toggle, 0 }, - { "slc", slchelp, slccmd, 0 }, -#if defined(TN3270) && defined(unix) - { "transcom", transcomhelp, settranscom, 0 }, -#endif /* defined(TN3270) && defined(unix) */ -#if defined(AUTHENTICATE) - { "auth", authhelp, auth_cmd, 0 }, -#endif -#if defined(ENCRYPT) - { "encrypt", encrypthelp, encrypt_cmd, 0 }, -#endif -#if defined(unix) - { "z", zhelp, suspend, 0 }, -#endif /* defined(unix) */ -#if defined(TN3270) - { "!", shellhelp, shell, 0 }, +static int slc_mode_import_0(void) { + slc_mode_import(0); + return 1; +} + +static int slc_mode_import_1(void) { + slc_mode_import(1); + return 1; +} + +static int do_slc_mode_export(void) { + slc_mode_export(); + return 1; +} + +//////////////////////////////////////////////////////////// + +// thunk functions for type-safety. + +static int call_handler_sub(int ac, const char **av, const command_table *sub){ + if (ac<2) { + fprintf(stderr, "Command requires a subfunction.\n"); + fprintf(stderr, "Try %s ? for help.\n", av[0]); + return 0; /* is this right? */ + } + return process_command(sub, ac-1, av+1); +} + +static int call_handler_0(int ac, const char **av, int (*func)(void)) { + if (ac != 1) { + fprintf(stderr, "Wrong number of arguments for command.\n"); + fprintf(stderr, "Try %s ? for help.\n", av[0]); + return 0; /* is this right? */ + } + return func(); +} + +static int call_handler_1(int ac, const char **av, int (*func)(const char *)) { + if (ac != 2) { + fprintf(stderr, "Wrong number of arguments for command.\n"); + fprintf(stderr, "Try %s ? for help.\n", av[0]); + return 0; /* is this right? */ + } + return func(av[1]); +} + +#if 0 /* not used */ +static int call_handler_2(int ac, const char **av, + int (*func)(const char *, const char *)) { + if (ac != 3) { + fprintf(stderr, "Wrong number of arguments for command.\n"); + fprintf(stderr, "Try %s ? for help.\n", av[0]); + return 0; /* is this right? */ + } + return func(av[1], av[2]); +} #endif - { "environ", envhelp, env_cmd, 0 }, - { "?", helphelp, help, 0 }, - { NULL } + +#define THUNKSUB(tbl) \ + static int call_##tbl(int ac, const char **av) { \ + return call_handler_sub(ac, av, &tbl); \ + } +#define THUNK0(func) \ + static int call_##func(int ac, const char **av) {\ + return call_handler_0(ac, av, func); \ + } +#define THUNK1(func) \ + static int call_##func(int ac, const char **av) {\ + return call_handler_1(ac, av, func); \ + } +#define THUNK2(func) \ + static int call_##func(int ac, const char **av) {\ + return call_handler_2(ac, av, func); \ + } + +//////////////////////////////////////////////////////////// + +/* slctab thunks */ +THUNK0(do_slc_mode_export); +THUNK0(slc_mode_import_1); +THUNK0(slc_mode_import_0); + +static const command_entry slctabentries[] = { + { "export", slcexporthelp, call_do_slc_mode_export }, + { "import", slcimporthelp, call_slc_mode_import_1 }, + { "check", slccheckhelp, call_slc_mode_import_0 }, + + { NULL, NULL, NULL } }; +static const command_table slctab = { slctabentries }; -static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; -static char escapehelp[] = "deprecated command -- use 'set escape' instead"; +/* cmdtab2 thunks */ +THUNK0(togcrmod); + +static const command_entry cmdtab2entries[] = { + { "escape", escapehelp, setescape }, + { "crmod", crmodhelp, call_togcrmod }, -static Command cmdtab2[] = { - { "help", 0, help, 0 }, - { "escape", escapehelp, setescape, 0 }, - { "crmod", crmodhelp, togcrmod, 0 }, - { NULL } + { NULL, NULL, NULL } }; +static const command_table cmdtab2 = { cmdtab2entries }; +/* cmdtab thunks */ +THUNK0(bye); +THUNK0(logout); +THUNK1(modecmd); +THUNK0(doquit); +THUNK0(status); +THUNKSUB(slctab); +THUNK0(suspend); + +static const command_entry cmdtabentries[] = { + { "close", closehelp, call_bye }, + { "logout", logouthelp, call_logout }, + { "display", displayhelp, display }, + { "mode", modestring, call_modecmd }, + { "open", openhelp, tn }, + { "quit", quithelp, call_doquit }, + { "send", sendhelp, sendcmd }, + { "set", sethelp, setcmd }, + { "unset", unsethelp, unsetcmd }, + { "status", statushelp, call_status }, + { "toggle", togglestring, toggle }, + { "slc", "set treatment of special characters\n", call_slctab }, + +#ifdef TN3270 + { "transcom", transcomhelp, settranscom }, +#endif /* TN3270 */ + + //{ "auth", authhelp, auth_cmd }, + //{ "encrypt", encrypthelp, encrypt_cmd }, + + { "z", zhelp, call_suspend }, + { "!", shellhelp, shell }, + { "environ", envhelp, env_cmd }, -/* - * Call routine with argc, argv set from args (terminated by 0). - */ + { NULL, NULL, NULL }, +}; - /*VARARGS1*/ -static int -call(va_alist) - va_dcl -{ - va_list ap; - typedef int (*intrtn_t)(); - intrtn_t routine; - char *args[100]; - int argno = 0; +static const command_table cmdtab = { cmdtabentries }; - va_start(ap); - routine = (va_arg(ap, intrtn_t)); - while ((args[argno++] = va_arg(ap, char *)) != 0) { - ; - } - va_end(ap); - return (*routine)(argno-1, args); +void cmdtab_init(void) { + /* nothing (for now) */ } - static Command * -getcmd(name) - char *name; -{ - Command *cm; +static const command_entry *getcmd(const command_table *tab, const char *name){ + const command_entry *found = NULL; + int i; - cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)); - if (cm!=NULL) return cm; + if (!strcasecmp(name, "?") || + !strcasecmp(name, "h") || + !strcasecmp(name, "help")) return (command_entry *)HELP; - return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); + for (i=0; tab->entries[i].name != NULL; i++) { + const command_entry *c = &tab->entries[i]; + if (!strcasecmp(c->name, name)) return c; + if (!strncasecmp(c->name, name, strlen(name))) { + if (found != NULL) { + return (command_entry *)AMBIGUOUS; + } + found = c; + } } + if (tab==&cmdtab && found==NULL) return getcmd(&cmdtab2, name); - void -command(top, tbuf, cnt) - int top; - char *tbuf; - int cnt; -{ - register Command *c; + return found; +} + +static int process_command(const command_table *tab, + int argc, const char **argv) { + const command_entry *c; + c = getcmd(tab, argv[0]); + if (c == HELP) { + help(tab, argc, argv); + } + else if (c == AMBIGUOUS) { + printf("?Ambiguous command\n"); + } + else if (c == NULL) { + printf("?Invalid command\n"); + } + else { + if (c->handler(argc, argv)) return 1; + } + return 0; +} + +void command(int top, const char *tbuf, int cnt) { setcommandmode(); if (!top) { putchar('\n'); -#if defined(unix) - } else { - (void) signal(SIGINT, SIG_DFL); - (void) signal(SIGQUIT, SIG_DFL); -#endif /* defined(unix) */ + } + else { + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); } for (;;) { if (rlogin == _POSIX_VDISABLE) printf("%s> ", prompt); if (tbuf) { - register char *cp; - cp = line; + char *cp = line; while (cnt > 0 && (*cp++ = *tbuf++) != '\n') cnt--; tbuf = 0; @@ -2489,13 +2001,14 @@ *cp = '\0'; if (rlogin == _POSIX_VDISABLE) printf("%s\n", line); - } else { + } + else { getline: if (rlogin != _POSIX_VDISABLE) printf("%s> ", prompt); if (fgets(line, sizeof(line), stdin) == NULL) { if (feof(stdin) || ferror(stdin)) { - (void) quit(); + quit(); /*NOTREACHED*/ } break; @@ -2507,26 +2020,11 @@ if (margv[0] == 0) { break; } - c = getcmd(margv[0]); - if (Ambiguous(c)) { - printf("?Ambiguous command\n"); - continue; - } - if (c == 0) { - printf("?Invalid command\n"); - continue; - } - if (c->needconnect && !connected) { - printf("?Need to be connected first.\n"); - continue; - } - if ((*c->handler)(margc, margv)) { - break; - } + if (process_command(&cmdtab, margc, margv)) break; } if (!top) { if (!connected) { - longjmp(toplevel, 1); + siglongjmp(toplevel, 1); /*NOTREACHED*/ } #if defined(TN3270) @@ -2542,49 +2040,57 @@ /* * Help command. */ -static int -help(int argc, char *argv[]) -{ - register Command *c; +static int help(const command_table *tab, int argc, const char *argv[]) { + int i; if (argc == 1) { printf("Commands may be abbreviated. Commands are:\n\n"); - for (c = cmdtab; c->name; c++) - if (c->help) { - printf("%-*s\t%s\n", HELPINDENT, c->name, - c->help); + for (i = 0; tab->entries[i].name != NULL; i++) { + const command_entry *ce = &tab->entries[i]; + if (ce->help) { + printf("%-*s\t%s\n", HELPINDENT, ce->name, ce->help); + } + else { + /* added 8/2002 */ + printf("%-*s\t(no help available)\n", HELPINDENT, ce->name); + } } return 0; } - while (--argc > 0) { - register char *arg; - arg = *++argv; - c = getcmd(arg); - if (Ambiguous(c)) - printf("?Ambiguous help command %s\n", arg); - else if (c == (Command *)0) - printf("?Invalid help command %s\n", arg); - else + for (i=1; ihelp) { printf("%s\n", c->help); } + else { + printf("No help available.\n"); + } + } + } return 0; } static char *rcname = 0; static char rcbuf[128]; -void -cmdrc(char *m1, char *m2) -{ - register Command *c; +void cmdrc(const char *m1, const char *m2) { FILE *rcfile; int gotmachine = 0; int l1 = strlen(m1); int l2 = strlen(m2); char m1save[64]; - if (skiprc) - return; + if (skiprc) return; strcpy(m1save, m1); m1 = m1save; @@ -2599,13 +2105,10 @@ rcname = rcbuf; } - if ((rcfile = fopen(rcname, "r")) == 0) { - return; - } + rcfile = fopen(rcname, "r"); + if (!rcfile) return; - for (;;) { - if (fgets(line, sizeof(line), rcfile) == NULL) - break; + while (fgets(line, sizeof(line), rcfile)) { if (line[0] == 0) break; if (line[0] == '#') @@ -2617,6 +2120,7 @@ if (gotmachine == 0) { if (isspace(line[0])) continue; + /* XXX this code is not standards-compliant */ if (strncasecmp(line, m1, l1) == 0) strncpy(line, &line[l1], sizeof(line) - l1); else if (strncasecmp(line, m2, l2) == 0) @@ -2632,28 +2136,12 @@ makeargv(); if (margv[0] == 0) continue; - c = getcmd(margv[0]); - if (Ambiguous(c)) { - printf("?Ambiguous command: %s\n", margv[0]); - continue; - } - if (c == 0) { - printf("?Invalid command: %s\n", margv[0]); - continue; - } - /* - * This should never happen... - */ - if (c->needconnect && !connected) { - printf("?Need to be connected first for %s.\n", margv[0]); - continue; - } - (*c->handler)(margc, margv); + process_command(&cmdtab, margc, margv); } fclose(rcfile); } -#if defined(IP_OPTIONS) && defined(IPPROTO_IP) +#if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) /* * Source route is handed in as @@ -2694,15 +2182,9 @@ * pointed to by *cpp is. * */ - unsigned long -sourceroute(arg, cpp, lenp) - char *arg; - char **cpp; - int *lenp; -{ +static unsigned long sourceroute(char *arg, char **cpp, int *lenp) { static char lsr[44]; char *cp, *cp2, *lsrp, *lsrep; - register int tmp; struct in_addr sin_addr; register struct hostent *host = 0; register char c; @@ -2722,7 +2204,8 @@ if (*cpp) { lsrp = *cpp; lsrep = lsrp + *lenp; - } else { + } + else { *cpp = lsrp = lsr; lsrep = lsrp + 44; } @@ -2737,8 +2220,8 @@ if (*cp == '!') { cp++; *lsrp++ = IPOPT_SSRR; - } else - *lsrp++ = IPOPT_LSRR; + } + else *lsrp++ = IPOPT_LSRR; if (*cp != '@') return((unsigned long)-1); @@ -2753,7 +2236,7 @@ for (c = 0;;) { if (c == ':') cp2 = 0; - else for (cp2 = cp; c = *cp2; cp2++) { + else for (cp2 = cp; (c = *cp2) != 0; cp2++) { if (c == ',') { *cp2++ = '\0'; if (*cp2 == '@') @@ -2769,14 +2252,15 @@ if (!c) cp2 = 0; - if ((tmp = inet_addr(cp)) != -1) { - sin_addr.s_addr = tmp; - } else if (host = gethostbyname(cp)) { + if (inet_aton(cp, &sin_addr)) ; /* nothing */ + else if ((host = gethostbyname(cp))!=NULL) { + if (host->h_length > (int)sizeof(sin_addr)) { + host->h_length = sizeof(sin_addr); + } #if defined(h_addr) - memcpy((caddr_t)&sin_addr, - host->h_addr_list[0], host->h_length); + memcpy(&sin_addr, host->h_addr_list[0], host->h_length); #else - memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length); + memcpy(&sin_addr, host->h_addr, host->h_length); #endif } else { *cpp = cp; Index: defines.h =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/defines.h,v retrieving revision 1.2 retrieving revision 1.5 diff -w -u -r1.2 -r1.5 --- defines.h 16 Jul 1996 05:37:02 -0000 1.2 +++ defines.h 4 Aug 1996 23:44:43 -0000 1.5 @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)defines.h 5.1 (Berkeley) 9/14/90 - * $Id: defines.h,v 1.2 1996/07/16 05:37:02 dholland Exp $ + * $Id: defines.h,v 1.5 1996/08/04 23:44:43 dholland Exp $ */ #define ENV_VAR NEW_ENV_VAR @@ -41,22 +41,8 @@ #define settimer(x) clocks.x = clocks.system++ #if !defined(TN3270) - #define SetIn3270() - -#endif /* !defined(TN3270) */ - -#define NETADD(c) { *netoring.supply = c; ring_supplied(&netoring, 1); } -#define NET2ADD(c1,c2) { NETADD(c1); NETADD(c2); } -#define NETBYTES() (ring_full_count(&netoring)) -#define NETROOM() (ring_empty_count(&netoring)) - -#define TTYADD(c) if (!(SYNCHing||flushout)) { \ - *ttyoring.supply = c; \ - ring_supplied(&ttyoring, 1); \ - } -#define TTYBYTES() (ring_full_count(&ttyoring)) -#define TTYROOM() (ring_empty_count(&ttyoring)) +#endif /* Various modes */ #define MODE_LOCAL_CHARS(m) ((m)&(MODE_EDIT|MODE_TRAPSIG)) Index: depend.mk =================================================================== RCS file: depend.mk diff -N depend.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ depend.mk 11 Aug 2002 23:22:40 -0000 1.5 @@ -0,0 +1,17 @@ +carray.o: carray.c carray.h +commands.o: commands.c ring.h externs.h defines.h types.h genget.h \ + environ.h proto.h netlink.h +main.o: main.c ../version.h ring.h externs.h defines.h proto.h +network.o: network.c ring.h defines.h externs.h proto.h netlink.h +ring.o: ring.c ring.h +sys_bsd.o: sys_bsd.c ring.h defines.h externs.h types.h proto.h \ + netlink.h terminal.h +telnet.o: telnet.c ring.h defines.h externs.h types.h environ.h \ + proto.h netlink.h terminal.h +terminal.o: terminal.c ring.h defines.h externs.h types.h proto.h \ + terminal.h +tn3270.o: tn3270.c defines.h ring.h externs.h proto.h +utilities.o: utilities.c ring.h defines.h externs.h proto.h terminal.h +genget.o: genget.c genget.h +environ.o: environ.c ring.h defines.h externs.h environ.h carray.h +netlink.o: netlink.c netlink.h proto.h ring.h Index: environ.c =================================================================== RCS file: environ.c diff -N environ.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ environ.c 11 Aug 2002 23:23:32 -0000 1.16 @@ -0,0 +1,369 @@ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include "ring.h" +#include "defines.h" +#include "externs.h" +#include "environ.h" + +#ifdef __cplusplus +#include "ptrarray.h" +#else +#include "carray.h" +#endif + +char environ_rcsid[] = + "$Id: environ.c,v 1.16 2002/08/11 23:23:32 dholland Exp $"; + +static char *dostrdup(const char *s) { + char *x; +#ifdef __cplusplus + x = new char[strlen(s)+1]; + strcpy(x, s); +#else + x = strdup(s); + if (x==NULL) { + /* XXX / FIXME - this is weak */ + perror("malloc"); + exit(1); + } +#endif + return x; +} + +static void dofree(char *s) { +#ifdef __cplusplus + delete []s; +#else + free(s); +#endif +} + +//////////////////////////////////////////////////////////// + +struct enviro { + char *var; /* pointer to variable name */ + char *value; /* pointer to variable's value */ + int doexport; /* 1 -> export with default list of variables */ +}; + +static struct enviro *enviro_create(const char *var, const char *val, int exp){ + struct enviro *e; +#ifdef __cplusplus + e = new enviro; +#else + e = malloc(sizeof(struct enviro)); +#endif + e->var = dostrdup(var); + e->value = dostrdup(val); + e->doexport = exp; + return e; +} + +static void enviro_destroy(struct enviro *e) { + if (e->var) { + dofree(e->var); + } + e->var = NULL; + + if (e->value) { + dofree(e->value); + } + e->value = NULL; + +#ifdef __cplusplus + delete e; +#else + free(e); +#endif +} + +static void enviro_change(struct enviro *e, const char *val, int exp) { + if (e->value) { + dofree(e->value); + } + e->value = dostrdup(val); + e->doexport = exp; +} + +//////////////////////////////////////////////////////////// + +#ifdef __cplusplus +static ptrarray vars; +static inline int array_getnum(ptrarray &ar) { return ar.num(); } +static inline enviro *array_getguy(ptrarray &ar, int i) {return ar[i];} +static inline void array_setguy(ptrarray &ar, int i, enviro *e) { + ar[i] = e; +} +static inline void array_add(ptrarray &ar, enviro *ep) {ar.add(ep);} + +#else +static struct array *vars; +#endif + +//////////////////////////////////////////////////////////// + +static struct enviro *env_find(const char *var) { + int i; + for (i=0; ivar, var)) { + return e; + } + } + return NULL; +} + +static struct enviro *env_find_remove(const char *var) { + int i; + for (i=0; ivar, var)) { + array_setguy(vars, i, NULL); + return e; + } + } + return NULL; +} + +static void env_put(const char *var, const char *val, int exp) { + struct enviro *ep; + int i; + + ep = env_find(var); + if (ep) { + enviro_change(ep, val, exp); + return; + } + ep = enviro_create(var, val, exp); + + for (i=0; idoexport = 1; + + if (strncmp(ep->value, ":", 1) && strncmp(ep->value, "unix:", 5)) { + return; + } + cp2 = strrchr(ep->value, ':'); + if (sizeof(hbuf) < strlen(cp2)+1) { + /* too long - give up */ + return; + } + maxlen = sizeof(hbuf)-(strlen(cp2)+1); + gethostname(hbuf, maxlen); + hbuf[maxlen] = 0; /* ensure null termination */ + + /* + * dholland 7/30/96 if not a FQDN ask DNS + */ + if (!strchr(hbuf, '.')) { + struct hostent *h = gethostbyname(hbuf); + if (h) { + strncpy(hbuf, h->h_name, maxlen); + hbuf[maxlen] = 0; /* ensure null termination */ + } + /* + * dholland 8/11/02 this is somewhat dangerous, so print a warning. + * It would be nice to suppress this if the name came from /etc/hosts, + * which is pretty much trustworthy, but there's no way to tell that + * without reading /etc/hosts ourselves... ugh. + */ + warn = 1; + } + + strcat(hbuf, cp2); + + if (warn) { + printf("telnet: passing $DISPLAY as %s\n", hbuf); + } + + enviro_change(ep, hbuf, 1); +} + +/*********************************************** interface ***********/ + +void env_init(void) { + struct enviro *ep; + +#ifndef __cplusplus + vars = array_create(); +#endif + + /* + * Get the environment strings from our process environment. + */ + env_copy(); + + /* + * Always export DISPLAY. Also twiddle it if it aims at localhost. + */ + env_fix_display(); + + /* + * If USER is not defined, but LOGNAME is, then add + * USER with the value from LOGNAME. By default, we + * don't export the USER variable. + */ + if (!env_find("USER")) { + ep = env_find("LOGNAME"); + if (ep) env_put("USER", ep->value, 0); + } + + /* + * Automatically export PRINTER. + */ + ep = env_find("PRINTER"); + if (ep) ep->doexport = 1; +} + +void env_define(const char *var, const char *value) { + env_put(var, value, 1); +} + +void env_undefine(const char *var) { + struct enviro *ep = env_find_remove(var); + if (ep) { + enviro_destroy(ep); + } +} + +void env_export(const char *var) { + struct enviro *ep = env_find(var); + if (ep) ep->doexport = 1; +} + +void env_unexport(const char *var) { + struct enviro *ep = env_find(var); + if (ep) ep->doexport = 0; +} + +void env_send(const char *var) { + struct enviro *ep; + + if (my_state_is_wont(TELOPT_ENVIRON)) { + fprintf(stderr, "Cannot send '%s': Telnet ENVIRON option disabled\n", + var); + return; + } + + ep = env_find(var); + if (!ep) { + fprintf(stderr, "Cannot send '%s': variable not defined\n", var); + return; + } + env_opt_start_info(); + env_opt_add(ep->var); + env_opt_end(0); +} + +void env_list(void) { + int i; + for (i=0; idoexport ? '*' : ' ', + ep->var, ep->value); + } + } +} + +void env_iterate(int *iter, int exported_only) { + (void)exported_only; + + *iter = 0; +} + +const char *env_next(int *iter, int exported_only) { + while (*iter>=0 && *iterdoexport || !exported_only) { + return ep->var; + } + } + return NULL; +} + +const char *env_getvalue(const char *var, int exported_only) { + struct enviro *ep = env_find(var); + if (ep && (!exported_only || ep->doexport)) + return ep->value; + return NULL; +} Index: environ.h =================================================================== RCS file: environ.h diff -N environ.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ environ.h 11 Aug 2002 23:23:32 -0000 1.4 @@ -0,0 +1,12 @@ +void env_define(const char *var, const char *val); +void env_undefine(const char *var); +void env_export(const char *var); +void env_unexport(const char *); +void env_send(const char *); +void env_list(void); +const char *env_getvalue(const char *, int exported_only); + +void env_iterate(int *, int exported_only); +const char *env_next(int *, int exported_only); + +void env_init(void); Index: externs.h =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/externs.h,v retrieving revision 1.2 retrieving revision 1.24 diff -w -u -r1.2 -r1.24 --- externs.h 16 Jul 1996 05:17:22 -0000 1.2 +++ externs.h 11 Aug 2002 23:23:32 -0000 1.24 @@ -31,122 +31,82 @@ * SUCH DAMAGE. * * from: @(#)externs.h 5.3 (Berkeley) 3/22/91 - * $Id: externs.h,v 1.2 1996/07/16 05:17:22 dholland Exp $ + * $Id: externs.h,v 1.24 2002/08/11 23:23:32 dholland Exp $ */ #ifndef BSD # define BSD 43 #endif -#if (BSD > 43 || defined(SYSV_TERMIO)) && !defined(USE_TERMIO) -# define USE_TERMIO -#endif - #include #include -#include -#include +#include #include -#ifdef USE_TERMIO -# ifndef VINTR -# ifdef SYSV_TERMIO -# include -# else -# include -# define termio termios -# error "This doesn't work for Linux..." -# endif -# endif -#endif -#if defined(NO_CC_T) || !defined(USE_TERMIO) -# if !defined(USE_TERMIO) -typedef char cc_t; -# else + +#if defined(NO_CC_T) typedef unsigned char cc_t; # endif -#endif -#ifndef NO_STRING_H -#include +#ifdef __linux__ +#include /* get _POSIX_VDISABLE */ #endif -#include #ifndef _POSIX_VDISABLE -# ifdef sun -# include /* pick up VDISABLE definition, mayby */ -# endif -# ifdef VDISABLE -# define _POSIX_VDISABLE VDISABLE -# else -# define _POSIX_VDISABLE ((cc_t)'\377') -# endif +#error "Please fix externs.h to define _POSIX_VDISABLE" #endif #define SUBBUFSIZE 256 -extern int errno; /* outside this world */ - -#if !defined(P) -# ifdef __STDC__ -# define P(x) x -# else -# define P(x) () -# endif -#endif - -extern int - autologin, /* Autologin enabled */ - skiprc, /* Don't process the ~/.telnetrc file */ - eight, /* use eight bit mode (binary in and/or out */ - flushout, /* flush output */ - connected, /* Are we connected to the other side? */ - globalmode, /* Mode tty should be in */ - In3270, /* Are we in 3270 mode? */ - telnetport, /* Are we connected to the telnet port? */ - localflow, /* Flow control handled locally */ - localchars, /* we recognize interrupt/quit */ - donelclchars, /* the user has set "localchars" */ - showoptions, - net, /* Network file descriptor */ - tin, /* Terminal input file descriptor */ - tout, /* Terminal output file descriptor */ - crlf, /* Should '\r' be mapped to (or )? */ - autoflush, /* flush output when interrupting? */ - autosynch, /* send interrupt characters with SYNCH? */ - SYNCHing, /* Is the stream in telnet SYNCH mode? */ - donebinarytoggle, /* the user has put us in binary */ - dontlecho, /* do we suppress local echoing right now? */ - crmod, - netdata, /* Print out network data flow */ - prettydump, /* Print "netdata" output in user readable format */ -#if defined(unix) -#if defined(TN3270) - cursesdata, /* Print out curses data flow */ -#endif /* defined(TN3270) */ - termdata, /* Print out terminal data flow */ -#endif /* defined(unix) */ - debug; /* Debug level */ +extern int autologin; /* Autologin enabled */ +extern int skiprc; /* Don't process the ~/.telnetrc file */ +extern int eight; /* use eight bit mode (binary in and/or out */ +extern int flushout; /* flush output */ +extern int connected; /* Are we connected to the other side? */ +extern int globalmode; /* Mode tty should be in */ +extern int In3270; /* Are we in 3270 mode? */ +extern int telnetport; /* Are we connected to the telnet port? */ +extern int localflow; /* Flow control handled locally */ +extern int localchars; /* we recognize interrupt/quit */ +extern int donelclchars; /* the user has set "localchars" */ +extern int showoptions; + +extern int crlf; /* Should '\r' be mapped to (or )? */ +extern int autoflush; /* flush output when interrupting? */ +extern int autosynch; /* send interrupt characters with SYNCH? */ +extern int SYNCHing; /* Is the stream in telnet SYNCH mode? */ +extern int donebinarytoggle; /* the user has put us in binary */ +extern int dontlecho; /* do we suppress local echoing right now? */ +extern int crmod; +//extern int netdata; /* Print out network data flow */ +//extern int prettydump; /* Print "netdata" output in user readable format */ +extern int debug; /* Debug level */ + +extern int linemode; +extern int resettermname; /* signaling flag for gettermname() */ + +extern char will_wont_resp[], do_dont_resp[]; +extern int want_status_response; + + +#ifdef TN3270 +extern int cursesdata; /* Print out curses data flow */ +#endif /* unix and TN3270 */ -extern cc_t escape; /* Escape to command mode */ +extern cc_t escapechar; /* Escape to command mode */ extern cc_t rlogin; /* Rlogin mode escape character */ #ifdef KLUDGELINEMODE extern cc_t echoc; /* Toggle local echoing */ +extern int kludgelinemode; #endif -extern char - *prompt; /* Prompt for command. */ +extern char *prompt; /* Prompt for command. */ -extern char - doopt[], - dont[], - will[], - wont[], - options[], /* All the little options */ - *hostname; /* Who are we connected to? */ -#if defined(ENCRYPT) -extern void (*encrypt_output) P((unsigned char *, int)); -extern int (*decrypt_input) P((int)); -#endif +extern char doopt[]; +extern char dont[]; +extern char will[]; +extern char wont[]; +extern char options[]; /* All the little options */ +extern char *hostname; /* Who are we connected to? */ /* * We keep track of each side of the option negotiation. @@ -182,7 +142,7 @@ #define set_my_want_state_wont(opt) {options[opt] &= ~MY_WANT_STATE_WILL;} /* - * Make everything symetrical + * Make everything symmetric */ #define HIS_STATE_WILL MY_STATE_DO @@ -211,119 +171,66 @@ #define set_his_want_state_wont set_my_want_state_dont -extern FILE - *NetTrace; /* Where debugging output goes */ -extern unsigned char - NetTraceFile[]; /* Name of file where debugging output goes */ -extern void - SetNetTrace P((char *)); /* Function to change where debugging goes */ - -extern jmp_buf - peerdied, - toplevel; /* For error conditions. */ - -extern void - command P((int, char *, int)), - Dump P((int, unsigned char *, int)), - init_3270 P((void)), - printoption P((char *, int, int)), - printsub P((int, unsigned char *, int)), - sendnaws P((void)), - setconnmode P((int)), - setcommandmode P((void)), - setneturg P((void)), - sys_telnet_init P((void)), - telnet P((char *)), - tel_enter_binary P((int)), - TerminalFlushOutput P((void)), - TerminalNewMode P((int)), - TerminalRestoreState P((void)), - TerminalSaveState P((void)), - tninit P((void)), - upcase P((char *)), - willoption P((int)), - wontoption P((int)); - -extern void - lm_will P((unsigned char *, int)), - lm_wont P((unsigned char *, int)), - lm_do P((unsigned char *, int)), - lm_dont P((unsigned char *, int)), - lm_mode P((unsigned char *, int, int)); - -extern void - slc_init P((void)), - slcstate P((void)), - slc_mode_export P((void)), - slc_mode_import P((int)), - slc_import P((int)), - slc_export P((void)), - slc P((unsigned char *, int)), - slc_check P((void)), - slc_start_reply P((void)), - slc_add_reply P((int, int, int)), - slc_end_reply P((void)); -extern int - slc_update P((void)); - -extern void - env_opt P((unsigned char *, int)), - env_opt_start P((void)), - env_opt_start_info P((void)), - env_opt_add P((unsigned char *)), - env_opt_end P((int)); - -extern unsigned char - *env_default P((int)), - *env_getvalue P((unsigned char *)); - -extern int - get_status P((void)), - dosynch P((void)); - -extern cc_t - *tcval P((int)); - -#ifndef USE_TERMIO - -extern struct tchars ntc; -extern struct ltchars nltc; -extern struct sgttyb nttyb; - -# define termEofChar ntc.t_eofc -# define termEraseChar nttyb.sg_erase -# define termFlushChar nltc.t_flushc -# define termIntChar ntc.t_intrc -# define termKillChar nttyb.sg_kill -# define termLiteralNextChar nltc.t_lnextc -# define termQuitChar ntc.t_quitc -# define termSuspChar nltc.t_suspc -# define termRprntChar nltc.t_rprntc -# define termWerasChar nltc.t_werasc -# define termStartChar ntc.t_startc -# define termStopChar ntc.t_stopc -# define termForw1Char ntc.t_brkc -extern cc_t termForw2Char; -extern cc_t termAytChar; +extern FILE *NetTrace; /* Where debugging output goes */ +extern char NetTraceFile[]; /* Name of file where debugging output goes */ -# define termEofCharp (cc_t *)&ntc.t_eofc -# define termEraseCharp (cc_t *)&nttyb.sg_erase -# define termFlushCharp (cc_t *)&nltc.t_flushc -# define termIntCharp (cc_t *)&ntc.t_intrc -# define termKillCharp (cc_t *)&nttyb.sg_kill -# define termLiteralNextCharp (cc_t *)&nltc.t_lnextc -# define termQuitCharp (cc_t *)&ntc.t_quitc -# define termSuspCharp (cc_t *)&nltc.t_suspc -# define termRprntCharp (cc_t *)&nltc.t_rprntc -# define termWerasCharp (cc_t *)&nltc.t_werasc -# define termStartCharp (cc_t *)&ntc.t_startc -# define termStopCharp (cc_t *)&ntc.t_stopc -# define termForw1Charp (cc_t *)&ntc.t_brkc -# define termForw2Charp (cc_t *)&termForw2Char -# define termAytCharp (cc_t *)&termAytChar +void SetNetTrace(const char *); /* Function to change where debugging goes */ -# else +extern sigjmp_buf peerdied; +extern sigjmp_buf toplevel; /* For error conditions. */ + +void command(int, const char *, int); +void Dump (int, char *, int); +void init_3270 (void); +void printoption(const char *, int, int); +void printsub (int, unsigned char *, int); +void sendnaws (void); +void setconnmode(int); +void setcommandmode (void); +void setneturg (void); +void sys_telnet_init (void); +void telnet(const char *); +void tel_enter_binary(int); +void TerminalFlushOutput(void); +void TerminalNewMode(int); +void TerminalRestoreState(void); +void TerminalSaveState(void); +void tninit(void); +void upcase(char *); +void willoption(int); +void wontoption(int); + +void lm_will(unsigned char *, int); +void lm_wont(unsigned char *, int); +void lm_do(unsigned char *, int); +void lm_dont(unsigned char *, int); +void lm_mode(unsigned char *, int, int); + +void slc_init(void); +void slcstate(void); +void slc_mode_export(void); +void slc_mode_import(int); +void slc_import(int); +void slc_export(void); +void slc(unsigned char *, int); +void slc_check(void); +void slc_start_reply(void); +void slc_add_reply(int, int, int); +void slc_end_reply(void); +int slc_update(void); + +void env_opt(unsigned char *, int); +void env_opt_start(void); +void env_opt_start_info(void); +void env_opt_add(const char *); +void env_opt_end(int); + +int get_status(const char *, const char *); +int dosynch(void); + +cc_t *tcval(int); +//#if 0 extern struct termios new_tc; # define termEofChar new_tc.c_cc[VEOF] @@ -337,6 +244,7 @@ # else # define termSuspChar new_tc.c_cc[VSUSP] # endif + # if defined(VFLUSHO) && !defined(VDISCARD) # define VDISCARD VFLUSHO # endif @@ -345,47 +253,58 @@ # else # define termFlushChar new_tc.c_cc[VDISCARD] # endif + # ifndef VWERASE extern cc_t termWerasChar; # else # define termWerasChar new_tc.c_cc[VWERASE] # endif + # ifndef VREPRINT extern cc_t termRprntChar; # else # define termRprntChar new_tc.c_cc[VREPRINT] # endif + # ifndef VLNEXT extern cc_t termLiteralNextChar; # else # define termLiteralNextChar new_tc.c_cc[VLNEXT] # endif + # ifndef VSTART extern cc_t termStartChar; # else # define termStartChar new_tc.c_cc[VSTART] # endif + # ifndef VSTOP extern cc_t termStopChar; # else # define termStopChar new_tc.c_cc[VSTOP] # endif + # ifndef VEOL extern cc_t termForw1Char; # else # define termForw1Char new_tc.c_cc[VEOL] # endif + # ifndef VEOL2 extern cc_t termForw2Char; # else # define termForw2Char new_tc.c_cc[VEOL] # endif + # ifndef VSTATUS extern cc_t termAytChar; #else # define termAytChar new_tc.c_cc[VSTATUS] #endif +//#endif /* 0 */ + +//#if 0 # if !defined(CRAY) || defined(__STDC__) # define termEofCharp &termEofChar # define termEraseCharp &termEraseChar @@ -420,40 +339,47 @@ # define termForw2Charp 0 # define termAytCharp 0 # endif -#endif + +//#endif /* 0 */ /* Ring buffer structures which are shared */ -extern Ring - netoring, - netiring, - ttyoring, - ttyiring; +extern struct ringbuf *netoring; +extern struct ringbuf *netiring; +extern struct ringbuf *ttyoring; +extern struct ringbuf *ttyiring; /* Tn3270 section */ #if defined(TN3270) -extern int - HaveInput, /* Whether an asynchronous I/O indication came in */ - noasynchtty, /* Don't do signals on I/O (SIGURG, SIGIO) */ - noasynchnet, /* Don't do signals on I/O (SIGURG, SIGIO) */ - sigiocount, /* Count of SIGIO receptions */ - shell_active; /* Subshell is active */ - -extern char - *Ibackp, /* Oldest byte of 3270 data */ - Ibuf[], /* 3270 buffer */ - *Ifrontp, /* Where next 3270 byte goes */ - tline[], - *transcom; /* Transparent command */ +extern int HaveInput; /* Whether an asynchronous I/O indication came in */ +extern int noasynchtty; /* Don't do signals on I/O (SIGURG, SIGIO) */ +extern int noasynchnet; /* Don't do signals on I/O (SIGURG, SIGIO) */ +extern int sigiocount; /* Count of SIGIO receptions */ +extern int shell_active; /* Subshell is active */ + +extern char *Ibackp; /* Oldest byte of 3270 data */ +extern char Ibuf[]; /* 3270 buffer */ +extern char *Ifrontp; /* Where next 3270 byte goes */ +extern char tline[]; +extern char *transcom; /* Transparent command */ + +void settranscom(int, char**); +//int shell(int, char**); +void inputAvailable(void); -extern void - settranscom P((int, char**)); +#endif /* defined(TN3270) */ -extern int - shell P((int, char**)); +void intp(void); +void sendbrk(void); +void sendabort(void); +void xmitAO(void); +void xmitEL(void); +void xmitEC(void); + +void send_do(int, int); +void send_dont(int, int); +void send_will(int, int); +void send_wont(int, int); -extern void - inputAvailable P((void)); -#endif /* defined(TN3270) */ Index: genget.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/genget.c,v retrieving revision 1.2 retrieving revision 1.3 diff -w -u -r1.2 -r1.3 --- genget.c 16 Jul 1996 09:14:25 -0000 1.2 +++ genget.c 26 Jul 1996 09:54:09 -0000 1.3 @@ -35,11 +35,13 @@ * From: @(#)genget.c 5.1 (Berkeley) 2/28/91 */ char gg_rcsid[] = - "$Id: genget.c,v 1.2 1996/07/16 09:14:25 dholland Exp $"; - + "$Id: genget.c,v 1.3 1996/07/26 09:54:09 dholland Exp $"; +#include #include +#include "genget.h" + #define LOWER(x) (isupper(x) ? tolower(x) : (x)) /* * The prefix function returns 0 if *s1 is not a prefix @@ -47,61 +49,43 @@ * the length is returned. If *s1 is a prefix of *s2, * the length of *s1 is returned. */ - int -isprefix(s1, s2) - register char *s1, *s2; -{ -/* register int n = 0; */ - char *os1; - register char c1, c2; +int isprefix(const char *s1, const char *s2) { + const char *os1; + char c1, c2; + + if (*s1 == 0) return -1; - if (*s1 == '\0') - return(-1); os1 = s1; c1 = *s1; c2 = *s2; + while (LOWER(c1) == LOWER(c2)) { - if (c1 == '\0') - break; + if (c1 == 0) break; c1 = *++s1; c2 = *++s2; } - return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1))); + if (*s1) return 0; + return *s2 ? (s1 - os1) : (os1 - s1); } -static char *ambiguous; /* special return value for command routines */ - - char ** -genget(name, table, stlen) - char *name; /* name to match */ - char **table; /* name entry in table */ - int stlen; -{ - register char **c, **found; - register int n; - - if (name == 0) - return 0; - - found = 0; - for (c = table; *c != 0; c = (char **)((char *)c + stlen)) { - if ((n = isprefix(name, *c)) == 0) - continue; - if (n < 0) /* exact match */ - return(c); - if (found) - return(&ambiguous); +/* + * name: name to match + * table: name entry in table + */ +char **genget(const char *name, char **table, int stlen) { + char **c, **found; + int n; + + if (!name) return NULL; + + found = NULL; + for (c = table; *c; c = (char **)((char *)c + stlen)) { + n = isprefix(name, *c); + if (n == 0) continue; + if (n < 0) return c; /* exact match */ + if (found) return (char **)AMBIGUOUS; found = c; } - return(found); + return found; } -/* - * Function call version of Ambiguous() - */ - int -Ambiguous(s) - char *s; -{ - return((char **)s == &ambiguous); -} Index: genget.h =================================================================== RCS file: genget.h diff -N genget.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ genget.h 5 Aug 1996 05:15:34 -0000 1.4 @@ -0,0 +1,5 @@ +int isprefix(const char *, const char *); +char **genget(const char *, char **, int); + +#define AMBIGUOUS ((void *)1) +#define HELP ((void *)2) Index: main.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/main.c,v retrieving revision 1.3 retrieving revision 1.15 diff -w -u -r1.3 -r1.15 --- main.c 16 Jul 1996 09:23:59 -0000 1.3 +++ main.c 11 Aug 2002 23:23:32 -0000 1.15 @@ -39,13 +39,13 @@ * From: @(#)main.c 5.4 (Berkeley) 3/22/91 */ char main_rcsid[] = - "$Id: main.c,v 1.3 1996/07/16 09:23:59 dholland Exp $"; + "$Id: main.c,v 1.15 2002/08/11 23:23:32 dholland Exp $"; + +#include "../version.h" -#include #include #include -#include -#include +#include #include "ring.h" #include "externs.h" @@ -71,32 +71,23 @@ #endif } - void -usage() -{ +/* + * note: -x should mean use encryption + * -k to set kerberos realm + * -K don't auto-login + * -X disable specified auth type + */ +static void usage(void) { fprintf(stderr, "Usage: %s %s%s%s%s\n", prompt, -#ifdef AUTHENTICATE - " [-8] [-E] [-K] [-L] [-X atype] [-a] [-d] [-e char] [-k realm]", - "\n\t[-l user] [-n tracefile] ", -#else " [-8] [-E] [-L] [-a] [-d] [-e char] [-l user] [-n tracefile]", "\n\t", -#endif -#if defined(TN3270) && defined(unix) -# ifdef AUTHENTICATE - "[-noasynch] [-noasynctty] [-noasyncnet]\n\t[-r] [-t transcom] ", -# else +#ifdef TN3270 "[-noasynch] [-noasynctty] [-noasyncnet] [-r] [-t transcom]\n\t", -# endif #else "[-r] ", #endif -#ifdef ENCRYPT - "[-x] [host-name [port]]" -#else "[host-name [port]]" -#endif ); exit(1); } @@ -108,10 +99,8 @@ int main(int argc, char *argv[]) { - extern char *optarg; - extern int optind; int ch; - char *user, *strrchr(); + char *user; tninit(); /* Clear out things */ #if defined(CRAY) && !defined(__STDC__) @@ -136,12 +125,10 @@ eight = 3; /* binary output and input */ break; case 'E': - rlogin = escape = _POSIX_VDISABLE; + rlogin = escapechar = _POSIX_VDISABLE; break; case 'K': -#ifdef AUTHENTICATE - autologin = 0; -#endif + //autologin = 0; break; case 'L': eight |= 2; /* binary output only */ @@ -164,9 +151,7 @@ } break; case 'X': -#ifdef AUTHENTICATE - auth_disable_name(optarg); -#endif + // disable authentication type "optarg" break; case 'a': autologin = 1; @@ -181,24 +166,16 @@ set_escape_char(optarg); break; case 'k': -#if defined(AUTHENTICATE) && defined(KRB4) - { - extern char *dest_realm, dst_realm_buf[], dst_realm_sz; - dest_realm = dst_realm_buf; - (void)strncpy(dest_realm, optarg, dst_realm_sz); - } -#else fprintf(stderr, - "%s: Warning: -k ignored, no Kerberos V4 support.\n", + "%s: -k ignored, no Kerberos V4 support.\n", prompt); -#endif break; case 'l': autologin = 1; user = optarg; break; case 'n': -#if defined(TN3270) && defined(unix) +#ifdef TN3270 /* distinguish between "-n oasynch" and "-noasynch" */ if (argv[optind - 1][0] == '-' && argv[optind - 1][1] == 'n' && argv[optind - 1][2] == 'o') { @@ -210,14 +187,14 @@ else if (!strcmp(optarg, "oasynchnet")) noasynchnet = 1; } else -#endif /* defined(TN3270) && defined(unix) */ +#endif /* TN3270 */ SetNetTrace(optarg); break; case 'r': rlogin = '~'; break; case 't': -#if defined(TN3270) && defined(unix) +#ifdef TN3270 transcom = tline; (void)strcpy(transcom, optarg); #else @@ -227,14 +204,9 @@ #endif break; case 'x': -#ifdef ENCRYPT - encrypt_auto(1); - decrypt_auto(1); -#else fprintf(stderr, - "%s: Warning: -x ignored, no ENCRYPT support.\n", + "%s: -x ignored, no encryption support.\n", prompt); -#endif break; case '?': default: @@ -249,7 +221,8 @@ argv += optind; if (argc) { - char *args[7], **volatile argp = args; + const char *args[7]; + const char **volatile argp = args; if (argc > 2) usage(); @@ -263,14 +236,14 @@ *argp++ = argv[1]; /* port */ *argp = 0; - if (setjmp(toplevel) != 0) + if (sigsetjmp(toplevel, 1) != 0) Exit(0); if (tn(argp - args, args) == 1) return (0); else return (1); } - (void)setjmp(toplevel); + (void)sigsetjmp(toplevel, 1); for (;;) { #ifdef TN3270 if (shell_active) Index: netlink.c =================================================================== RCS file: netlink.c diff -N netlink.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ netlink.c 11 Aug 2002 22:52:55 -0000 1.24 @@ -0,0 +1,237 @@ +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "netlink.h" +#include "proto.h" +#include "ring.h" + +char netlink_rcsid[] = + "$Id: netlink.c,v 1.24 2002/08/11 22:52:55 dholland Exp $"; + +/* In Linux, this is an enum */ +#if defined(__linux__) || defined(IPPROTO_IP) +#define HAS_IPPROTO_IP +#endif + +//////////////////////////////////////////////////////////// + +static int netsource_read(char *buf, int maxlen) { + int net = nlink_getfd(); + int l = recv(net, buf, maxlen, 0); + if (l<0 && errno == EWOULDBLOCK) l = 0; + return l; +} + +static int netsink_write(const char *buf, int len) { + int r = nlink_send(buf, len, 0); + if (r==-1 && (errno==ENOBUFS || errno==EWOULDBLOCK)) return 0; + return r; +} + +static int netsink_writeurg(const char *buf, int len) { + int r, rr; + /* + * In 4.2 (and 4.3) systems, there is some question about + * what byte in a sendOOB operation is the "OOB" data. + * To make ourselves compatible, we only send ONE byte + * out of band, the one WE THINK should be OOB (though + * we really have more the TCP philosophy of urgent data + * rather than the Unix philosophy of OOB data). + */ + if (len==0) return 0; + + r = nlink_send(buf, 1, MSG_OOB); + if (r==-1 && (errno==ENOBUFS || errno==EWOULDBLOCK)) r = 0; + if (r<=0) return r; + + rr = nlink_send(buf+1, len-r, 0); + if (rr==-1 && (errno==ENOBUFS || errno==EWOULDBLOCK)) rr = 0; + if (rr<=0) return r; /* less than ideal */ + + return r+rr; +} + +static const struct datasource_c chan = { + netsource_read, /* read */ +}; +const struct datasource_c *const netsrc = &chan; + +static const struct datasink_c chan2 = { + netsink_write, /* write */ + netsink_writeurg, /* writeurg */ +}; +const struct datasink_c *const netsink = &chan2; + +//////////////////////////////////////////////////////////// + +static int netfd = -1; + +int nlink_setdebug(int debug) { + if (netfd > 0 && + (setsockopt(netfd, SOL_SOCKET, SO_DEBUG, &debug, sizeof(debug))) < 0) { + perror("setsockopt (SO_DEBUG)"); + } + return 1; +} + +void nlink_close(int doshutdown) { + if (doshutdown) { + shutdown(netfd, 2); + } + close(netfd); + netfd = -1; +} + +int nlink_connect(int debug, struct hostent *host, + struct sockaddr_in *sn, + char *srcroute, int srlen, int tos) +{ + int on=1; + + netfd = socket(AF_INET, SOCK_STREAM, 0); + if (netfd < 0) { + perror("telnet: socket"); + return 0; + } + +#if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP) + if (srcroute) { + if (setsockopt(netfd, IPPROTO_IP, IP_OPTIONS, srcroute, srlen) < 0) + perror("setsockopt (IP_OPTIONS)"); + } +#endif + +#if defined(HAS_IPPROTO_IP) && defined(IP_TOS) +#if defined(HAS_GETTOS) + struct tosent *tp; + if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) + tos = tp->t_tos; +#endif + if (tos < 0) tos = 020; /* Low Delay bit */ + if (tos && (setsockopt(netfd, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) + && (errno != ENOPROTOOPT)) + perror("telnet: setsockopt (IP_TOS) (ignored)"); +#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ + + if (debug && setsockopt(netfd, SOL_SOCKET, SO_DEBUG, &on, sizeof(on)) < 0){ + perror("setsockopt (SO_DEBUG)"); + } + + if (connect(netfd, (struct sockaddr *)sn, sizeof(*sn)) < 0) { +#if defined(h_addr) /* In 4.3, this is a #define */ + if (host && host->h_addr_list[1]) { + int oerrno = errno; + + fprintf(stderr, "telnet: connect to address %s: ", + inet_ntoa(sn->sin_addr)); + errno = oerrno; + perror(NULL); + host->h_addr_list++; + if (host->h_length > (int)sizeof(sn->sin_addr)) { + host->h_length = sizeof(sn->sin_addr); + } + memcpy(&sn->sin_addr, host->h_addr_list[0], host->h_length); + close(netfd); + netfd = -1; + return 1; + } +#endif /* defined(h_addr) */ + + perror("telnet: Unable to connect to remote host"); + return 0; + } + return 2; +} + + +void nlink_oobinline(void) { + int on=1; + + /* Systems without SO_OOBINLINE probably won't work */ + if (setsockopt(netfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) == -1) { + perror("setsockopt"); + } +} + + +/* + * Check to see if any out-of-band data exists on a socket (for + * Telnet "synch" processing). + */ + +int nlink_stilloob(void) { + static struct timeval timeout = { 0, 0 }; + fd_set excepts; + int value; + + do { + FD_ZERO(&excepts); + FD_SET(netfd, &excepts); + value = select(netfd+1, NULL, NULL, &excepts, &timeout); + } while ((value == -1) && (errno == EINTR)); + + if (value < 0) { + perror("select"); + quit(); + /* NOTREACHED */ + } + if (FD_ISSET(netfd, &excepts)) { + return 1; + } else { + return 0; + } +} + +int nlink_send(const char *s, int n, int f) { + return send(netfd, s, n, f); +} + +void nlink_nonblock(int onoff) { + ioctl(netfd, FIONBIO, &onoff); +} + +int nlink_getfd(void) { + return netfd; +} Index: netlink.h =================================================================== RCS file: netlink.h diff -N netlink.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ netlink.h 11 Aug 2002 20:55:37 -0000 1.5 @@ -0,0 +1,19 @@ +struct sockaddr_in; +struct hostent; + +int nlink_connect(int debug, struct hostent *host, + struct sockaddr_in *sin, + char *srcroute, int srlen, + int tos); +void nlink_close(int doshutdown); + +int nlink_setdebug(int debug); +void nlink_oobinline(void); +void nlink_nonblock(int onoff); + +int nlink_stilloob(void); + +int nlink_send(const char *buf, int len, int flags); + +int nlink_getfd(void); + Index: network.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/network.c,v retrieving revision 1.2 retrieving revision 1.18 diff -w -u -r1.2 -r1.18 --- network.c 16 Jul 1996 07:57:25 -0000 1.2 +++ network.c 11 Aug 2002 20:56:25 -0000 1.18 @@ -35,9 +35,8 @@ * From: @(#)network.c 5.2 (Berkeley) 3/1/91 */ char net_rcsid[] = - "$Id: network.c,v 1.2 1996/07/16 07:57:25 dholland Exp $"; + "$Id: network.c,v 1.18 2002/08/11 20:56:25 dholland Exp $"; -#include #include #include #include @@ -47,23 +46,23 @@ #include "ring.h" #include "defines.h" #include "externs.h" -#include "fdset.h" #include "proto.h" +#include "netlink.h" -Ring netoring, netiring; -unsigned char netobuf[2*BUFSIZ], netibuf[BUFSIZ]; +struct ringbuf *netoring; +struct ringbuf *netiring; /* * Initialize internal network data structures. */ - void -init_network() -{ - if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) { +void init_network(void) { + netoring = ringbuf_create(2*BUFSIZ, netsink, NULL); + if (netoring==NULL) { exit(1); } - if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) { + netiring = ringbuf_create(BUFSIZ, NULL, netsrc); + if (netiring==NULL) { exit(1); } NetTrace = stdout; @@ -71,50 +70,6 @@ /* - * Check to see if any out-of-band data exists on a socket (for - * Telnet "synch" processing). - */ - -int -stilloob(void) -{ - static struct timeval timeout = { 0 }; - fd_set excepts; - int value; - - do { - FD_ZERO(&excepts); - FD_SET(net, &excepts); - value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); - } while ((value == -1) && (errno == EINTR)); - - if (value < 0) { - perror("select"); - (void) quit(); - /* NOTREACHED */ - } - if (FD_ISSET(net, &excepts)) { - return 1; - } else { - return 0; - } -} - - -/* - * setneturg() - * - * Sets "neturg" to the current location. - */ - - void -setneturg() -{ - ring_mark(&netoring); -} - - -/* * netflush * Send as much data as possible to the network, * handling requests for urgent data. @@ -124,55 +79,15 @@ */ -int -netflush(void) -{ - register int n, n1; - -#if defined(ENCRYPT) - if (encrypt_output) - ring_encrypt(&netoring, encrypt_output); -#endif - if ((n1 = n = ring_full_consecutive(&netoring)) > 0) { - if (!ring_at_mark(&netoring)) { - n = send(net, netoring.consume, n, 0); /* normal write */ - } else { - /* - * In 4.2 (and 4.3) systems, there is some question about - * what byte in a sendOOB operation is the "OOB" data. - * To make ourselves compatible, we only send ONE byte - * out of band, the one WE THINK should be OOB (though - * we really have more the TCP philosophy of urgent data - * rather than the Unix philosophy of OOB data). - */ - n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */ - } - } - if (n < 0) { - if (errno != ENOBUFS && errno != EWOULDBLOCK) { +int netflush(void) { + int r = ringbuf_flush(netoring); + if (r < -1) { setcommandmode(); perror(hostname); - (void)NetClose(net); - ring_clear_mark(&netoring); - longjmp(peerdied, -1); + nlink_close(0); + ringbuf_clear_mark(netoring); + siglongjmp(peerdied, -1); /*NOTREACHED*/ } - n = 0; - } - if (netdata && n) { - Dump('>', netoring.consume, n); - } - if (n) { - ring_consumed(&netoring, n); - /* - * If we sent all, and more to send, then recurse to pick - * up the other half. - */ - if ((n1 == n) && ring_full_consecutive(&netoring)) { - (void) netflush(); - } - return 1; - } else { - return 0; - } + return r>0; } Index: proto.h =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/proto.h,v retrieving revision 1.1 retrieving revision 1.11 diff -w -u -r1.1 -r1.11 --- proto.h 16 Jul 1996 07:57:11 -0000 1.1 +++ proto.h 11 Aug 2002 23:23:32 -0000 1.11 @@ -5,37 +5,36 @@ void Exit(int); void ExitString(const char *, int); -int NetClose(int fd); -int SetSockOpt(int, int, int, int); int TerminalAutoFlush(void); void TerminalDefaultChars(void); int TerminalSpecialChars(int); void TerminalSpeeds(long *ispeed, long *ospeed); int TerminalWindowSize(long *rows, long *cols); -int TerminalWrite(const char *buf, int n); void auth_encrypt_user(char *); void auth_name(unsigned char *, int); void auth_printsub(unsigned char *, int, unsigned char *, int); -void cmdrc(char *m1, char *m2); -void env_init(void); +void cmdrc(const char *m1, const char *m2); int getconnmode(void); void init_network(void); void init_sys(void); void init_telnet(void); void init_terminal(void); -int is_unique(char *name, char **as, char **ae); int netflush(void); void optionstatus(void); int process_rings(int, int, int, int, int, int); void quit(void); -int ring_at_mark(Ring *ring); int rlogin_susp(void); -int send_tncmd(int (*func)(int, int), char *cmd, char *name); +int send_tncmd(void (*func)(int, int), const char *cmd, const char *name); void sendeof(void); void sendsusp(void); void set_escape_char(char *); -int stilloob(void); void tel_leave_binary(int); int telrcv(void); -int tn(int argc, char *argv[]); +int tn(int argc, const char *argv[]); int ttyflush(int); +void sendayt(void); +void ayt_status(int); +void ayt(int sig); + +/* commands.c */ +void cmdtab_init(void); Index: ring.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/ring.c,v retrieving revision 1.2 retrieving revision 1.30 diff -w -u -r1.2 -r1.30 --- ring.c 16 Jul 1996 07:57:25 -0000 1.2 +++ ring.c 11 Aug 2002 21:10:10 -0000 1.30 @@ -35,329 +35,315 @@ * From: @(#)ring.c 5.2 (Berkeley) 3/1/91 */ char ring_rcsid[] = - "$Id: ring.c,v 1.2 1996/07/16 07:57:25 dholland Exp $"; + "$Id: ring.c,v 1.30 2002/08/11 21:10:10 dholland Exp $"; /* * This defines a structure for a ring buffer. - * - * The circular buffer has two parts: - *((( - * full: [consume, supply) - * empty: [supply, consume) - *]]] - * */ -#include #include -#include -#include - -#ifdef size_t -#undef size_t -#endif - -#include -#ifndef FILIO_H -#include -#endif -#include - +#include +#include +#include #include "ring.h" -#include "general.h" -#include "proto.h" -/* Internal macros */ +//////////////////////////////////////////////////////////// +// +// ringbuf -#if !defined(MIN) -#define MIN(a,b) (((a)<(b))? (a):(b)) -#endif /* !defined(MIN) */ +struct ringbuf { + const struct datasink_c *binding; + const struct datasource_c *srcbinding; -#define ring_subtract(d,a,b) (((a)-(b) >= 0)? \ - (a)-(b): (((a)-(b))+(d)->size)) + char *buf; + int size; /* total size of buffer */ + int head; /* next input character goes here */ + int tail; /* next output character comes from here */ + int count; /* chars presently stored in buffer */ + // The buffer is empty when head==tail. -#define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ - (a)+(c) : (((a)+(c))-(d)->size)) + int marked; /* this character is marked */ +}; -#define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \ - (a)-(c) : (((a)-(c))-(d)->size)) +//////////////////////////////////////////////////////////// +/* null data destination: throw away data passed in */ +static int null_write(const char *buf, int n) { + (void) buf; + return n; +} -/* - * The following is a clock, used to determine full, empty, etc. - * - * There is some trickiness here. Since the ring buffers are initialized - * to ZERO on allocation, we need to make sure, when interpreting the - * clock, that when the times are EQUAL, then the buffer is FULL. - */ -static u_long ring_clock = 0; +static const struct datasink_c nullsink_obj = { + null_write, /* write */ + null_write, /* writeurg */ +}; +const struct datasink_c *const nullsink = &nullsink_obj; -#define ring_empty(d) (((d)->consume == (d)->supply) && \ - ((d)->consumetime >= (d)->supplytime)) -#define ring_full(d) (((d)->supply == (d)->consume) && \ - ((d)->supplytime > (d)->consumetime)) +//////////////////////////////////////////////////////////// +#if 0 + int gets(char *buf, int max); + int getch(int *ch); + void ungetch(int ch); + int full_count(); + // automatic consume + int flush(); + /////// supply end + // manual supply + void putch(char c) { write(&c, 1); } + void write(const char *buffer, int ct); + void printf(const char *format, ...); + int empty_count() { return size - count; } -/* Buffer state transition routines */ -int -ring_init(Ring *ring, unsigned char *buffer, int count) -{ - memset(ring, 0, sizeof *ring); + // automatic supply + int read_source(); - ring->size = count; + /////// others + void clear_mark() { marked = -1; } + void set_mark() { marked = head; } - ring->supply = ring->consume = ring->bottom = buffer; + int init(int size, const datasink_c *sink, const datasource_c *src); - ring->top = ring->bottom+ring->size; + const datasink_c *setsink(const datasink_c *nu) { + const datasink_c *old = binding; + binding = nu; + return old; + } -#if defined(ENCRYPT) - ring->clearto = 0; #endif - return 1; -} -/* Mark routines */ -/* - * Mark the most recently supplied byte. - */ +/////////////////////////////////////////////////// consume ////////////// - void -ring_mark(ring) - Ring *ring; -{ - ring->mark = ring_decrement(ring, ring->supply, 1); +int ringbuf_gets(struct ringbuf *b, char *rbuf, int max) { + int i=0, ch; + assert(max>0); + while (ringbuf_getch(b, &ch)>0 && imark == ring->consume) { - return 1; - } else { - return 0; +int ringbuf_getch(struct ringbuf *b, int *ch) { + int rv = 0; + if (b->count > 0) { + if (b->tail==b->marked) { + rv = 2; + b->marked = -1; } + else rv = 1; + *ch = (unsigned char) b->buf[b->tail++]; + if (b->tail>=b->size) b->tail -= b->size; + b->count--; + } + return rv; /* 0 = no more chars available */ } -/* - * Clear any mark set on the ring. - */ +void ringbuf_ungetch(struct ringbuf *b, int ch) { + int x, och; - void -ring_clear_mark(ring) - Ring *ring; -{ - ring->mark = 0; + x = b->tail; + x--; + if (x<0) x += b->size; + och = b->buf[x]; /* avoid sign-extension and other such problems */ + if ((och&0xff) == (ch&0xff)) { + b->tail = x; + b->count++; + } + else { + //assert(!"Bad ungetch"); + b->tail = x; + b->count++; + } } -/* - * Add characters from current segment to ring buffer. - */ - void -ring_supplied(ring, count) - Ring *ring; - int count; -{ - ring->supply = ring_increment(ring, ring->supply, count); - ring->supplytime = ++ring_clock; +int ringbuf_full_count(struct ringbuf *rb) { + return rb->count; } /* - * We have just consumed "c" bytes. + * Return value: + * -2: Significant error occurred. + * -1: No useful work done, data waiting to go out. + * 0: No data was waiting, so nothing was done. + * 1: All waiting data was written out. + * n: Some data written, n-1 bytes left. */ - void -ring_consumed(ring, count) - Ring *ring; - int count; -{ - if (count == 0) /* don't update anything */ - return; - - if (ring->mark && - (ring_subtract(ring, ring->mark, ring->consume) < count)) { - ring->mark = 0; - } -#if defined(ENCRYPT) - if (ring->consume < ring->clearto && - ring->clearto <= ring->consume + count) - ring->clearto = 0; - else if (ring->consume + count > ring->top && - ring->bottom <= ring->clearto && - ring->bottom + ((ring->consume + count) - ring->top)) - ring->clearto = 0; -#endif - ring->consume = ring_increment(ring, ring->consume, count); - ring->consumetime = ++ring_clock; +int ringbuf_flush(struct ringbuf *b) { + static int busy=0; + + assert(b->binding); + assert(b->count>=0); + if (b->count==0) return 0; + + if (busy) { + return -1; + } + busy=1; + /* - * Try to encourage "ring_empty_consecutive()" to be large. + * should always be true + * assert(((b->size+b->head-b->tail)%b->size)==b->count); + * + * Nope! The above fails if the buffer is full; then: + * head == tail (so LHS is 0), but count == size. + * The following formula should be better. --okir */ - if (ring_empty(ring)) { - ring->consume = ring->supply = ring->bottom; - } -} + assert(((b->head - b->tail - b->count) % b->size) == 0); + while (b->count > 0) { + int n, bot, top; + bot = b->tail; + top = b->head; + if (top < bot) top = b->size; + if (b->marked > bot) top = b->marked; + assert(top-bot > 0 && top-bot <= b->count); -/* Buffer state query routines */ + if (b->marked==bot) { + n = b->binding->writeurg(b->buf+bot, top-bot); + } + else { + n = b->binding->write(b->buf+bot, top-bot); + } + if (n < 0) { + busy=0; + return -2; + } + else if (n==0) { + busy=0; + return -1; + } + if (b->marked==bot) b->marked = -1; + b->tail += n; + if (b->tail >= b->size) b->tail -= b->size; + b->count -= n; + assert(((b->size+b->head-b->tail)%b->size)==b->count); -/* Number of bytes that may be supplied */ - int -ring_empty_count(ring) - Ring *ring; -{ - if (ring_empty(ring)) { /* if empty */ - return ring->size; - } else { - return ring_subtract(ring, ring->consume, ring->supply); + if (n > 0 && n < top-bot) { busy=0; return n+1; } + /* otherwise (if we wrote all data) loop */ } + assert(((b->size+b->head-b->tail)%b->size)==b->count); + busy=0; + return 1; } -/* number of CONSECUTIVE bytes that may be supplied */ - int -ring_empty_consecutive(ring) - Ring *ring; -{ - if ((ring->consume < ring->supply) || ring_empty(ring)) { - /* - * if consume is "below" supply, or empty, then - * return distance to the top - */ - return ring_subtract(ring, ring->top, ring->supply); - } else { - /* - * else, return what we may. - */ - return ring_subtract(ring, ring->consume, ring->supply); - } + +/////////////////////////////////////////////////// supply ////////////// + +void ringbuf_printf(struct ringbuf *b, const char *format, ...) { + char xbuf[256]; + int l; + va_list ap; + + va_start(ap, format); + l = vsnprintf(xbuf, sizeof(xbuf), format, ap); + va_end(ap); + + /* note that because xbuf may include nulls we CANNOT use strlen(xbuf) */ + ringbuf_write(b, xbuf, l); } -/* Return the number of bytes that are available for consuming - * (but don't give more than enough to get to cross over set mark) - */ +void ringbuf_write(struct ringbuf *b, const char *buffer, int ct) { + int i; - int -ring_full_count(ring) - Ring *ring; -{ - if ((ring->mark == 0) || (ring->mark == ring->consume)) { - if (ring_full(ring)) { - return ring->size; /* nothing consumed, but full */ - } else { - return ring_subtract(ring, ring->supply, ring->consume); + if (ct > b->size - b->count) { + // Oops. We're about to overflow our buffer. + // In practice this shouldn't ever actually happen. + // We could return a short count, but then we'd have to check + // and retry every call, which ranges somewhere between painful + // and impossible. + // Instead, we drop the data on the floor. This should only happen + // if (1) the tty hangs, (2) the network hangs while we're trying + // to send large volumes of data, or (3) massive internal logic errors. + fprintf(stderr, "\n\ntelnet: buffer overflow, losing data, sorry\n"); + ct = b->size - b->count; } - } else { - return ring_subtract(ring, ring->mark, ring->consume); + for (i=0; ibuf[b->head++] = buffer[i]; + if (b->head>=b->size) b->head -= b->size; + b->count++; } } -/* - * Return the number of CONSECUTIVE bytes available for consuming. - * However, don't return more than enough to cross over set mark. - */ - int -ring_full_consecutive(ring) - Ring *ring; -{ - if ((ring->mark == 0) || (ring->mark == ring->consume)) { - if ((ring->supply < ring->consume) || ring_full(ring)) { - return ring_subtract(ring, ring->top, ring->consume); - } else { - return ring_subtract(ring, ring->supply, ring->consume); - } - } else { - if (ring->mark < ring->consume) { - return ring_subtract(ring, ring->top, ring->consume); - } else { /* Else, distance to mark */ - return ring_subtract(ring, ring->mark, ring->consume); - } +void ringbuf_putch(struct ringbuf *b, char c) { + ringbuf_write(b, &c, 1); } + +int ringbuf_empty_count(struct ringbuf *b) { + return b->size - b->count; } -/* - * Move data into the "supply" portion of of the ring buffer. - */ - void -ring_supply_data(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; -{ - int i; +int ringbuf_read_source(struct ringbuf *b) { + int bot, top, l; + + bot = b->head; + top = b->tail-1; /* leave room for an ungetc */ + if (top<0) top += b->size; + if (top < bot) top = b->size; + + if (top==bot) return 0; - while (count) { - i = MIN(count, ring_empty_consecutive(ring)); - memcpy(ring->supply, buffer, i); - ring_supplied(ring, i); - count -= i; - buffer += i; + l = b->srcbinding->read(b->buf+bot, top-bot); + if (l>=0) { + b->head += l; + if (b->head>=b->size) b->head -= b->size; + b->count += l; } + if (l==0) l = -1; + return l; } -#ifdef notdef +/////////////////////////////////////////////////// others ////////////// -/* - * Move data from the "consume" portion of the ring buffer - */ - void -ring_consume_data(ring, buffer, count) - Ring *ring; - unsigned char *buffer; - int count; -{ - int i; +void ringbuf_clear_mark(struct ringbuf *b) { + b->marked = -1; +} - while (count) { - i = MIN(count, ring_full_consecutive(ring)); - memcpy(buffer, ring->consume, i); - ring_consumed(ring, i); - count -= i; - buffer += i; +void ringbuf_set_mark(struct ringbuf *b) { + b->marked = b->head; } + +struct ringbuf *ringbuf_create(int sz, const struct datasink_c *sink, + const struct datasource_c *src) { + struct ringbuf *b; + +#ifdef __cplusplus + b = new ringbuf; + b->buf = new char[sz]; +#else + b = malloc(sizeof(struct ringbuf)); + if (b==NULL) { + return NULL; + } + b->buf = malloc(sz); + if (b->buf==NULL) { + free(b); + return NULL; } #endif -#if defined(ENCRYPT) - void -ring_encrypt(ring, encryptor) - Ring *ring; - void (*encryptor)(); -{ - unsigned char *s, *c; - - if (ring_empty(ring) || ring->clearto == ring->supply) - return; - - if (!(c = ring->clearto)) - c = ring->consume; - - s = ring->supply; - - if (s <= c) { - (*encryptor)(c, ring->top - c); - (*encryptor)(ring->bottom, s - ring->bottom); - } else - (*encryptor)(c, s - c); - - ring->clearto = ring->supply; -} - - void -ring_clearto(ring) - Ring *ring; -{ - if (!ring_empty(ring)) - ring->clearto = ring->supply; - else - ring->clearto = 0; + b->size = sz; + b->head = b->tail = 0; + b->count = 0; + b->marked = -1; + + b->binding = sink; + b->srcbinding = src; + + return b; +} + +const struct datasink_c *ringbuf_setsink(struct ringbuf *b, + const struct datasink_c *nu) { + const struct datasink_c *old = b->binding; + b->binding = nu; + return old; } -#endif Index: ring.h =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/ring.h,v retrieving revision 1.1 retrieving revision 1.19 diff -w -u -r1.1 -r1.19 --- ring.h 16 Jul 1996 05:17:22 -0000 1.1 +++ ring.h 11 Aug 2002 19:44:44 -0000 1.19 @@ -31,76 +31,68 @@ * SUCH DAMAGE. * * from: @(#)ring.h 5.2 (Berkeley) 3/1/91 - * $Id: ring.h,v 1.1 1996/07/16 05:17:22 dholland Exp $ + * $Id: ring.h,v 1.19 2002/08/11 19:44:44 dholland Exp $ */ -#if defined(P) -# undef P -#endif - -#if defined(__STDC__) || defined(LINT_ARGS) -# define P(x) x -#else -# define P(x) () -#endif - -/* - * This defines a structure for a ring buffer. - * - * The circular buffer has two parts: - *((( - * full: [consume, supply) - * empty: [supply, consume) - *]]] - * - */ -typedef struct { - unsigned char *consume, /* where data comes out of */ - *supply, /* where data comes in to */ - *bottom, /* lowest address in buffer */ - *top, /* highest address+1 in buffer */ - *mark; /* marker (user defined) */ -#if defined(ENCRYPT) - unsigned char *clearto; /* Data to this point is clear text */ - unsigned char *encryyptedto; /* Data is encrypted to here */ -#endif - int size; /* size in bytes of buffer */ - u_long consumetime, /* help us keep straight full, empty, etc. */ - supplytime; -} Ring; - -/* Here are some functions and macros to deal with the ring buffer */ - -/* Initialization routine */ -extern int - ring_init P((Ring *ring, unsigned char *buffer, int count)); - -/* Data movement routines */ -extern void - ring_supply_data P((Ring *ring, unsigned char *buffer, int count)); -#ifdef notdef -extern void - ring_consume_data P((Ring *ring, unsigned char *buffer, int count)); -#endif - -/* Buffer state transition routines */ -extern void - ring_supplied P((Ring *ring, int count)), - ring_consumed P((Ring *ring, int count)); - -/* Buffer state query routines */ -extern int - ring_empty_count P((Ring *ring)), - ring_empty_consecutive P((Ring *ring)), - ring_full_count P((Ring *ring)), - ring_full_consecutive P((Ring *ring)); - -#if defined(ENCRYPT) -extern void - ring_encrypt P((Ring *ring, void (*func)())), - ring_clearto P((Ring *ring)); -#endif - -extern void - ring_clear_mark(), - ring_mark(); +struct datasink_c { + int (*write)(const char *buf, int len); + int (*writeurg)(const char *buf, int len); +}; + +struct datasource_c { + int (*read)(char *buf, int len); +}; + +/* Structure for a ring buffer. (Opaque) */ +struct ringbuf; + + +/////// consume end functions + +// manual consume +int ringbuf_gets(struct ringbuf *, char *buf, int max); +int ringbuf_getch(struct ringbuf *, int *ch); +void ringbuf_ungetch(struct ringbuf *, int ch); +int ringbuf_full_count(struct ringbuf *); + +// automatic consume +int ringbuf_flush(struct ringbuf *); + + +/////// supply end functions + +// manual supply +void ringbuf_putch(struct ringbuf *, char c); +void ringbuf_write(struct ringbuf *, const char *buffer, int ct); +void ringbuf_printf(struct ringbuf *, const char *format, ...); +int ringbuf_empty_count(struct ringbuf *); + +// automatic supply +int ringbuf_read_source(struct ringbuf *); + + +/////// other functions + +void ringbuf_clear_mark(struct ringbuf *); +void ringbuf_set_mark(struct ringbuf *); + +struct ringbuf *ringbuf_create(int size, const struct datasink_c *sink, + const struct datasource_c *src); + +// returns the old sink +const struct datasink_c *ringbuf_setsink(struct ringbuf *, + const struct datasink_c *); + + +/////// data + +extern const struct datasink_c *const netsink; +extern const struct datasink_c *const ttysink; +extern const struct datasink_c *const nullsink; + +extern const struct datasource_c *const netsrc; +extern const struct datasource_c *const ttysrc; + +#define NETADD(c) { ringbuf_putch(netoring, c); } +#define NET2ADD(c1,c2) { NETADD(c1); NETADD(c2); } + Index: sys_bsd.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/sys_bsd.c,v retrieving revision 1.3 retrieving revision 1.30 diff -w -u -r1.3 -r1.30 --- sys_bsd.c 16 Jul 1996 07:57:25 -0000 1.3 +++ sys_bsd.c 11 Aug 2002 23:51:12 -0000 1.30 @@ -35,92 +35,40 @@ * From: @(#)sys_bsd.c 5.2 (Berkeley) 3/1/91 */ char bsd_rcsid[] = - "$Id: sys_bsd.c,v 1.3 1996/07/16 07:57:25 dholland Exp $"; + "$Id: sys_bsd.c,v 1.30 2002/08/11 23:51:12 dholland Exp $"; /* * The following routines try to encapsulate what is system dependent * (at least between 4.x and dos) which is used in telnet.c. */ -#include #include #include #include #include -#include +#include +#include #include #include +#include #include -#include #include #include "ring.h" -#include "fdset.h" - #include "defines.h" #include "externs.h" #include "types.h" #include "proto.h" - -#if defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO)) -#define SIG_FUNC_RET void -#else -#define SIG_FUNC_RET int -#endif - -int - tout, /* Output file descriptor */ - tin, /* Input file descriptor */ - net; - -#ifndef USE_TERMIO -struct tchars otc = { 0 }, ntc = { 0 }; -struct ltchars oltc = { 0 }, nltc = { 0 }; -struct sgttyb ottyb = { 0 }, nttyb = { 0 }; -int olmode = 0; -# define cfgetispeed(ptr) (ptr)->sg_ispeed -# define cfgetospeed(ptr) (ptr)->sg_ospeed -# define old_tc ottyb - -#else /* USE_TERMIO */ -struct termios old_tc = { 0 }; -extern struct termios new_tc; - -# ifndef TCSANOW -# ifdef TCSETS -# define TCSANOW TCSETS -# define TCSADRAIN TCSETSW -# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) -# else -# ifdef TCSETA -# define TCSANOW TCSETA -# define TCSADRAIN TCSETAW -# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) -# else -# define TCSANOW TIOCSETA -# define TCSADRAIN TIOCSETAW -# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) -# endif -# endif -# define tcsetattr(f, a, t) ioctl(f, a, (char *)t) -# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) -# ifdef CIBAUD -# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) -# else -# define cfgetispeed(ptr) cfgetospeed(ptr) -# endif -# endif /* TCSANOW */ -#endif /* USE_TERMIO */ +#include "netlink.h" +#include "terminal.h" +#include "externs.h" static fd_set ibits, obits, xbits; - - void -init_sys() +void init_sys(void) { - tout = fileno(stdout); - tin = fileno(stdin); + tlink_init(); FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&xbits); @@ -129,31 +77,6 @@ } -int TerminalWrite(const char *buf, int n) { - return write(tout, buf, n); -} - -int TerminalRead(char *buf, int n) { - return read(tin, buf, n); -} - -/* - * - */ - -int -TerminalAutoFlush(void) -{ -#if defined(LNOFLSH) - int flush; - - ioctl(0, TIOCLGET, (char *)&flush); - return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ -#else /* LNOFLSH */ - return 1; -#endif /* LNOFLSH */ -} - #ifdef KLUDGELINEMODE extern int kludgelinemode; #endif @@ -169,13 +92,9 @@ * 1 Do add this character */ -void intp(), sendbrk(), sendabort(); - int TerminalSpecialChars(int c) { - void xmitAO(), xmitEL(), xmitEC(); - if (c == termIntChar) { intp(); return 0; @@ -212,66 +131,8 @@ } -/* - * Flush output to the terminal - */ - void -TerminalFlushOutput() -{ -#ifdef TIOCFLUSH - (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); -#else - (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); -#endif -} - - void -TerminalSaveState() -{ -#ifndef USE_TERMIO - ioctl(0, TIOCGETP, (char *)&ottyb); - ioctl(0, TIOCGETC, (char *)&otc); - ioctl(0, TIOCGLTC, (char *)&oltc); - ioctl(0, TIOCLGET, (char *)&olmode); - - ntc = otc; - nltc = oltc; - nttyb = ottyb; - -#else /* USE_TERMIO */ - tcgetattr(0, &old_tc); - - new_tc = old_tc; - -#ifndef VDISCARD - termFlushChar = CONTROL('O'); -#endif -#ifndef VWERASE - termWerasChar = CONTROL('W'); -#endif -#ifndef VREPRINT - termRprntChar = CONTROL('R'); -#endif -#ifndef VLNEXT - termLiteralNextChar = CONTROL('V'); -#endif -#ifndef VSTART - termStartChar = CONTROL('Q'); -#endif -#ifndef VSTOP - termStopChar = CONTROL('S'); -#endif -#ifndef VSTATUS - termAytChar = CONTROL('T'); -#endif -#endif /* USE_TERMIO */ -} - - cc_t * -tcval(func) - register int func; -{ +cc_t *tcval(int func) { switch(func) { case SLC_IP: return(&termIntChar); case SLC_ABORT: return(&termQuitChar); @@ -281,7 +142,6 @@ case SLC_XON: return(&termStartChar); case SLC_XOFF: return(&termStopChar); case SLC_FORW1: return(&termForw1Char); -#ifdef USE_TERMIO case SLC_FORW2: return(&termForw2Char); # ifdef VDISCARD case SLC_AO: return(&termFlushChar); @@ -301,536 +161,82 @@ # ifdef VSTATUS case SLC_AYT: return(&termAytChar); # endif -#endif case SLC_SYNCH: case SLC_BRK: case SLC_EOR: default: - return((cc_t *)0); + return NULL; } } - void -TerminalDefaultChars() -{ -#ifndef USE_TERMIO - ntc = otc; - nltc = oltc; - nttyb.sg_kill = ottyb.sg_kill; - nttyb.sg_erase = ottyb.sg_erase; -#else /* USE_TERMIO */ - memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); -# ifndef VDISCARD - termFlushChar = CONTROL('O'); -# endif -# ifndef VWERASE - termWerasChar = CONTROL('W'); -# endif -# ifndef VREPRINT - termRprntChar = CONTROL('R'); -# endif -# ifndef VLNEXT - termLiteralNextChar = CONTROL('V'); -# endif -# ifndef VSTART - termStartChar = CONTROL('Q'); -# endif -# ifndef VSTOP - termStopChar = CONTROL('S'); -# endif -# ifndef VSTATUS - termAytChar = CONTROL('T'); -# endif -#endif /* USE_TERMIO */ -} - -#ifdef notdef -void -TerminalRestoreState() -{ +#if defined(TN3270) +void NetSigIO(int fd, int onoff) { + ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ } -#endif - -/* - * TerminalNewMode - set up terminal to a specific mode. - * MODE_ECHO: do local terminal echo - * MODE_FLOW: do local flow control - * MODE_TRAPSIG: do local mapping to TELNET IAC sequences - * MODE_EDIT: do local line editing - * - * Command mode: - * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG - * local echo - * local editing - * local xon/xoff - * local signal mapping - * - * Linemode: - * local/no editing - * Both Linemode and Single Character mode: - * local/remote echo - * local/no xon/xoff - * local/no signal mapping - */ -SIG_FUNC_RET ayt_status(); - - void -TerminalNewMode(f) - register int f; -{ - static int prevmode = 0; -#ifndef USE_TERMIO - struct tchars tc; - struct ltchars ltc; - struct sgttyb sb; - int lmode; -#else /* USE_TERMIO */ - struct termios tmp_tc; -#endif /* USE_TERMIO */ - int onoff; - int old; - cc_t esc; +void NetSetPgrp(int fd) { + int myPid; - globalmode = f&~MODE_FORCE; - if (prevmode == f) - return; + myPid = getpid(); + fcntl(fd, F_SETOWN, myPid); +} +#endif /*defined(TN3270)*/ /* - * Write any outstanding data before switching modes - * ttyflush() returns 0 only when there is no more data - * left to write out, it returns -1 if it couldn't do - * anything at all, otherwise it returns 1 + the number - * of characters left to write. -#ifndef USE_TERMIO - * We would really like ask the kernel to wait for the output - * to drain, like we can do with the TCSADRAIN, but we don't have - * that option. The only ioctl that waits for the output to - * drain, TIOCSETP, also flushes the input queue, which is NOT - * what we want (TIOCSETP is like TCSADFLUSH). -#endif - */ - old = ttyflush(SYNCHing|flushout); - if (old < 0 || old > 1) { -#ifdef USE_TERMIO - tcgetattr(tin, &tmp_tc); -#endif /* USE_TERMIO */ - do { - /* - * Wait for data to drain, then flush again. + * Various signal handling routines. */ -#ifdef USE_TERMIO - tcsetattr(tin, TCSADRAIN, &tmp_tc); -#endif /* USE_TERMIO */ - old = ttyflush(SYNCHing|flushout); - } while (old < 0 || old > 1); - } - - old = prevmode; - prevmode = f&~MODE_FORCE; -#ifndef USE_TERMIO - sb = nttyb; - tc = ntc; - ltc = nltc; - lmode = olmode; -#else - tmp_tc = new_tc; -#endif - if (f&MODE_ECHO) { -#ifndef USE_TERMIO - sb.sg_flags |= ECHO; -#else - tmp_tc.c_lflag |= ECHO; - tmp_tc.c_oflag |= ONLCR; - if (crlf) - tmp_tc.c_iflag |= ICRNL; -#endif - } else { -#ifndef USE_TERMIO - sb.sg_flags &= ~ECHO; -#else - tmp_tc.c_lflag &= ~ECHO; - tmp_tc.c_oflag &= ~ONLCR; - if (crlf) - tmp_tc.c_iflag &= ~ICRNL; -#endif - } - - if ((f&MODE_FLOW) == 0) { -#ifndef USE_TERMIO - tc.t_startc = _POSIX_VDISABLE; - tc.t_stopc = _POSIX_VDISABLE; -#else - tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON); - } else { - tmp_tc.c_iflag |= IXANY|IXOFF|IXON; -#endif - } - - if ((f&MODE_TRAPSIG) == 0) { -#ifndef USE_TERMIO - tc.t_intrc = _POSIX_VDISABLE; - tc.t_quitc = _POSIX_VDISABLE; - tc.t_eofc = _POSIX_VDISABLE; - ltc.t_suspc = _POSIX_VDISABLE; - ltc.t_dsuspc = _POSIX_VDISABLE; -#else - tmp_tc.c_lflag &= ~ISIG; -#endif - localchars = 0; - } else { -#ifdef USE_TERMIO - tmp_tc.c_lflag |= ISIG; -#endif - localchars = 1; - } +static void deadpeer(int sig) { + static int dying=0; - if (f&MODE_EDIT) { -#ifndef USE_TERMIO - sb.sg_flags &= ~CBREAK; - sb.sg_flags |= CRMOD; -#else - tmp_tc.c_lflag |= ICANON; -#endif - } else { -#ifndef USE_TERMIO - sb.sg_flags |= CBREAK; - if (f&MODE_ECHO) - sb.sg_flags |= CRMOD; - else - sb.sg_flags &= ~CRMOD; -#else - tmp_tc.c_lflag &= ~ICANON; - tmp_tc.c_iflag &= ~ICRNL; - tmp_tc.c_cc[VMIN] = 1; - tmp_tc.c_cc[VTIME] = 0; -#endif - } + (void)sig; // unused - if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { -#ifndef USE_TERMIO - ltc.t_lnextc = _POSIX_VDISABLE; -#else -# ifdef VLNEXT - tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); -# endif -#endif - } - - if (f&MODE_SOFT_TAB) { -#ifndef USE_TERMIO - sb.sg_flags |= XTABS; -#else -# ifdef OXTABS - tmp_tc.c_oflag |= OXTABS; -# endif -# ifdef TABDLY - tmp_tc.c_oflag &= ~TABDLY; - tmp_tc.c_oflag |= TAB3; -# endif -#endif - } else { -#ifndef USE_TERMIO - sb.sg_flags &= ~XTABS; -#else -# ifdef OXTABS - tmp_tc.c_oflag &= ~OXTABS; -# endif -# ifdef TABDLY - tmp_tc.c_oflag &= ~TABDLY; -# endif -#endif - } - - if (f&MODE_LIT_ECHO) { -#ifndef USE_TERMIO - lmode &= ~LCTLECH; -#else -# ifdef ECHOCTL - tmp_tc.c_lflag &= ~ECHOCTL; -# endif -#endif - } else { -#ifndef USE_TERMIO - lmode |= LCTLECH; -#else -# ifdef ECHOCTL - tmp_tc.c_lflag |= ECHOCTL; -# endif -#endif - } - - if (f == -1) { - onoff = 0; - } else { -#ifndef USE_TERMIO - if (f & MODE_OUTBIN) - lmode |= LLITOUT; - else - lmode &= ~LLITOUT; - - if (f & MODE_INBIN) - lmode |= LPASS8; - else - lmode &= ~LPASS8; -#else - if (f & MODE_INBIN) - tmp_tc.c_iflag &= ~ISTRIP; - else - tmp_tc.c_iflag |= ISTRIP; - if (f & MODE_OUTBIN) { - tmp_tc.c_cflag &= ~(CSIZE|PARENB); - tmp_tc.c_cflag |= CS8; - tmp_tc.c_oflag &= ~OPOST; - } else { - tmp_tc.c_cflag &= ~(CSIZE|PARENB); - tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); - tmp_tc.c_oflag |= OPOST; - } -#endif - onoff = 1; - } - - if (f != -1) { -#ifdef SIGTSTP - static SIG_FUNC_RET susp(); -#endif /* SIGTSTP */ -#ifdef SIGINFO - static SIG_FUNC_RET ayt(); -#endif SIGINFO - -#ifdef SIGTSTP - (void) signal(SIGTSTP, susp); -#endif /* SIGTSTP */ -#ifdef SIGINFO - (void) signal(SIGINFO, ayt); -#endif SIGINFO -#if defined(USE_TERMIO) && defined(NOKERNINFO) - tmp_tc.c_lflag |= NOKERNINFO; -#endif - /* - * We don't want to process ^Y here. It's just another - * character that we'll pass on to the back end. It has - * to process it because it will be processed when the - * user attempts to read it, not when we send it. - */ -#ifndef USE_TERMIO - ltc.t_dsuspc = _POSIX_VDISABLE; -#else -# ifdef VDSUSP - tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); -# endif -#endif -#ifdef USE_TERMIO + if (dying==0) { /* - * If the VEOL character is already set, then use VEOL2, - * otherwise use VEOL. + * Only do this once. We only get here from the SIGPIPE handler; + * the catch is that SIGPIPE is not necessarily caused by the + * peer dying; it might be that our stdout or stderr is a pipe + * and has closed. In the latter case, we might receive more + * SIGPIPEs while trying to clean up, and jumping repeatedly + * back through the same jmp_buf is not only going to cause + * an infinite loop, but is also, I believe, undefined behavior. */ - esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; - if ((tmp_tc.c_cc[VEOL] != esc) -# ifdef VEOL2 - && (tmp_tc.c_cc[VEOL2] != esc) -# endif - ) { - if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) - tmp_tc.c_cc[VEOL] = esc; -# ifdef VEOL2 - else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) - tmp_tc.c_cc[VEOL2] = esc; -# endif - } -#else - if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) - tc.t_brkc = esc; -#endif - } else { -#ifdef SIGINFO - (void) signal(SIGINFO, ayt_status); -#endif SIGINFO -#ifdef SIGTSTP - (void) signal(SIGTSTP, SIG_DFL); -/* (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); */ -#endif /* SIGTSTP */ -#ifndef USE_TERMIO - ltc = oltc; - tc = otc; - sb = ottyb; - lmode = olmode; -#else - tmp_tc = old_tc; -#endif - } -#ifndef USE_TERMIO - ioctl(tin, TIOCLSET, (char *)&lmode); - ioctl(tin, TIOCSLTC, (char *)<c); - ioctl(tin, TIOCSETC, (char *)&tc); - ioctl(tin, TIOCSETN, (char *)&sb); -#else - if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) - tcsetattr(tin, TCSANOW, &tmp_tc); -#endif - -#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) - ioctl(tin, FIONBIO, (char *)&onoff); - ioctl(tout, FIONBIO, (char *)&onoff); -#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ -#if defined(TN3270) - if (noasynchtty == 0) { - ioctl(tin, FIOASYNC, (char *)&onoff); - } -#endif /* defined(TN3270) */ - -} - -#if defined(USE_TERMIO) && !defined(SYSV_TERMIO) && !defined(__linux__) - void -TerminalSpeeds(ispeed, ospeed) - long *ispeed; - long *ospeed; -{ - - *ispeed = cfgetispeed(&old_tc); - *ospeed = cfgetospeed(&old_tc); + dying = 1; + setcommandmode(); + siglongjmp(peerdied, -1); } -#else /* USE_TERMIO && !SYSV_TERMIO */ -#ifndef B19200 -# define B19200 B9600 -#endif - -#ifndef B38400 -# define B38400 B19200 -#endif - -#ifndef B57600 -# define B57600 B38400 -#endif - -#ifndef B115200 -# define B115200 B57600 -#endif - + else if (dying<10) { /* - * This code assumes that the values B0, B50, B75... - * are in ascending order. They do not have to be - * contiguous. + * Allow up to 10 (arbitrarily chosen value) SIGPIPEs while + * cleaning up before bailing completely. */ -struct termspeeds { - long speed; - long value; -} termspeeds[] = { - { 0, B0 }, { 50, B50 }, { 75, B75 }, - { 110, B110 }, { 134, B134 }, { 150, B150 }, - { 200, B200 }, { 300, B300 }, { 600, B600 }, - { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, - { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, - { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, - { -1, B115200 } -}; - -void -TerminalSpeeds(long *ispeed, long *ospeed) -{ - register struct termspeeds *tp; - register long in, out; - - out = cfgetospeed(&old_tc); - in = cfgetispeed(&old_tc); - if (in == 0) - in = out; - - tp = termspeeds; - while ((tp->speed != -1) && (tp->value < in)) - tp++; - *ispeed = tp->speed; - - tp = termspeeds; - while ((tp->speed != -1) && (tp->value < out)) - tp++; - *ospeed = tp->speed; + dying++; } -#endif /* USE_TERMIO && !SYSV_TERMIO */ - -int -TerminalWindowSize(long *rows, long *cols) -{ -#ifdef TIOCGWINSZ - struct winsize ws; - - if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { - *rows = ws.ws_row; - *cols = ws.ws_col; - return 1; - } -#endif /* TIOCGWINSZ */ - return 0; -} - -int NetClose(int fd) { - return close(fd); -} - - - void -NetNonblockingIO(fd, onoff) - int fd; - int onoff; -{ - ioctl(fd, FIONBIO, (char *)&onoff); + else if (dying<11) { + dying++; + exit(1); } - -#if defined(TN3270) - void -NetSigIO(fd, onoff) - int fd; - int onoff; -{ - ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ + else { + _exit(1); } - - void -NetSetPgrp(fd) - int fd; -{ - int myPid; - - myPid = getpid(); - fcntl(fd, F_SETOWN, myPid); } -#endif /*defined(TN3270)*/ - -/* - * Various signal handling routines. - */ - /* ARGSUSED */ - static SIG_FUNC_RET -deadpeer(sig) - int sig; -{ - setcommandmode(); - longjmp(peerdied, -1); -} +static void intr(int sig) { + (void)sig; // unused - /* ARGSUSED */ - static SIG_FUNC_RET -intr(sig) - int sig; -{ if (localchars) { intp(); - return; } + else { setcommandmode(); - longjmp(toplevel, -1); + siglongjmp(toplevel, -1); + } } - /* ARGSUSED */ - static SIG_FUNC_RET -intr2(sig) - int sig; -{ +static void intr2(int sig) { + (void)sig; // unused + if (localchars) { #ifdef KLUDGELINEMODE if (kludgelinemode) @@ -842,25 +248,10 @@ } } -#ifdef SIGTSTP - /* ARGSUSED */ - static SIG_FUNC_RET -susp(sig) - int sig; -{ - if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) - return; - if (localchars) - sendsusp(); -} -#endif - #ifdef SIGWINCH - /* ARGSUSED */ - static SIG_FUNC_RET -sendwin(sig) - int sig; -{ +static void sendwin(int sig) { + (void)sig; // unused + if (connected) { sendnaws(); } @@ -868,38 +259,30 @@ #endif #ifdef SIGINFO - /* ARGSUSED */ - static SIG_FUNC_RET -ayt(sig) - int sig; -{ +void ayt(int sig) { + (void)sig; + if (connected) sendayt(); else - ayt_status(); + ayt_status(0); } #endif - - void -sys_telnet_init() -{ - (void) signal(SIGINT, intr); - (void) signal(SIGQUIT, intr2); - (void) signal(SIGPIPE, deadpeer); +void sys_telnet_init(void) { + signal(SIGINT, intr); + signal(SIGQUIT, intr2); + signal(SIGPIPE, deadpeer); #ifdef SIGWINCH - (void) signal(SIGWINCH, sendwin); -#endif -#ifdef SIGTSTP - (void) signal(SIGTSTP, susp); + signal(SIGWINCH, sendwin); #endif #ifdef SIGINFO - (void) signal(SIGINFO, ayt); + signal(SIGINFO, ayt); #endif setconnmode(0); - NetNonblockingIO(net, 1); + nlink_nonblock(1); #if defined(TN3270) if (noasynchnet == 0) { /* DBX can't handle! */ @@ -908,11 +291,7 @@ } #endif /* defined(TN3270) */ -#if defined(SO_OOBINLINE) - if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { - perror("SetSockOpt"); - } -#endif /* defined(SO_OOBINLINE) */ + nlink_oobinline(); } /* @@ -926,18 +305,21 @@ * The return value is 1 if something happened, 0 if not. */ -int -process_rings(int netin, int netout, int netex, int ttyin, int ttyout, +int process_rings(int netin, int netout, int netex, int ttyin, int ttyout, int poll /* If 0, then block until something to do */) { - register int c; + register int c, maxfd; /* One wants to be a bit careful about setting returnValue * to one, since a one implies we did some useful work, * and therefore probably won't be called to block next * time (TN3270 mode only). */ int returnValue = 0; - static struct timeval TimeValue = { 0 }; + static struct timeval TimeValue = { 0, 0 }; + + int net = nlink_getfd(); + int tin = tlink_getifd(); + int tout = tlink_getofd(); if (netout) { FD_SET(net, &obits); @@ -945,28 +327,21 @@ if (ttyout) { FD_SET(tout, &obits); } -#if defined(TN3270) if (ttyin) { FD_SET(tin, &ibits); } -#else /* defined(TN3270) */ - if (ttyin) { - FD_SET(tin, &ibits); - } -#endif /* defined(TN3270) */ -#if defined(TN3270) - if (netin) { - FD_SET(net, &ibits); - } -# else /* !defined(TN3270) */ if (netin) { FD_SET(net, &ibits); } -# endif /* !defined(TN3270) */ if (netex) { FD_SET(net, &xbits); } - if ((c = select(16, &ibits, &obits, &xbits, + + maxfd = net; + if (maxfd < tin) maxfd=tin; + if (maxfd < tout) maxfd=tout; + + if ((c = select(maxfd+1, &ibits, &obits, &xbits, (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { if (c == -1) { /* @@ -993,7 +368,7 @@ FD_ZERO(&xbits); return 0; } -# endif /* defined(TN3270) */ +#endif /* TN3270 */ /* I don't like this, does it ever happen? */ printf("sleep(5) from telnet, after select\r\n"); sleep(5); @@ -1011,116 +386,37 @@ } /* - * Something to read from the network... + * Should flush output buffers first to make room for new input. --okir */ - if (FD_ISSET(net, &ibits)) { - int canread; - - FD_CLR(net, &ibits); - canread = ring_empty_consecutive(&netiring); -#if !defined(SO_OOBINLINE) - /* - * In 4.2 (and some early 4.3) systems, the - * OOB indication and data handling in the kernel - * is such that if two separate TCP Urgent requests - * come in, one byte of TCP data will be overlaid. - * This is fatal for Telnet, but we try to live - * with it. - * - * In addition, in 4.2 (and...), a special protocol - * is needed to pick up the TCP Urgent data in - * the correct sequence. - * - * What we do is: if we think we are in urgent - * mode, we look to see if we are "at the mark". - * If we are, we do an OOB receive. If we run - * this twice, we will do the OOB receive twice, - * but the second will fail, since the second - * time we were "at the mark", but there wasn't - * any data there (the kernel doesn't reset - * "at the mark" until we do a normal read). - * Once we've read the OOB data, we go ahead - * and do normal reads. - * - * There is also another problem, which is that - * since the OOB byte we read doesn't put us - * out of OOB state, and since that byte is most - * likely the TELNET DM (data mark), we would - * stay in the TELNET SYNCH (SYNCHing) state. - * So, clocks to the rescue. If we've "just" - * received a DM, then we test for the - * presence of OOB data when the receive OOB - * fails (and AFTER we did the normal mode read - * to clear "at the mark"). - */ - if (SYNCHing) { - int atmark; - static int bogus_oob = 0, first = 1; - - ioctl(net, SIOCATMARK, (char *)&atmark); - if (atmark) { - c = recv(net, netiring.supply, canread, MSG_OOB); - if ((c == -1) && (errno == EINVAL)) { - c = recv(net, netiring.supply, canread, 0); - if (clocks.didnetreceive < clocks.gotDM) { - SYNCHing = stilloob(net); + if (FD_ISSET(net, &obits)) { + FD_CLR(net, &obits); + returnValue |= netflush(); } - } else if (first && c > 0) { - /* - * Bogosity check. Systems based on 4.2BSD - * do not return an error if you do a second - * recv(MSG_OOB). So, we do one. If it - * succeeds and returns exactly the same - * data, then assume that we are running - * on a broken system and set the bogus_oob - * flag. (If the data was different, then - * we probably got some valid new data, so - * increment the count...) - */ - int i; - i = recv(net, netiring.supply + c, canread - c, MSG_OOB); - if (i == c && - bcmp(netiring.supply, netiring.supply + c, i) == 0) { - bogus_oob = 1; - first = 0; - } else if (i < 0) { - bogus_oob = 0; - first = 0; - } else - c += i; + if (FD_ISSET(tout, &obits)) { + FD_CLR(tout, &obits); + returnValue |= (ttyflush(SYNCHing|flushout) > 0); } - if (bogus_oob && c > 0) { - int i; + /* - * Bogosity. We have to do the read - * to clear the atmark to get out of - * an infinate loop. + * Something to read from the network... */ - i = read(net, netiring.supply + c, canread - c); - if (i > 0) - c += i; - } - } else { - c = recv(net, netiring.supply, canread, 0); - } - } else { - c = recv(net, netiring.supply, canread, 0); - } - settimer(didnetreceive); -#else /* !defined(SO_OOBINLINE) */ - c = recv(net, netiring.supply, canread, 0); -#endif /* !defined(SO_OOBINLINE) */ - if (c < 0 && errno == EWOULDBLOCK) { - c = 0; - } else if (c <= 0) { + if (FD_ISSET(net, &ibits)) { + /* hacks for systems without SO_OOBINLINE removed */ + + FD_CLR(net, &ibits); + /* Only call network input routine if there is room. Otherwise + * we will try a 0 byte read, which we happily interpret as the + * server having dropped the connection... + * NB the input routine reserves 1 byte for ungetc. + * 12.3.97 --okir */ + returnValue = 1; + if (ringbuf_empty_count(netiring) > 1) { + c = ringbuf_read_source(netiring); + if (c <= 0) return -1; + else if (c == 0) + returnValue = 0; } - if (netdata) { - Dump('<', netiring.supply, c); - } - if (c) - ring_supplied(&netiring, c); - returnValue = 1; } /* @@ -1128,34 +424,12 @@ */ if (FD_ISSET(tin, &ibits)) { FD_CLR(tin, &ibits); - c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); - if (c < 0 && errno == EWOULDBLOCK) { - c = 0; - } else { - /* EOF detection for line mode!!!! */ - if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { - /* must be an EOF... */ - *ttyiring.supply = termEofChar; - c = 1; - } - if (c <= 0) { + c = ringbuf_read_source(ttyiring); + if (c < 0) { return -1; } - if (termdata) { - Dump('<', ttyiring.supply, c); - } - ring_supplied(&ttyiring, c); - } - returnValue = 1; /* did something useful */ - } - - if (FD_ISSET(net, &obits)) { - FD_CLR(net, &obits); - returnValue |= netflush(); - } - if (FD_ISSET(tout, &obits)) { - FD_CLR(tout, &obits); - returnValue |= (ttyflush(SYNCHing|flushout) > 0); + else if (c==0) returnValue = 0; + else returnValue = 1; /* did something useful */ } return returnValue; Index: telnet.1 =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/telnet.1,v retrieving revision 1.1 retrieving revision 1.16 diff -w -u -r1.1 -r1.16 --- telnet.1 16 Jul 1996 05:17:22 -0000 1.1 +++ telnet.1 6 Nov 2001 00:55:11 -0000 1.16 @@ -30,65 +30,106 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)telnet.1 6.16 (Berkeley) 7/27/91 -.\" $Id: telnet.1,v 1.1 1996/07/16 05:17:22 dholland Exp $ +.\" $Id: telnet.1,v 1.16 2001/11/06 00:55:11 dholland Exp $ .\" -.Dd July 27, 1991 +.Dd August 15, 1999 .Dt TELNET 1 -.Os BSD 4.2 +.Os "Linux NetKit (0.18-pre1)" .Sh NAME .Nm telnet -.Nd User interface to the +.Nd user interface to the .Tn TELNET protocol .Sh SYNOPSIS .Nm telnet -.Op Fl d -.Op Fl a -.Op Fl n Ar tracefile +.Op Fl 8ELadr +.Op Fl S Ar tos .Op Fl e Ar escapechar -.Oo .Op Fl l Ar user +.Op Fl n Ar tracefile +.Oo .Ar host -.Op port +.Op Ar port .Oc .Sh DESCRIPTION The .Nm telnet command -is used to communicate with another host using the +is used for interactive communication with another host using the .Tn TELNET -protocol. -If +protocol. It begins in command mode, where it prints a telnet prompt +("telnet\&> "). If .Nm telnet -is invoked without the +is invoked with a .Ar host -argument, it enters command mode, -indicated by its prompt -.Pq Nm telnet\&> . -In this mode, it accepts and executes the commands listed below. -If it is invoked with arguments, it performs an +argument, it performs an .Ic open -command with those arguments. +command implicitly; see the description below. .Pp Options: .Bl -tag -width indent -.It Fl d -Sets the initial value of the -.Ic debug -toggle to -.Dv TRUE +.It Fl 8 +Request 8-bit operation. This causes an attempt to negotiate the +.Dv TELNET BINARY +option for both input and output. By default telnet is not 8-bit +clean. +.It Fl E +Disables the escape character functionality; that is, sets the escape +character to ``no character''. +.It Fl L +Specifies an 8-bit data path on output. This causes the +.Dv TELNET BINARY +option to be negotiated on just output. .It Fl a -Attempt automatic login. -Currently, this sends the user name via the +Attempt automatic login. Currently, this sends the user name via the .Ev USER variable of the .Ev ENVIRON -option if supported by the remote system. -The name used is that of the current user as returned by -.Xr getlogin 2 -if it agrees with the current user ID, -otherwise it is the name associated with the user ID. +option if supported by the remote system. The username is retrieved +via +.Xr getlogin 3 . +.It Fl d +Sets the initial value of the +.Ic debug +toggle to +.Dv TRUE. +.It Fl r +Emulate +.Xr rlogin 1 . +In this mode, the default escape character is a tilde. Also, the +interpretation of the escape character is changed: an escape character +followed by a dot causes +.Nm telnet +to disconnect from the remote host. A ^Z instead of a dot suspends +.Nm telnet , +and a ^] (the default +.Nm telnet +escape character) generates a normal telnet prompt. These codes are +accepted only at the beginning of a line. +.It Fl S Ar tos +Sets the IP type-of-service (TOS) option for the telnet +connection to the value +.Ar tos . +.It Fl e Ar escapechar +Sets the escape character to +.Ar escapechar. +If no character is supplied, no escape character will be used. +Entering the escape character while connected causes telnet to drop to +command mode. +.It Fl l Ar user +Specify +.Ar user +as the user to log in as on the remote system. This is accomplished by +sending the specified name as the +.Dv USER +environment variable, so it requires that the remote system support the +.Ev TELNET ENVIRON +option. This option implies the +.Fl a +option, and may also be used with the +.Ic open +command. .It Fl n Ar tracefile Opens .Ar tracefile @@ -96,39 +137,17 @@ See the .Ic set tracefile command below. -.It Fl l Ar user -When connecting to the remote system, if the remote system -understands the -.Ev ENVIRON -option, then -.Ar user -will be sent to the remote system as the value for the variable USER. -This option implies the -.Fl a -option. -This option may also be used with the -.Ic open -command. -.It Fl e Ar escape char -Sets the initial -.Nm -.Nm telnet -escape character to -.Ar escape char. -If -.Ar escape char -is ommitted, then -there will be no escape character. .It Ar host -Indicates the official name, an alias, or the Internet address -of a remote host. +Specifies a host to contact over the network. .It Ar port -Indicates a port number (address of an application). If a number is -not specified, the default +Specifies a port number or service name to contact. If not specified, +the .Nm telnet -port is used. +port (23) is used. .El .Pp +Protocol: +.Pp Once a connection has been opened, .Nm telnet will attempt to enable the @@ -206,47 +225,168 @@ and .Ic intr ) . .Pp -While connected to a remote host, -.Nm telnet -command mode may be entered by typing the -.Nm telnet -\*(Lqescape character\*(Rq (initially \*(Lq^]\*(Rq). -When in command mode, the normal terminal editing conventions are available. +Commands: .Pp The following .Nm telnet -commands are available. -Only enough of each command to uniquely identify it need be typed -(this is also true for arguments to the -.Ic mode , -.Ic set , -.Ic toggle , -.Ic unset , -.Ic slc , -.Ic environ , -and -.Ic display -commands). +commands are available. Unique prefixes are understood as abbreviations. .Pp .Bl -tag -width "mode type" +.It Ic auth Ar argument ... +The +.Ic auth +command controls the +.Dv TELNET AUTHENTICATE +protocol option. If +.Nm telnet +was compiled without authentication, the +.Ic auth +command will not be supported. +Valid arguments are as follows: +.Bl -tag -width "disable type" +.It Ic disable Ar type +Disable the specified type of authentication. To +obtain a list of available types, use the +.Ic auth disable \&? +command. +.It Ic enable Ar type +Enable the specified type of authentication. To +obtain a list of available types, use the +.Ic auth enable \&? +command. +.It Ic status +List the current status of the various types of +authentication. +.El +.Pp +Note that the current version of +.Nm telnet +does not support authentication. .It Ic close -Close a -.Tn TELNET -session and return to command mode. +Close the connection to the remote host, if any, and return to command +mode. .It Ic display Ar argument ... -Displays all, or some, of the +Display all, or some, of the .Ic set and .Ic toggle values (see below). +.It Ic encrypt Ar argument ... +The encrypt command controls the +.Dv TELNET ENCRYPT +protocol option. If +.Nm telnet +was compiled without encryption, the +.Ic encrypt +command will not be supported. +.Pp +Valid arguments are as follows: +.Bl -tag -width Ar +.It Ic disable Ar type Ic [input|output] +Disable the specified type of encryption. If you do not specify input +or output, encryption of both is disabled. To obtain a list of +available types, use ``encrypt disable \&?''. +.It Ic enable Ar type Ic [input|output] +Enable the specified type of encryption. If you do not specify input +or output, encryption of both is enabled. To obtain a list of +available types, use ``encrypt enable \&?''. +.It Ic input +This is the same as ``encrypt start input''. +.It Ic -input +This is the same as ``encrypt stop input''. +.It Ic output +This is the same as ``encrypt start output''. +.It Ic -output +This is the same as ``encrypt stop output''. +.It Ic start Ic [input|output] +Attempt to begin encrypting. If you do not specify input or output, +encryption of both input and output is started. +.It Ic status +Display the current status of the encryption module. +.It Ic stop Ic [input|output] +Stop encrypting. If you do not specify input or output, encryption of +both is stopped. +.It Ic type Ar type +Sets the default type of encryption to be used with later ``encrypt start'' +or ``encrypt stop'' commands. +.El +.Pp +Note that the current version of +.Nm telnet +does not support encryption. +.It Ic environ Ar arguments... +The +.Ic environ +command is used to propagate environment variables across the +.Nm telnet +link using the +.Dv TELNET ENVIRON +protocol option. +All variables exported from the shell are defined, but only the +.Ev DISPLAY +and +.Ev PRINTER +variables are marked to be sent by default. The +.Ev USER +variable is marked to be sent if the +.Fl a +or +.Fl l +command-line options were used. +.Pp +Valid arguments for the +.Ic environ +command are: +.Bl -tag -width Fl +.It Ic define Ar variable value +Define the variable +.Ar variable +to have a value of +.Ar value. +Any variables defined by this command are automatically marked for +propagation (``exported''). +The +.Ar value +may be enclosed in single or double quotes so +that tabs and spaces may be included. +.It Ic undefine Ar variable +Remove any existing definition of +.Ar variable . +.It Ic export Ar variable +Mark the specified variable for propagation to the remote host. +.It Ic unexport Ar variable +Do not mark the specified variable for propagation to the remote +host. The remote host may still ask explicitly for variables that are +not exported. +.It Ic list +List the current set of environment variables. +Those marked with a +.Cm * +will be propagated to the remote host. The remote host may still ask +explicitly for the rest. +.It Ic \&? +Prints out help information for the +.Ic environ +command. +.El +.It Ic logout +Send the +.Dv TELNET LOGOUT +protocol option to the remote host. +This command is similar to a +.Ic close +command. If the remote host does not support the +.Dv LOGOUT +option, nothing happens. But if it does, this command should cause it +to close the connection. If the remote side also supports the concept +of suspending a user's session for later reattachment, the logout +command indicates that the session should be terminated immediately. .It Ic mode Ar type .Ar Type -is one of several options, depending on the state of the -.Tn TELNET -session. -The remote host is asked for permission to go into the requested mode. -If the remote host is capable of entering that mode, the requested -mode will be entered. +is one of several options, depending on the state of the session. +.Tn Telnet +asks the remote host to go into the requested mode. If the remote host +says it can, that mode takes effect. .Bl -tag -width Ar .It Ic character Disable the @@ -308,61 +448,61 @@ .Oc Ns Oo Fl .Ar port Oc .Xc -Open a connection to the named host. -If no port number -is specified, +Open a connection to the named host. If no port number is specified, .Nm telnet will attempt to contact a -.Tn TELNET -server at the default port. -The host specification may be either a host name (see -.Xr hosts 5 ) -or an Internet address specified in the \*(Lqdot notation\*(Rq (see -.Xr inet 3 ) . +.Tn telnet +daemon at the standard port (23). +The host specification may be a host name or IP address. The -.Op Fl l -option may be used to specify the user name -to be passed to the remote system via the -.Ev ENVIRON -option. -When connecting to a non-standard port, -.Nm telnet -omits any automatic initiation of -.Tn TELNET -options. When the port number is preceeded by a minus sign, -the inital option negotiation is done. -After establishing a connection, the file -.Pa \&.telnetrc -in the -users home directory is opened. Lines begining with a # are -comment lines. Blank lines are ignored. Lines that begin -without whitespace are the start of a machine entry. The -first thing on the line is the name of the machine that is -being connected to. The rest of the line, and successive -lines that begin with whitespace are assumed to be +.Fl l +option may be used to specify a user name to be passed to the remote +system, like the +.Fl l +command-line option. +.Pp +When connecting to ports other than the .Nm telnet -commands and are processed as if they had been typed -in manually to the +port, .Nm telnet -command prompt. +does not attempt +.Tn telnet +protocol negotiations. This makes it possible to connect to services +that do not support the +.Tn telnet +protocol without making a mess. Protocol negotiation can be forced by +placing a dash before the port number. +.Pp +After establishing a connection, any commands associated with the +remote host in the user's +.Pa .telnetrc +file are executed. +.Pp +The format of the .telnetrc file is as follows: Lines beginning with a +#, and blank lines, are ignored. The rest of the file should consist +of hostnames and sequences of +.Nm telnet +commands to use with that host. Commands should be one per line, +indented by whitespace; lines beginning without whitespace are +interpreted as hostnames. Upon connecting to a particular host, the +commands associated with that host are executed. .It Ic quit -Close any open -.Tn TELNET -session and exit +Close any open session and exit .Nm telnet . -An end of file (in command mode) will also close a session and exit. +An end of file condition on input, when in command mode, will trigger +this operation as well. .It Ic send Ar arguments -Sends one or more special character sequences to the remote host. -The following are the arguments which may be specified -(more than one argument may be specified at a time): +Send one or more special +.Tn telnet +protocol character sequences to the remote host. The following are +the codes which may be specified (more than one may be used in one +command): .Pp .Bl -tag -width escape .It Ic abort Sends the .Dv TELNET ABORT -(Abort -processes) -sequence. +(Abort Processes) sequence. .It Ic ao Sends the .Dv TELNET AO @@ -375,8 +515,8 @@ .It Ic ayt Sends the .Dv TELNET AYT -(Are You There) -sequence, to which the remote system may or may not choose to respond. +(Are You There?) sequence, to which the remote system may or may not +choose to respond. .It Ic brk Sends the .Dv TELNET BRK @@ -407,7 +547,7 @@ .It Ic escape Sends the current .Nm telnet -escape character (initially \*(Lq^\*(Rq). +escape character. .It Ic ga Sends the .Dv TELNET GA @@ -428,12 +568,12 @@ .It Ic nop Sends the .Dv TELNET NOP -(No OPeration) +(No Operation) sequence. .It Ic susp Sends the .Dv TELNET SUSP -(SUSPend process) +(Suspend Process) sequence. .It Ic synch Sends the @@ -448,6 +588,26 @@ .Bx 4.2 system -- if it doesn't work, a lower case \*(Lqr\*(Rq may be echoed on the terminal). +.It Ic do Ar cmd +.It Ic dont Ar cmd +.It Ic will Ar cmd +.It Ic wont Ar cmd +Sends the +.Dv TELNET DO +.Ar cmd +sequence. +.Ar cmd +can be either a decimal number between 0 and 255, +or a symbolic name for a specific +.Dv TELNET +command. +.Ar cmd +can also be either +.Ic help +or +.Ic \&? +to print out help information, including +a list of known symbolic names. .It Ic \&? Prints out help information for the .Ic send @@ -464,27 +624,31 @@ The special value .Ic off turns off the function associated with -the variable, this is equivalent to using the +the variable. This is equivalent to using the .Ic unset command. The .Ic unset command will disable or set to .Dv FALSE -any of the specified functions. +any of the specified variables. The values of variables may be interrogated with the .Ic display command. The variables which may be set or unset, but not toggled, are listed here. In addition, any of the variables for the .Ic toggle -command may be explicitly set or unset using -the -.Ic set -and -.Ic unset -commands. +command may be explicitly set or unset. .Bl -tag -width escape +.It Ic ayt +If +.Tn telnet +is in localchars mode, or +.Dv LINEMODE +is enabled, and the status character is typed, a +.Dv TELNET AYT +sequence is sent to the remote host. The initial value for the "Are +You There" character is the terminal's status character. .It Ic echo This is the value (initially \*(Lq^E\*(Rq) which, when in \*(Lqline by line\*(Rq mode, toggles between doing local echoing @@ -554,6 +718,17 @@ the terminal's .Ic flush character. +.It Ic forw1 +.It Ic forw2 +If +.Tn TELNET +is operating in +.Dv LINEMODE , +these are the +characters that, when typed, cause partial lines to be +forwarded to the remote system. The initial value for +the forwarding characters are taken from the terminal's +eol and eol2 characters. .It Ic interrupt If .Nm telnet @@ -648,6 +823,11 @@ the terminal's .Ic reprint character. +.It Ic rlogin +This is the rlogin mode escape character. Setting it enables rlogin +mode, as with the +.Ar r +command-line option (q.v.) .It Ic start If the .Dv TELNET TOGGLE-FLOW-CONTROL @@ -693,7 +873,7 @@ .Ic suspend character. .It Ic tracefile -Thi is the file to which the output, caused by +This is the file to which the output, caused by .Ic netdata or .Ic option @@ -742,6 +922,11 @@ .Ic kill ) . By default, the local special characters are exported. .Bl -tag -width Fl +.It Ic check +Verify the current settings for the current special characters. +The remote side is requested to send all the current special +character settings, and if there are any discrepancies with +the local side, the local side will switch to the remote value. .It Ic export Switch to the local defaults for the special characters. The local default characters are those of the local terminal at @@ -754,75 +939,16 @@ at the time when the .Tn TELNET connection was established. -.It Ic check -Verify the current settings for the current special characters. -The remote side is requested to send all the current special -character settings, and if there are any discrepencies with -the local side, the local side will switch to the remote value. .It Ic \&? Prints out help information for the .Ic slc command. .El -.It Ic environ Ar arguments... -The -.Ic environ -command is used to manipulate the -the variables that my be sent through the -.Dv TELNET ENVIRON -option. -The initial set of variables is taken from the users -environment, with only the -.Ev DISPLAY -and -.Ev PRINTER -variables being exported by default. -The -.Ev USER -variable is also exported if the -.Fl a -or -.Fl l -options are used. -.br -Valid arguments for the -.Ic environ -command are: -.Bl -tag -width Fl -.It Ic define Ar variable value -Define the variable -.Ar variable -to have a value of -.Ar value. -Any variables defined by this command are automatically exported. -The -.Ar value -may be enclosed in single or double quotes so -that tabs and spaces may be included. -.It Ic undefine Ar variable -Remove -.Ar variable -from the list of environment variables. -.It Ic export Ar variable -Mark the variable -.Ar variable -to be exported to the remote side. -.It Ic unexport Ar variable -Mark the variable -.Ar variable -to not be exported unless -explicitly asked for by the remote side. -.It Ic list -List the current set of environment variables. -Those marked with a -.Cm * -will be sent automatically, -other variables will only be sent if explicitly requested. -.It Ic \&? -Prints out help information for the -.Ic environ -command. -.El +.It Ic status +Show the current status of +.Nm telnet . +This includes the name of the remote host, if any, as well as the +current mode. .It Ic toggle Ar arguments ... Toggle (between .Dv TRUE @@ -839,13 +965,16 @@ .Ic set and .Ic unset -commands listed above. -More than one argument may be specified. -The state of these flags may be interrogated with the +commands. +More than one flag may be toggled at once. +The state of these flags may be examined with the .Ic display command. -Valid arguments are: +Valid flags are: .Bl -tag -width Ar +.It Ic authdebug +Turns on debugging for the authentication code. This flag only exists +if authentication support is enabled. .It Ic autoflush If .Ic autoflush @@ -877,6 +1006,32 @@ .Dv FALSE (see .Xr stty 1 ) . +.It Ic autodecrypt +When the +.Dv TELNET ENCRYPT +option is negotiated, by +default the actual encryption (decryption) of the data +stream does not start automatically. The autoencrypt +(autodecrypt) command states that encryption of the +output (input) stream should be enabled as soon as +possible. +.Pp +Note that this flag exists only if encryption support is enabled. +.It Ic autologin +If the remote side supports the +.Dv TELNET AUTHENTICATION +option, +.Tn telnet +attempts to use it to perform automatic authentication. If the +.Dv TELNET AUTHENTICATION +option is not supported, the user's login name is propagated using the +.Dv TELNET ENVIRON +option. +Setting this flag is the same as specifying the +.Ar a +option to the +.Ic open +command or on the command line. .It Ic autosynch If .Ic autosynch @@ -895,7 +1050,7 @@ and .Ic quit characters), the resulting -.Tn TELNET +.Tn telnet sequence sent is followed by the .Dv TELNET SYNCH sequence. @@ -903,7 +1058,7 @@ .Ic should cause the remote system to begin throwing away all previously typed input until both of the -.Tn TELNET +.Tn telnet sequences have been read and acted upon. The initial value of this toggle is .Dv FALSE . @@ -946,6 +1101,9 @@ .Ic super user ) . The initial value for this toggle is .Dv FALSE . +.It Ic encdebug +Turns on debugging information for the encryption code. +Note that this flag only exists if encryption support is available. .It Ic localchars If this is .Dv TRUE , @@ -1006,7 +1164,7 @@ Toggles the display of some internal .Nm telnet protocol processing (having to do with -.Tn TELNET +.Tn telnet options). The initial value for this toggle is .Dv FALSE . @@ -1017,11 +1175,33 @@ .Ic prettydump is enabled the output from the .Ic netdata -command will be formated in a more user readable format. +command will be formatted in a more user-readable format. Spaces are put between each character in the output, and the -begining of any +beginning of +.Tn telnet +escape sequences are preceded by a '*' to aid in locating them. +.It Ic skiprc +When the skiprc toggle is +.Dv TRUE , +.Tn telnet +does not read the +.Pa \&.telnetrc +file. The initial value for this toggle is +.Dv FALSE. +.It Ic termdata +Toggles the display of all terminal data (in hexadecimal format). +The initial value for this toggle is +.Dv FALSE . +.It Ic verbose_encrypt +When the +.Ic verbose_encrypt +toggle is +.Dv TRUE , .Tn TELNET -escape sequence is preceeded by a '*' to aid in locating them. +prints out a message each time encryption is enabled or +disabled. The initial value for this toggle is +.Dv FALSE. +This flag only exists if encryption support is available. .It Ic \&? Displays the legal .Ic toggle @@ -1036,13 +1216,7 @@ Execute a single command in a subshell on the local system. If .Ic command -is ommitted, then an interactive -subshell is invoked. -.It Ic status -Show the current status of -.Nm telnet . -This includes the peer one is connected to, as well -as the current mode. +is omitted, then an interactive subshell is invoked. .It Ic \&? Op Ar command Get help. With no arguments, .Nm telnet @@ -1059,8 +1233,8 @@ .Ev DISPLAY , and .Ev TERM -environent variables. -Other envirnoment variables may be propogated +environment variables. +Other environment variables may be propagated to the other side via the .Dv TELNET ENVIRON option. @@ -1085,3 +1259,5 @@ .Ic eof character is only recognized (and sent to the remote system) when it is the first character on a line. +.Sh BUGS +The source code is not comprehensible. Index: telnet.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/telnet.c,v retrieving revision 1.4 diff -w -u -r1.4 telnet.c --- telnet.c 16 Jul 1996 09:23:59 -0000 1.4 +++ telnet.c 3 May 2007 05:29:18 -0000 @@ -35,52 +35,52 @@ * From: @(#)telnet.c 5.53 (Berkeley) 3/22/91 */ char telnet_rcsid[] = - "$Id: telnet.c,v 1.4 1996/07/16 09:23:59 dholland Exp $"; +"$Id: telnet.c,v 1.41 2002/08/12 06:51:36 dholland Exp $"; #include -#include #include #include +#include #include - -#if defined(unix) -#include -/* By the way, we need to include curses.h before telnet.h since, - * among other things, telnet.h #defines 'DO', which is a variable - * declared in curses.h. - */ -#endif /* defined(unix) */ +#include +#include #include -#include #include -#include -#include -#include -#include #include "ring.h" - #include "defines.h" #include "externs.h" #include "types.h" -#include "general.h" +#include "environ.h" #include "proto.h" +#include "netlink.h" +#include "terminal.h" + +/* + * Due to lossage in some linux distributions/kernel releases/libc versions + * this must come *after* termios.h (which is included in externs.h) + */ +#include + +#ifdef USE_NCURSES +#include +#endif #define strip(x) ((x)&0x7f) -static unsigned char subbuffer[SUBBUFSIZE], - *subpointer, *subend; /* buffer for sub-options */ +static unsigned char subbuffer[SUBBUFSIZE]; +static unsigned char *subpointer, *subend; /* buffer for sub-options */ #define SB_CLEAR() subpointer = subbuffer; #define SB_TERM() { subend = subpointer; SB_CLEAR(); } #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ *subpointer++ = (c); \ } -#define SB_GET() ((*subpointer++)&0xff) -#define SB_PEEK() ((*subpointer)&0xff) +#define SB_GET() (*subpointer++) +#define SB_PEEK() (*subpointer) #define SB_EOF() (subpointer >= subend) #define SB_LEN() (subend - subpointer) @@ -98,7 +98,6 @@ ISend, /* trying to send network data in */ debug = 0, crmod, - netdata, /* Print out network data flow */ crlf, /* Should '\r' be mapped to (or )? */ #if defined(TN3270) noasynchtty = 0,/* User specified "-noasynch" on command line */ @@ -119,7 +118,7 @@ char *prompt = 0; -cc_t escape; +cc_t escapechar; cc_t rlogin; #ifdef KLUDGELINEMODE cc_t echoc; @@ -140,8 +139,8 @@ static int telrcv_state; -jmp_buf toplevel; -jmp_buf peerdied; +sigjmp_buf toplevel; +sigjmp_buf peerdied; int flushline; int linemode; @@ -169,29 +168,23 @@ }; #endif - /* * Initialize telnet environment. */ - - void -init_telnet() -{ +void init_telnet(void) { env_init(); + cmdtab_init(); SB_CLEAR(); - ClearArray(options); + memset(options, 0, sizeof(options)); connected = In3270 = ISend = localflow = donebinarytoggle = 0; -#if defined(ENCRYPT) || defined(AUTHENTICATE) - auth_encrypt_connect(connected); -#endif SYNCHing = 0; /* Don't change NetTrace */ - escape = CONTROL(']'); + escapechar = CONTROL(']'); rlogin = _POSIX_VDISABLE; #ifdef KLUDGELINEMODE echoc = CONTROL('E'); @@ -202,26 +195,18 @@ } -#ifdef notdef -#include +#if 0 +#include - /*VARARGS*/ - static void -printring(va_alist) - va_dcl -{ +static void printring(Ring *ring, const char *format, ...) { va_list ap; char buffer[100]; /* where things go */ char *ptr; - char *format; char *string; - Ring *ring; int i; - va_start(ap); + va_start(ap, format); - ring = va_arg(ap, Ring *); - format = va_arg(ap, char *); ptr = buffer; while ((i = *format++) != 0) { @@ -233,8 +218,8 @@ break; case 's': string = va_arg(ap, char *); - ring_supply_data(ring, buffer, ptr-buffer); - ring_supply_data(ring, string, strlen(string)); + ring->supply_data(buffer, ptr-buffer); + ring->supply_data(string, strlen(string)); ptr = buffer; break; case 0: @@ -244,11 +229,12 @@ ExitString("printring: unknown format character.\n", 1); /*NOTREACHED*/ } - } else { + } + else { *ptr++ = i; } } - ring_supply_data(ring, buffer, ptr-buffer); + ring->supply_data(buffer, ptr-buffer); } #endif @@ -260,10 +246,7 @@ * is in disagreement as to what the current state should be. */ - void -send_do(c, init) - register int c, init; -{ +void send_do(int c, int init) { if (init) { if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || my_want_state_is_do(c)) @@ -276,10 +259,7 @@ printoption("SENT", DO, c); } - void -send_dont(c, init) - register int c, init; -{ +void send_dont(int c, int init) { if (init) { if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || my_want_state_is_dont(c)) @@ -292,10 +272,7 @@ printoption("SENT", DONT, c); } - void -send_will(c, init) - register int c, init; -{ +void send_will(int c, int init) { if (init) { if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || my_want_state_is_will(c)) @@ -308,10 +285,7 @@ printoption("SENT", WILL, c); } - void -send_wont(c, init) - register int c, init; -{ +void send_wont(int c, int init) { if (init) { if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || my_want_state_is_wont(c)) @@ -325,10 +299,7 @@ } - void -willoption(option) - int option; -{ +void willoption(int option) { int new_state_ok = 0; if (do_dont_resp[option]) { @@ -338,9 +309,7 @@ } if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { - switch (option) { - case TELOPT_ECHO: # if defined(TN3270) /* @@ -365,18 +334,12 @@ } /* Fall through */ case TELOPT_EOR: -#endif /* defined(TN3270) */ +#endif /* TN3270 */ case TELOPT_BINARY: case TELOPT_SGA: settimer(modenegotiated); /* FALL THROUGH */ case TELOPT_STATUS: -#if defined(AUTHENTICATE) - case TELOPT_AUTHENTICATION: -#endif -#if defined(ENCRYPT) - case TELOPT_ENCRYPT: -#endif new_state_ok = 1; break; @@ -400,22 +363,16 @@ set_my_want_state_do(option); send_do(option, 0); setconnmode(0); /* possibly set new tty mode */ - } else { + } + else { do_dont_resp[option]++; send_dont(option, 0); } } set_my_state_do(option); -#if defined(ENCRYPT) - if (option == TELOPT_ENCRYPT) - encrypt_send_support(); -#endif } - void -wontoption(option) - int option; -{ +void wontoption(int option) { if (do_dont_resp[option]) { --do_dont_resp[option]; if (do_dont_resp[option] && my_state_is_dont(option)) @@ -450,7 +407,8 @@ if (my_state_is_do(option)) send_dont(option, 0); setconnmode(0); /* Set new tty mode */ - } else if (option == TELOPT_TM) { + } + else if (option == TELOPT_TM) { /* * Special case for TM. */ @@ -461,10 +419,7 @@ set_my_state_dont(option); } - static void -dooption(option) - int option; -{ +static void dooption(int option) { int new_state_ok = 0; if (will_wont_resp[option]) { @@ -498,20 +453,11 @@ case TELOPT_TTYPE: /* terminal type option */ case TELOPT_SGA: /* no big deal */ case TELOPT_ENVIRON: /* environment variable option */ -#if defined(ENCRYPT) - case TELOPT_ENCRYPT: /* encryption variable option */ -#endif - new_state_ok = 1; - break; -#if defined(AUTHENTICATE) - case TELOPT_AUTHENTICATION: - if (autologin) new_state_ok = 1; break; -#endif case TELOPT_XDISPLOC: /* X Display location */ - if (env_getvalue((unsigned char *)"DISPLAY")) + if (env_getvalue("DISPLAY", 0)) new_state_ok = 1; break; @@ -534,12 +480,14 @@ if (new_state_ok) { set_my_want_state_will(option); send_will(option, 0); - setconnmode(0); /* Set new tty mode */ - } else { + setconnmode(0); /* Set new tty fmode */ + } + else { will_wont_resp[option]++; send_wont(option, 0); } - } else { + } + else { /* * Handle options that need more things done after the * other side has acknowledged the option. @@ -560,11 +508,7 @@ set_my_state_will(option); } - static void -dontoption(option) - int option; -{ - +static void dontoption(int option) { if (will_wont_resp[option]) { --will_wont_resp[option]; if (will_wont_resp[option] && my_state_is_wont(option)) @@ -586,6 +530,81 @@ set_my_state_wont(option); } +//////////////////////////////////////////////////////////// + +/* special-purpose array of const char */ + +/* this struct avoids problems with (const char *const *) in C */ +struct stringentry { + const char *str; +}; + +struct stringarray { + struct stringentry *entries; + unsigned num; + unsigned alloced; +}; + +#define SA_INITIALIZER { NULL, 0, 0 } + +static void sa_setsize(struct stringarray *ar, unsigned newsize) { + if (newsize >= ar->alloced) { + struct stringentry *newentries; + unsigned newalloced; + size_t allocsize; + + newalloced = ar->alloced; + while (newsize >= newalloced) { + newalloced = (newalloced+1)*2; + } + + assert(SIZE_T_MAX/sizeof(struct stringentry) > newalloced); + allocsize = newalloced*sizeof(struct stringentry); + + if (ar->entries != NULL) { + newentries = (struct stringentry *)realloc(ar->entries, allocsize); + } + else { + newentries = (struct stringentry *)malloc(allocsize); + } + if (newentries==NULL) { + /* XXX / FIXME this is not optimal */ + perror("realloc"); + exit(1); + } + ar->entries = newentries; + ar->alloced = newalloced; + } + else if (newsize==0) { + free(ar->entries); + ar->entries = NULL; + ar->alloced = 0; + } + ar->num = newsize; +} + +static int sa_getnum(const struct stringarray *ar) { + return ar->num; +} + +static const char *sa_getguy(const struct stringarray *ar, unsigned x) { + assert(xnum); + return ar->entries[x].str; +} + +static void sa_setguy(struct stringarray *ar, unsigned x, const char *s) { + assert(xnum); + ar->entries[x].str = s; +} + +static void sa_add(struct stringarray *ar, const char *s) { + sa_setsize(ar, ar->num+1); + assert(ar->num>0); + ar->entries[ar->num-1].str = s; +} + +//////////////////////////////////////////////////////////// + /* * Given a buffer returned by tgetent(), this routine will turn * the pipe seperated list of names in the buffer into an array @@ -593,94 +612,74 @@ * duplicate, or verbose names (names with spaces). */ -static char *name_unknown = "UNKNOWN"; -static char *unknown[] = { 0, 0 }; +static int is_unique(const char *name, const struct stringarray *ar) { + int i; + for (i=0; i 40) { - name = 0; - unknown[0] = name_unknown; - } else { - unknown[0] = name; - upcase(name); - } - } else - unknown[0] = name_unknown; /* - * Count up the number of names. + * Skip entries longer than 40 characters. + * Skip entries with spaces or non-ascii values. + * Convert lower case letters to upper case. */ - for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { - if (*cp == '|') - n++; + if (strlen(cp)>40) continue; + bad = 0; + for (i=0; cp[i]; i++) if (!isascii(cp[i]) || cp[i]==' ') bad=1; + if (bad) continue; + upcase(cp); + if (is_unique(cp, fill)) sa_add(fill, cp); } - /* - * Allocate an array to put the name pointers into - */ - argv = (char **)malloc((n+3)*sizeof(char *)); - if (argv == 0) - return(unknown); /* - * Fill up the array of pointers to names. - */ - *argv = 0; - argvp = argv+1; - n = 0; - for (cp = cp2 = buf; (c = *cp); cp++) { - if (c == '|' || c == ':') { - *cp++ = '\0'; - /* - * Skip entries that have spaces or are over 40 - * characters long. If this is our environment - * name, then put it up front. Otherwise, as - * long as this is not a duplicate name (case - * insensitive) add it to the list. + * Move the name we were passed to the beginning if it's not already + * there. */ - if (n || (cp - cp2 > 41)) - ; - else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) - *argv = cp2; - else if (is_unique(cp2, argv+1, argvp)) - *argvp++ = cp2; - if (c == ':') - break; - /* - * Skip multiple delimiters. Reset cp2 to - * the beginning of the next name. Reset n, - * the flag for names with spaces. - */ - while ((c = *cp) == '|') - cp++; - cp2 = cp; - n = 0; + for (j=1; j', &temp[2], len-2); - } else { - ExitString("No room in buffer for terminal type.\n", 1); - /*NOTREACHED*/ - } } break; case TELOPT_TSPEED: @@ -826,21 +782,10 @@ if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { - long ospeed, ispeed; - unsigned char temp[50]; - int len; - - TerminalSpeeds(&ispeed, &ospeed); - - sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, - TELOPT_TSPEED, TELQUAL_IS, ospeed, ispeed, IAC, SE); - len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ - - if (len < NETROOM()) { - ring_supply_data(&netoring, temp, len); - printsub('>', temp+2, len - 2); - } -/*@*/ else printf("lm_will: not enough room in buffer\n"); + long oospeed, iispeed; + TerminalSpeeds(&iispeed, &oospeed); + ringbuf_printf(netoring, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, + TELQUAL_IS, oospeed, iispeed, IAC, SE); } break; case TELOPT_LFLOW: @@ -917,10 +862,8 @@ if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { - unsigned char temp[50], *dp; - int len; - - if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) { + const char *dp = env_getvalue("DISPLAY", 0); + if (dp == NULL) { /* * Something happened, we no longer have a DISPLAY * variable. So, turn off the option. @@ -928,226 +871,77 @@ send_wont(TELOPT_XDISPLOC, 1); break; } - sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, + ringbuf_printf(netoring, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); - len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ - - if (len < NETROOM()) { - ring_supply_data(&netoring, temp, len); - printsub('>', temp+2, len - 2); - } -/*@*/ else printf("lm_will: not enough room in buffer\n"); } break; -#if defined(AUTHENTICATE) - case TELOPT_AUTHENTICATION: { - if (!autologin) - break; - if (SB_EOF()) - return; - switch(SB_GET()) { - case TELQUAL_IS: - if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) - return; - auth_is(subpointer, SB_LEN()); - break; - case TELQUAL_SEND: - if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) - return; - auth_send(subpointer, SB_LEN()); - break; - case TELQUAL_REPLY: - if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) - return; - auth_reply(subpointer, SB_LEN()); - break; - case TELQUAL_NAME: - if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) - return; - auth_name(subpointer, SB_LEN()); - break; - } - } - break; -#endif -#if defined(ENCRYPT) - case TELOPT_ENCRYPT: - if (SB_EOF()) - return; - switch(SB_GET()) { - case ENCRYPT_START: - if (my_want_state_is_dont(TELOPT_ENCRYPT)) - return; - encrypt_start(subpointer, SB_LEN()); - break; - case ENCRYPT_END: - if (my_want_state_is_dont(TELOPT_ENCRYPT)) - return; - encrypt_end(); - break; - case ENCRYPT_SUPPORT: - if (my_want_state_is_wont(TELOPT_ENCRYPT)) - return; - encrypt_support(subpointer, SB_LEN()); - break; - case ENCRYPT_REQSTART: - if (my_want_state_is_wont(TELOPT_ENCRYPT)) - return; - encrypt_request_start(subpointer, SB_LEN()); - break; - case ENCRYPT_REQEND: - if (my_want_state_is_wont(TELOPT_ENCRYPT)) - return; - /* - * We can always send an REQEND so that we cannot - * get stuck encrypting. We should only get this - * if we have been able to get in the correct mode - * anyhow. - */ - encrypt_request_end(); - break; - case ENCRYPT_IS: - if (my_want_state_is_dont(TELOPT_ENCRYPT)) - return; - encrypt_is(subpointer, SB_LEN()); - break; - case ENCRYPT_REPLY: - if (my_want_state_is_wont(TELOPT_ENCRYPT)) - return; - encrypt_reply(subpointer, SB_LEN()); - break; - case ENCRYPT_ENC_KEYID: - if (my_want_state_is_dont(TELOPT_ENCRYPT)) - return; - encrypt_enc_keyid(subpointer, SB_LEN()); - break; - case ENCRYPT_DEC_KEYID: - if (my_want_state_is_wont(TELOPT_ENCRYPT)) - return; - encrypt_dec_keyid(subpointer, SB_LEN()); - break; - default: - break; - } - break; -#endif default: break; } } -static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; +//static char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; - void -lm_will(cmd, len) - unsigned char *cmd; - int len; -{ +void lm_will(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ return; } - switch(cmd[0]) { - case LM_FORWARDMASK: /* We shouldn't ever get this... */ - default: - str_lm[3] = DONT; - str_lm[4] = cmd[0]; - if (NETROOM() > sizeof(str_lm)) { - ring_supply_data(&netoring, str_lm, sizeof(str_lm)); - printsub('>', &str_lm[2], sizeof(str_lm)-2); - } -/*@*/ else printf("lm_will: not enough room in buffer\n"); - break; - } + + ringbuf_printf(netoring, "%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, + DONT, cmd[0], IAC, SE); } - void -lm_wont(cmd, len) - unsigned char *cmd; - int len; -{ +void lm_wont(unsigned char *cmd, int len) { + (void)cmd; + if (len < 1) { /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ return; } - switch(cmd[0]) { - case LM_FORWARDMASK: /* We shouldn't ever get this... */ - default: /* We are always DONT, so don't respond */ - return; - } } - void -lm_do(cmd, len) - unsigned char *cmd; - int len; -{ +void lm_do(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ return; } - switch(cmd[0]) { - case LM_FORWARDMASK: - default: - str_lm[3] = WONT; - str_lm[4] = cmd[0]; - if (NETROOM() > sizeof(str_lm)) { - ring_supply_data(&netoring, str_lm, sizeof(str_lm)); - printsub('>', &str_lm[2], sizeof(str_lm)-2); - } -/*@*/ else printf("lm_do: not enough room in buffer\n"); - break; - } + ringbuf_printf(netoring, "%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, + WONT, cmd[0], IAC, SE); } - void -lm_dont(cmd, len) - unsigned char *cmd; - int len; -{ +void lm_dont(unsigned char *cmd, int len) { + (void)cmd; + if (len < 1) { /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ return; } - switch(cmd[0]) { - case LM_FORWARDMASK: - default: /* we are always WONT, so don't respond */ - break; - } } -static unsigned char str_lm_mode[] = { - IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE -}; +void lm_mode(unsigned char *cmd, int len, int init) { + int k; + + if (len != 1) return; + if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) return; + if (*cmd&MODE_ACK) return; - void -lm_mode(cmd, len, init) - unsigned char *cmd; - int len, init; -{ - if (len != 1) - return; - if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) - return; - if (*cmd&MODE_ACK) - return; linemode = *cmd&(MODE_MASK&~MODE_ACK); - str_lm_mode[4] = linemode; - if (!init) - str_lm_mode[4] |= MODE_ACK; - if (NETROOM() > sizeof(str_lm_mode)) { - ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); - printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); + k = linemode; + if (!init) { + k |= MODE_ACK; } -/*@*/ else printf("lm_mode: not enough room in buffer\n"); + + ringbuf_printf(netoring, "%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, + k, IAC, SE); + setconnmode(0); /* set changed mode */ } - /* * slc() * Handle special character suboption of LINEMODE. @@ -1165,9 +959,7 @@ #define SLC_RVALUE 2 static int slc_mode = SLC_EXPORT; - void -slc_init() -{ +void slc_init(void) { register struct spc *spcp; localchars = 1; @@ -1195,27 +987,17 @@ /* No EOR */ initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); initfunc(SLC_EOF, 0); -#ifndef SYSV_TERMIO initfunc(SLC_SUSP, SLC_FLUSHIN); -#endif + initfunc(SLC_EC, 0); initfunc(SLC_EL, 0); -#ifndef SYSV_TERMIO - initfunc(SLC_EW, 0); - initfunc(SLC_RP, 0); - initfunc(SLC_LNEXT, 0); -#endif + initfunc(SLC_XON, 0); initfunc(SLC_XOFF, 0); -#ifdef SYSV_TERMIO - spc_data[SLC_XON].mylevel = SLC_CANTCHANGE; - spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE; -#endif + initfunc(SLC_FORW1, 0); -#ifdef USE_TERMIO initfunc(SLC_FORW2, 0); /* No FORW2 */ -#endif initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); #undef initfunc @@ -1227,58 +1009,37 @@ } - void -slcstate() -{ +void slcstate(void) { printf("Special characters are %s values\n", slc_mode == SLC_IMPORT ? "remote default" : slc_mode == SLC_EXPORT ? "local" : "remote"); } - void -slc_mode_export() -{ +void slc_mode_export(void) { slc_mode = SLC_EXPORT; if (my_state_is_will(TELOPT_LINEMODE)) slc_export(); } - void -slc_mode_import(def) - int def; -{ +void slc_mode_import(int def) { slc_mode = def ? SLC_IMPORT : SLC_RVALUE; if (my_state_is_will(TELOPT_LINEMODE)) slc_import(def); } -unsigned char slc_import_val[] = { - IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE -}; -unsigned char slc_import_def[] = { - IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE -}; - - void -slc_import(def) - int def; -{ - if (NETROOM() > sizeof(slc_import_val)) { +void slc_import(int def) { if (def) { - ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); - printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); - } else { - ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); - printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); + ringbuf_printf(netoring, "%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, + LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE); } + else { + ringbuf_printf(netoring, "%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, + LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE); } -/*@*/ else printf("slc_import: not enough room\n"); } - void -slc_export() -{ +void slc_export(void) { register struct spc *spcp; TerminalDefaultChars(); @@ -1300,11 +1061,7 @@ setconnmode(1); /* Make sure the character values are set */ } - void -slc(cp, len) - register unsigned char *cp; - int len; -{ +void slc(unsigned char *cp, int len) { register struct spc *spcp; register int func,level; @@ -1330,7 +1087,7 @@ level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); - if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && + if ((cp[SLC_VALUE] == spcp->val) && ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { continue; } @@ -1370,9 +1127,7 @@ setconnmode(1); /* set the new character values */ } - void -slc_check() -{ +void slc_check(void) { register struct spc *spcp; slc_start_reply(); @@ -1390,13 +1145,15 @@ setconnmode(1); } - +/* + * XXX + * this appears overflowable + * http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=220 + */ unsigned char slc_reply[128]; unsigned char *slc_replyp; - void -slc_start_reply() -{ +void slc_start_reply(void) { slc_replyp = slc_reply; *slc_replyp++ = IAC; *slc_replyp++ = SB; @@ -1404,41 +1161,29 @@ *slc_replyp++ = LM_SLC; } - void -slc_add_reply(func, flags, value) - unsigned char func; - unsigned char flags; - cc_t value; -{ +void slc_add_reply(int func, int flags, int value) { if ((*slc_replyp++ = func) == IAC) *slc_replyp++ = IAC; if ((*slc_replyp++ = flags) == IAC) *slc_replyp++ = IAC; - if ((*slc_replyp++ = (unsigned char)value) == IAC) + if ((*slc_replyp++ = value) == IAC) *slc_replyp++ = IAC; } - void -slc_end_reply() -{ +void slc_end_reply(void) { register int len; *slc_replyp++ = IAC; *slc_replyp++ = SE; len = slc_replyp - slc_reply; - if (len <= 6) - return; - if (NETROOM() > len) { - ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); - printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); - } -/*@*/else printf("slc_end_reply: not enough room\n"); + if (len <= 6) return; + + printsub('>', &slc_reply[2], len - 2); + ringbuf_write(netoring, (char *)slc_reply, len); } - int -slc_update() -{ - register struct spc *spcp; +int slc_update(void) { + struct spc *spcp; int need_update = 0; for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { @@ -1453,25 +1198,22 @@ return(need_update); } - void -env_opt(buf, len) - register unsigned char *buf; - register int len; -{ - register unsigned char *ep = 0, *epc = 0; - register int i; +void env_opt(unsigned char *buf, int len) { + unsigned char *ep = 0, *epc = 0; + int i; - switch(buf[0]&0xff) { + switch(buf[0]) { case TELQUAL_SEND: env_opt_start(); if (len == 1) { env_opt_add(NULL); - } else for (i = 1; i < len; i++) { - switch (buf[i]&0xff) { + } + else for (i = 1; i < len; i++) { + switch (buf[i]) { case ENV_VALUE: if (ep) { *epc = 0; - env_opt_add(ep); + env_opt_add((const char *)ep); } ep = epc = &buf[i+1]; break; @@ -1485,7 +1227,7 @@ } if (ep) { *epc = 0; - env_opt_add(ep); + env_opt_add((const char *)ep); } } env_opt_end(1); @@ -1506,9 +1248,7 @@ unsigned char *opt_replyp; unsigned char *opt_replyend; - void -env_opt_start() -{ +void env_opt_start(void) { if (opt_reply) opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); else @@ -1526,32 +1266,27 @@ *opt_replyp++ = TELQUAL_IS; } - void -env_opt_start_info() -{ +void env_opt_start_info(void) { env_opt_start(); if (opt_replyp) opt_replyp[-1] = TELQUAL_INFO; } - void -env_opt_add(ep) - register unsigned char *ep; -{ - register unsigned char *vp, c; +void env_opt_add(const char *ep) { + const char *vp; + unsigned char c; if (opt_reply == NULL) /*XXX*/ return; /*XXX*/ if (ep == NULL || *ep == '\0') { - env_default(1); - while ((ep = env_default(0))!=NULL) - env_opt_add(ep); + int i; + env_iterate(&i, 1); + for (ep = env_next(&i,1); ep; ep = env_next(&i,1)) env_opt_add(ep); return; } - vp = env_getvalue(ep); - if (opt_replyp + (vp ? strlen((char *)vp) : 0) + - strlen((char *)ep) + 6 > opt_replyend) + vp = env_getvalue(ep, 1); + if (opt_replyp + (vp ? strlen(vp) : 0) + strlen(ep) + 6 > opt_replyend) { register int len; opt_replyend += OPT_REPLY_SIZE; @@ -1568,7 +1303,7 @@ *opt_replyp++ = ENV_VAR; for (;;) { while ((c = *ep++)!=0) { - switch(c&0xff) { + switch(c) { case IAC: *opt_replyp++ = IAC; break; @@ -1588,21 +1323,15 @@ } } - void -env_opt_end(emptyok) - register int emptyok; -{ +void env_opt_end(int emptyok) { register int len; len = opt_replyp - opt_reply + 2; if (emptyok || len > 6) { *opt_replyp++ = IAC; *opt_replyp++ = SE; - if (NETROOM() > len) { - ring_supply_data(&netoring, opt_reply, len); printsub('>', &opt_reply[2], len - 2); - } -/*@*/ else printf("slc_end_reply: not enough room\n"); + ringbuf_write(netoring, (char *)opt_reply, len); } if (opt_reply) { free(opt_reply); @@ -1611,46 +1340,27 @@ } -int -telrcv(void) -{ +int telrcv(void) { int c; - int scc; - unsigned char *sbp = NULL; - int count; int returnValue = 0; - scc = 0; - count = 0; while (TTYROOM() > 2) { - if (scc == 0) { - if (count) { - ring_consumed(&netiring, count); - returnValue = 1; - count = 0; - } - sbp = netiring.consume; - scc = ring_full_consecutive(&netiring); - if (scc == 0) { + if (!ringbuf_getch(netiring, &c)) { /* No more data coming in */ break; } - } - - c = *sbp++ & 0xff, scc--; count++; -#if defined(ENCRYPT) - if (decrypt_input) - c = (*decrypt_input)(c); -#endif + returnValue = 1; switch (telrcv_state) { - case TS_CR: telrcv_state = TS_DATA; if (c == '\0') { break; /* Ignore \0 after CR */ } - else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { + else if ((c == '\n') && + my_want_state_is_dont(TELOPT_ECHO) && + !crmod) + { TTYADD(c); break; } @@ -1664,12 +1374,7 @@ # if defined(TN3270) if (In3270) { *Ifrontp++ = c; - while (scc > 0) { - c = *sbp++ & 0377, scc--; count++; -#if defined(ENCRYPT) - if (decrypt_input) - c = (*decrypt_input)(c); -#endif + while (ringbuf_getch(netiring, &c)) { if (c == IAC) { telrcv_state = TS_IAC; break; @@ -1686,39 +1391,28 @@ * input, the mapping is done here (sigh). */ if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { - if (scc > 0) { - c = *sbp&0xff; -#if defined(ENCRYPT) - if (decrypt_input) - c = (*decrypt_input)(c); -#endif + if (ringbuf_getch(netiring, &c)) { if (c == 0) { - sbp++, scc--; count++; /* a "true" CR */ TTYADD('\r'); - } else if (my_want_state_is_dont(TELOPT_ECHO) && + } + else if (my_want_state_is_dont(TELOPT_ECHO) && (c == '\n')) { - sbp++, scc--; count++; TTYADD('\n'); - } else { -#if defined(ENCRYPT) - if (decrypt_input) - (*decrypt_input)(-1); -#endif - + } + else { + ringbuf_ungetch(netiring, c); TTYADD('\r'); - if (crmod) { - TTYADD('\n'); + if (crmod) TTYADD('\n'); } } - } else { + else { telrcv_state = TS_CR; TTYADD('\r'); - if (crmod) { - TTYADD('\n'); + if (crmod) TTYADD('\n'); } } - } else { + else { TTYADD(c); } continue; @@ -1726,23 +1420,18 @@ case TS_IAC: process_iac: switch (c) { - case WILL: telrcv_state = TS_WILL; continue; - case WONT: telrcv_state = TS_WONT; continue; - case DO: telrcv_state = TS_DO; continue; - case DONT: telrcv_state = TS_DONT; continue; - case DM: /* * We may have missed an urgent notification, @@ -1751,11 +1440,10 @@ */ printoption("RCVD", IAC, DM); SYNCHing = 1; - (void) ttyflush(1); - SYNCHing = stilloob(); + ttyflush(1); + SYNCHing = nlink_stilloob(); settimer(gotDM); break; - case SB: SB_CLEAR(); telrcv_state = TS_SB; @@ -1767,7 +1455,8 @@ if (Ibackp == Ifrontp) { Ibackp = Ifrontp = Ibuf; ISend = 0; /* should have been! */ - } else { + } + else { Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1); ISend = 1; } @@ -1782,7 +1471,8 @@ # else /* !defined(TN3270) */ if (In3270) { *Ifrontp++ = IAC; - } else { + } + else { TTYADD(IAC); } # endif /* !defined(TN3270) */ @@ -1817,7 +1507,8 @@ SetIn3270(); if (c == TELOPT_NAWS) { sendnaws(); - } else if (c == TELOPT_LFLOW) { + } + else if (c == TELOPT_LFLOW) { localflow = 1; setcommandmode(); setconnmode(0); @@ -1837,7 +1528,8 @@ case TS_SB: if (c == IAC) { telrcv_state = TS_SE; - } else { + } + else { SB_ACCUM(c); } continue; @@ -1870,7 +1562,8 @@ } SB_ACCUM(c); telrcv_state = TS_SB; - } else { + } + else { SB_ACCUM(IAC); SB_ACCUM(SE); subpointer -= 2; @@ -1880,17 +1573,14 @@ telrcv_state = TS_DATA; } } + } - if (count) - ring_consumed(&netiring, count); - return returnValue||count; + return returnValue; } static int bol = 1, local = 0; -int -rlogin_susp(void) -{ +int rlogin_susp(void) { if (local) { local = 0; bol = 1; @@ -1900,33 +1590,24 @@ return(0); } - static int -telsnd() -{ - int tcc; - int count; +static int telsnd(void) { + // int tcc; + // int count; int returnValue = 0; - unsigned char *tbp = NULL; + // const char *tbp = NULL; - tcc = 0; - count = 0; - while (NETROOM() > 2) { - register int sc; - register int c; - - if (tcc == 0) { - if (count) { - ring_consumed(&ttyiring, count); - returnValue = 1; - count = 0; - } - tbp = ttyiring.consume; - tcc = ring_full_consecutive(&ttyiring); - if (tcc == 0) { + // tcc = 0; + // count = 0; + while (ringbuf_empty_count(netoring) > 2) { + int c, sc; + + if (!ringbuf_getch(ttyiring, &c)) { break; } - } - c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; + returnValue = 1; + + sc = strip(c); + if (rlogin != _POSIX_VDISABLE) { if (bol) { bol = 0; @@ -1934,7 +1615,8 @@ local = 1; continue; } - } else if (local) { + } + else if (local) { local = 0; if (sc == '.' || c == termEofChar) { bol = 1; @@ -1946,47 +1628,56 @@ command(0, "z\n", 2); continue; } - if (sc == escape) { - command(0, (char *)tbp, tcc); + if (sc == escapechar && escapechar !=_POSIX_VDISABLE) { + int l; + char buf[128]; + l = ringbuf_gets(ttyiring, buf, sizeof(buf)); + command(0, buf, l); bol = 1; - count += tcc; - tcc = 0; flushline = 1; break; } if (sc != rlogin) { - ++tcc; - --tbp; - --count; + ringbuf_ungetch(ttyiring, c); c = sc = rlogin; } } if ((sc == '\n') || (sc == '\r')) bol = 1; - } else if (sc == escape) { + } + else if (sc == escapechar && escapechar != _POSIX_VDISABLE) { + int ignore = 0; /* * Double escape is a pass through of a single escape character. */ - if (tcc && strip(*tbp) == escape) { - tbp++; - tcc--; - count++; + if (ringbuf_getch(ttyiring, &c)) { + if (strip(c) != escapechar) ringbuf_ungetch(ttyiring, c); + else { bol = 0; - } else { - command(0, (char *)tbp, tcc); + ignore = 1; + } + } + if (!ignore) { + int l; + char buf[128]; + l = ringbuf_gets(ttyiring, buf, sizeof(buf)); + command(0, buf, l); bol = 1; - count += tcc; - tcc = 0; flushline = 1; break; } - } else + } + else { bol = 0; + } #ifdef KLUDGELINEMODE if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { - if (tcc > 0 && strip(*tbp) == echoc) { - tcc--; tbp++; count++; - } else { + int ignore=0; + if (ringbuf_getch(ttyiring, &c) > 0) { + if (strip(c) != echoc) ringbuf_ungetch(ttyiring, c); + else ignore=1; + } + if (!ignore) { dontlecho = !dontlecho; settimer(echotoggle); setconnmode(0); @@ -2018,7 +1709,8 @@ case '\r': if (!crlf) { NET2ADD('\r', '\0'); - } else { + } + else { NET2ADD('\r', '\n'); } bol = flushline = 1; @@ -2030,15 +1722,16 @@ NETADD(c); break; } - } else if (c == IAC) { + } + else if (c == IAC) { NET2ADD(IAC, IAC); - } else { + } + else { NETADD(c); } } - if (count) - ring_consumed(&ttyiring, count); - return returnValue||count; /* Non-zero if we did anything */ + + return returnValue; /* Non-zero if we did anything */ } /* @@ -2050,11 +1743,8 @@ * */ - - int -Scheduler(block) - int block; /* should we block in the select ? */ -{ +/* block: should we block in the select ? */ +static int Scheduler(int block) { /* One wants to be a bit careful about setting returnValue * to one, since a one implies we did some useful work, * and therefore probably won't be called to block next @@ -2065,7 +1755,7 @@ /* Decide which rings should be processed */ - netout = ring_full_count(&netoring) && + netout = ringbuf_full_count(netoring) && (flushline || (my_want_state_is_wont(TELOPT_LINEMODE) #ifdef KLUDGELINEMODE @@ -2073,29 +1763,29 @@ #endif ) || my_want_state_is_will(TELOPT_BINARY)); - ttyout = ring_full_count(&ttyoring); + ttyout = ringbuf_full_count(ttyoring); #if defined(TN3270) - ttyin = ring_empty_count(&ttyiring) && (shell_active == 0); + ttyin = ringbuf_empty_count(ttyiring) && (shell_active == 0); #else /* defined(TN3270) */ - ttyin = ring_empty_count(&ttyiring); + ttyin = ringbuf_empty_count(ttyiring); #endif /* defined(TN3270) */ #if defined(TN3270) - netin = ring_empty_count(&netiring); + netin = ringbuf_empty_count(netiring); # else /* !defined(TN3270) */ - netin = !ISend && ring_empty_count(&netiring); + netin = !ISend && ringbuf_empty_count(netiring); # endif /* !defined(TN3270) */ netex = !SYNCHing; /* If we have seen a signal recently, reset things */ -# if defined(TN3270) && defined(unix) +#ifdef TN3270 if (HaveInput) { HaveInput = 0; (void) signal(SIGIO, inputAvailable); } -#endif /* defined(TN3270) && defined(unix) */ +#endif /* TN3270 */ /* Call to system code to process rings */ @@ -2103,7 +1793,7 @@ /* Now, look at the input rings, looking for work to do. */ - if (ring_full_count(&ttyiring)) { + if (ringbuf_full_count(ttyiring)) { # if defined(TN3270) if (In3270) { int c; @@ -2122,7 +1812,7 @@ # endif /* defined(TN3270) */ } - if (ring_full_count(&netiring)) { + if (ringbuf_full_count(netiring)) { # if !defined(TN3270) returnValue |= telrcv(); # else /* !defined(TN3270) */ @@ -2135,35 +1825,14 @@ /* * Select from tty and network... */ - void -telnet(user) - char *user; -{ +void telnet(const char *user) { + (void)user; + sys_telnet_init(); -#if defined(ENCRYPT) || defined(AUTHENTICATE) - { - static char local_host[256] = { 0 }; - int len = sizeof(local_host); - if (!local_host[0]) { - gethostname(local_host, len); - local_host[sizeof(local_host)-1] = 0; - } - auth_encrypt_init(local_host, hostname, "TELNET", 0); - auth_encrypt_user(user); - } -#endif # if !defined(TN3270) if (telnetport) { -#if defined(AUTHENTICATE) - if (autologin) - send_will(TELOPT_AUTHENTICATION, 1); -#endif -#if defined(ENCRYPT) - send_do(TELOPT_ENCRYPT, 1); - send_will(TELOPT_ENCRYPT, 1); -#endif send_do(TELOPT_SGA, 1); send_will(TELOPT_TTYPE, 1); send_will(TELOPT_NAWS, 1); @@ -2172,7 +1841,7 @@ send_will(TELOPT_LINEMODE, 1); send_will(TELOPT_ENVIRON, 1); send_do(TELOPT_STATUS, 1); - if (env_getvalue((unsigned char *)"DISPLAY")) + if (env_getvalue("DISPLAY", 0)) send_will(TELOPT_XDISPLOC, 1); if (eight) tel_enter_binary(eight); @@ -2248,14 +1917,11 @@ * character. */ - static char * -nextitem(current) - char *current; -{ - if ((*current&0xff) != IAC) { +static unsigned char *nextitem(unsigned char *current) { + if (*current != IAC) { return current+1; } - switch (*(current+1)&0xff) { + switch (current[1]) { case DO: case DONT: case WILL: @@ -2263,11 +1929,11 @@ return current+3; case SB: /* loop forever looking for the SE */ { - register char *look = current+2; + unsigned char *look = current+2; for (;;) { - if ((*look++&0xff) == IAC) { - if ((*look++&0xff) == SE) { + if (*look++ == IAC) { + if (*look++ == SE) { return look; } } @@ -2296,14 +1962,12 @@ * us in any case. */ - static void -netclear() -{ +static void netclear(void) { #if 0 /* XXX */ register char *thisitem, *next; char *good; -#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ - ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) +#define wewant(p) ((nfrontp > p) && (*p == IAC) && \ + (p[1] != EC) && (p[1] != EL)) thisitem = netobuf; @@ -2339,9 +2003,7 @@ * These routines add various telnet commands to the data stream. */ - static void -doflush() -{ +static void doflush(void) { NET2ADD(IAC, DO); NETADD(TELOPT_TM); flushline = 1; @@ -2351,9 +2013,7 @@ printoption("SENT", DO, TELOPT_TM); } - void -xmitAO() -{ +void xmitAO(void) { NET2ADD(IAC, AO); printoption("SENT", IAC, AO); if (autoflush) { @@ -2362,27 +2022,21 @@ } - void -xmitEL() -{ +void xmitEL(void) { NET2ADD(IAC, EL); printoption("SENT", IAC, EL); } - void -xmitEC() -{ +void xmitEC(void) { NET2ADD(IAC, EC); printoption("SENT", IAC, EC); } - int -dosynch() -{ +int dosynch(void) { netclear(); /* clear the path to the network */ NETADD(IAC); - setneturg(); + ringbuf_set_mark(netoring); NETADD(DM); printoption("SENT", IAC, DM); return 1; @@ -2390,11 +2044,12 @@ int want_status_response = 0; - int -get_status() -{ +int get_status(const char *junk1, const char *junk2) { unsigned char tmp[16]; - register unsigned char *cp; + unsigned char *cp; + + (void)junk1; + (void)junk2; if (my_want_state_is_dont(TELOPT_STATUS)) { printf("Remote side does not support STATUS option\n"); @@ -2408,17 +2063,13 @@ *cp++ = TELQUAL_SEND; *cp++ = IAC; *cp++ = SE; - if (NETROOM() >= cp - tmp) { - ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); - } + ringbuf_write(netoring, (char *)tmp, cp-tmp); ++want_status_response; return 1; } - void -intp() -{ +void intp(void) { NET2ADD(IAC, IP); printoption("SENT", IAC, IP); flushline = 1; @@ -2430,9 +2081,7 @@ } } - void -sendbrk() -{ +void sendbrk(void) { NET2ADD(IAC, BREAK); printoption("SENT", IAC, BREAK); flushline = 1; @@ -2444,9 +2093,7 @@ } } - void -sendabort() -{ +void sendabort(void) { NET2ADD(IAC, ABORT); printoption("SENT", IAC, ABORT); flushline = 1; @@ -2458,9 +2105,7 @@ } } - void -sendsusp() -{ +void sendsusp(void) { NET2ADD(IAC, SUSP); printoption("SENT", IAC, SUSP); flushline = 1; @@ -2472,16 +2117,12 @@ } } - void -sendeof() -{ +void sendeof(void) { NET2ADD(IAC, xEOF); printoption("SENT", IAC, xEOF); } - void -sendayt() -{ +void sendayt(void) { NET2ADD(IAC, AYT); printoption("SENT", IAC, AYT); } @@ -2490,12 +2131,10 @@ * Send a window size update to the remote system. */ - void -sendnaws() -{ +void sendnaws(void) { long rows, cols; unsigned char tmp[16]; - register unsigned char *cp; + unsigned char *cp; if (my_state_is_wont(TELOPT_NAWS)) return; @@ -2516,25 +2155,18 @@ PUTSHORT(cp, rows); *cp++ = IAC; *cp++ = SE; - if (NETROOM() >= cp - tmp) { - ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); - } + ringbuf_write(netoring, (char *)tmp, cp-tmp); } - void -tel_enter_binary(rw) - int rw; -{ +void tel_enter_binary(int rw) { if (rw&1) send_do(TELOPT_BINARY, 1); if (rw&2) send_will(TELOPT_BINARY, 1); } -void -tel_leave_binary(int rw) -{ +void tel_leave_binary(int rw) { if (rw&1) send_dont(TELOPT_BINARY, 1); if (rw&2) Index: terminal.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/terminal.c,v retrieving revision 1.2 retrieving revision 1.34 diff -w -u -r1.2 -r1.34 --- terminal.c 16 Jul 1996 07:57:25 -0000 1.2 +++ terminal.c 11 Aug 2002 23:35:27 -0000 1.34 @@ -35,70 +35,80 @@ * From: @(#)terminal.c 5.3 (Berkeley) 3/22/91 */ char terminal_rcsid[] = - "$Id: terminal.c,v 1.2 1996/07/16 07:57:25 dholland Exp $"; + "$Id: terminal.c,v 1.34 2002/08/11 23:35:27 dholland Exp $"; -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include "ring.h" - +#include "defines.h" #include "externs.h" #include "types.h" #include "proto.h" +#include "terminal.h" -Ring ttyoring, ttyiring; -unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ]; +static int TerminalWrite(const char *buf, int n); +static int TerminalRead(char *buf, int n); -int termdata; /* Debugging flag */ +struct ringbuf *ttyoring, *ttyiring; -#ifdef USE_TERMIO # ifndef VDISCARD cc_t termFlushChar; # endif + # ifndef VLNEXT cc_t termLiteralNextChar; # endif + # ifndef VSUSP cc_t termSuspChar; # endif + # ifndef VWERASE cc_t termWerasChar; # endif + # ifndef VREPRINT cc_t termRprntChar; # endif + # ifndef VSTART cc_t termStartChar; # endif + # ifndef VSTOP cc_t termStopChar; # endif + # ifndef VEOL cc_t termForw1Char; # endif + # ifndef VEOL2 cc_t termForw2Char; # endif + # ifndef VSTATUS cc_t termAytChar; # endif -#else -cc_t termForw2Char; -cc_t termAytChar; -#endif /* * initialize the terminal data structures. */ - - void -init_terminal() -{ - if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) { +void init_terminal(void) { + ttyoring = ringbuf_create(2*BUFSIZ, ttysink, NULL); + if (ttyoring==NULL) { exit(1); } - if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) { + ttyiring = ringbuf_create(BUFSIZ, NULL, ttysrc); + if (ttyiring==NULL) { exit(1); } autoflush = TerminalAutoFlush(); @@ -107,6 +117,7 @@ /* * Send as much data as possible to the terminal. + * if arg "drop" is nonzero, drop data on the floor instead. * * Return value: * -1: No useful work done, data waiting to go out. @@ -114,64 +125,27 @@ * 1: All waiting data was written out. * n: All data - n was written out. */ +int ttyflush(int drop) { + const struct datasink_c *s = NULL; + int rv; - -int -ttyflush(int drop) -{ - register int n, n0, n1; - - n0 = ring_full_count(&ttyoring); - if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) { if (drop) { TerminalFlushOutput(); - /* we leave 'n' alone! */ - } else { - n = TerminalWrite(ttyoring.consume, n); - } + s = ringbuf_setsink(ttyoring, nullsink); } - if (n > 0) { - if (termdata && n) { - Dump('>', ttyoring.consume, n); - } - /* - * If we wrote everything, and the full count is - * larger than what we wrote, then write the - * rest of the buffer. - */ - if (n1 == n && n0 > n) { - n1 = n0 - n; - if (!drop) - n1 = TerminalWrite(ttyoring.bottom, n1); - n += n1; - } - ring_consumed(&ttyoring, n); - } - if (n < 0) - return -1; - if (n == n0) { - if (n0) - return -1; - return 0; - } - return n0 - n + 1; + rv = ringbuf_flush(ttyoring); + if (s) ringbuf_setsink(ttyoring, s); + return rv; } + /* * These routines decides on what the mode should be (based on the values * of various global variables). */ - - -int -getconnmode(void) -{ - extern int linemode; +int getconnmode(void) { int mode = 0; -#ifdef KLUDGELINEMODE - extern int kludgelinemode; -#endif if (In3270) return(MODE_FLOW); @@ -204,39 +178,539 @@ return(mode); } - void -setconnmode(force) - int force; -{ -#ifdef ENCRYPT - static int enc_passwd = 0; -#endif - register int newmode; +void setconnmode(int force) { + int newmode; newmode = getconnmode()|(force?MODE_FORCE:0); TerminalNewMode(newmode); -#ifdef ENCRYPT - if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) { - if (my_want_state_is_will(TELOPT_ENCRYPT) - && (enc_passwd == 0) && !encrypt_output) { - encrypt_request_start(0, 0); - enc_passwd = 1; } + + +void setcommandmode(void) { + TerminalNewMode(-1); +} + + +/*********************/ + +static int tout; /* Output file descriptor */ +static int tin; /* Input file descriptor */ + + +static int ttysource_read(char *buf, int maxlen) { + int l = TerminalRead(buf, maxlen); + if (l<0 && errno==EWOULDBLOCK) l = 0; + else if (l==0 && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { + /* EOF detection for line mode!!!! */ + /* must be an EOF... */ + *buf = termEofChar; + l = 1; + } + return l; +} + +static const struct datasink_c chan1 = { + TerminalWrite, /* write */ + TerminalWrite, /* writeurg */ +}; + +static const struct datasource_c chan2 = { + ttysource_read, /* read */ +}; + +const struct datasink_c *const ttysink = &chan1; +const struct datasource_c *const ttysrc = &chan2; + + +struct termios old_tc; +struct termios new_tc; + +#ifndef TCSANOW + +#if defined(TCSETS) +#define TCSANOW TCSETS +#define TCSADRAIN TCSETSW +#define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) + +#elif defined(TCSETA) +#define TCSANOW TCSETA +#define TCSADRAIN TCSETAW +#define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) + +#else +#define TCSANOW TIOCSETA +#define TCSADRAIN TIOCSETAW +#define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) + +#endif + +#define tcsetattr(f, a, t) ioctl(f, a, (char *)t) +#define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) +#ifdef CIBAUD +#define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) +#else +#define cfgetispeed(ptr) cfgetospeed(ptr) +#endif + +#endif /* no TCSANOW */ + + +static void susp(int sig); + +void tlink_init(void) { +#ifdef SIGTSTP + signal(SIGTSTP, susp); +#endif + tout = fileno(stdout); + tin = fileno(stdin); +} + +int tlink_getifd(void) { + return tin; +} + +int tlink_getofd(void) { + return tout; +} + +static int TerminalWrite(const char *buf, int n) { + int r; + do { + r = write(tout, buf, n); + } while (r<0 && errno==EINTR); + if (r<0 && (errno==ENOBUFS || errno==EWOULDBLOCK)) r = 0; + return r; +} + +static int TerminalRead(char *buf, int n) { + int r; + do { + r = read(tin, buf, n); + } while (r<0 && errno==EINTR); + return r; +} + +#ifdef SIGTSTP +static void susp(int sig) { + (void)sig; + + if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) + return; + if (localchars) + sendsusp(); +} +#endif + +/* + * TerminalNewMode - set up terminal to a specific mode. + * MODE_ECHO: do local terminal echo + * MODE_FLOW: do local flow control + * MODE_TRAPSIG: do local mapping to TELNET IAC sequences + * MODE_EDIT: do local line editing + * + * Command mode: + * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG + * local echo + * local editing + * local xon/xoff + * local signal mapping + * + * Linemode: + * local/no editing + * Both Linemode and Single Character mode: + * local/remote echo + * local/no xon/xoff + * local/no signal mapping + */ + +void TerminalNewMode(int f) +{ + static int prevmode = 0; + struct termios tmp_tc; + + int onoff; + int old; + cc_t esc; + + globalmode = f&~MODE_FORCE; + if (prevmode == f) + return; + + /* + * Write any outstanding data before switching modes + * ttyflush() returns 0 only when there is no more data + * left to write out, it returns -1 if it couldn't do + * anything at all, otherwise it returns 1 + the number + * of characters left to write. + */ + old = ttyflush(SYNCHing|flushout); + if (old < 0 || old > 1) { + tcgetattr(tin, &tmp_tc); + do { + /* + * Wait for data to drain, then flush again. + */ + tcsetattr(tin, TCSADRAIN, &tmp_tc); + old = ttyflush(SYNCHing|flushout); + } while (old < 0 || old > 1); + } + + old = prevmode; + prevmode = f&~MODE_FORCE; + tmp_tc = new_tc; + + if (f&MODE_ECHO) { + tmp_tc.c_lflag |= ECHO; + tmp_tc.c_oflag |= ONLCR; + if (crlf) + tmp_tc.c_iflag |= ICRNL; + } + else { + tmp_tc.c_lflag &= ~ECHO; + tmp_tc.c_oflag &= ~ONLCR; + if (crlf) tmp_tc.c_iflag &= ~ICRNL; + } + + if ((f&MODE_FLOW) == 0) { + tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON); + } + else { + tmp_tc.c_iflag |= IXANY|IXOFF|IXON; + } + + if ((f&MODE_TRAPSIG) == 0) { + tmp_tc.c_lflag &= ~ISIG; + localchars = 0; + } + else { + tmp_tc.c_lflag |= ISIG; + localchars = 1; + } + + if (f&MODE_EDIT) { + tmp_tc.c_lflag |= ICANON; + } + else { + tmp_tc.c_lflag &= ~ICANON; + tmp_tc.c_iflag &= ~ICRNL; + tmp_tc.c_cc[VMIN] = 1; + tmp_tc.c_cc[VTIME] = 0; + } + + if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { +#ifdef VLNEXT + tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); +#endif + } + + if (f&MODE_SOFT_TAB) { +#ifdef OXTABS + tmp_tc.c_oflag |= OXTABS; +#endif +#ifdef TABDLY + tmp_tc.c_oflag &= ~TABDLY; + tmp_tc.c_oflag |= TAB3; +#endif + } + else { +#ifdef OXTABS + tmp_tc.c_oflag &= ~OXTABS; +#endif +#ifdef TABDLY + tmp_tc.c_oflag &= ~TABDLY; +#endif + } + + if (f&MODE_LIT_ECHO) { +#ifdef ECHOCTL + tmp_tc.c_lflag &= ~ECHOCTL; +#endif + } + else { +#ifdef ECHOCTL + tmp_tc.c_lflag |= ECHOCTL; +#endif + } + + if (f == -1) { + onoff = 0; + } + else { + if (f & MODE_INBIN) { + tmp_tc.c_iflag &= ~ISTRIP; + } + else { + // Commented this out 5/97 so it works with 8-bit characters + // ...and put it back 12/99 because it violates the RFC and + // breaks SunOS. + tmp_tc.c_iflag |= ISTRIP; + } + if (f & MODE_OUTBIN) { + tmp_tc.c_cflag &= ~(CSIZE|PARENB); + tmp_tc.c_cflag |= CS8; + tmp_tc.c_oflag &= ~OPOST; } else { - if (enc_passwd) { - encrypt_request_end(); - enc_passwd = 0; + tmp_tc.c_cflag &= ~(CSIZE|PARENB); + tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); + tmp_tc.c_oflag |= OPOST; } + onoff = 1; } + + if (f != -1) { +#ifdef SIGTSTP + signal(SIGTSTP, susp); +#endif /* SIGTSTP */ + +#ifdef SIGINFO + signal(SIGINFO, ayt); +#endif /* SIGINFO */ + +#if defined(NOKERNINFO) + tmp_tc.c_lflag |= NOKERNINFO; #endif + /* + * We don't want to process ^Y here. It's just another + * character that we'll pass on to the back end. It has + * to process it because it will be processed when the + * user attempts to read it, not when we send it. + */ +#ifdef VDSUSP + tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); +#endif + /* + * If the VEOL character is already set, then use VEOL2, + * otherwise use VEOL. + */ + esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escapechar; + if ((tmp_tc.c_cc[VEOL] != esc) +#ifdef VEOL2 + && (tmp_tc.c_cc[VEOL2] != esc) +#endif + ) { + if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) + tmp_tc.c_cc[VEOL] = esc; +#ifdef VEOL2 + else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) + tmp_tc.c_cc[VEOL2] = esc; +#endif + } + } + else { + +#ifdef SIGINFO + signal(SIGINFO, ayt_status); +#endif /* SIGINFO */ + +#ifdef SIGTSTP + signal(SIGTSTP, SIG_DFL); +/* (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); */ +#endif /* SIGTSTP */ + + tmp_tc = old_tc; + } + if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) + tcsetattr(tin, TCSANOW, &tmp_tc); + + ioctl(tin, FIONBIO, (char *)&onoff); + ioctl(tout, FIONBIO, (char *)&onoff); + +#if defined(TN3270) + if (noasynchtty == 0) { + ioctl(tin, FIOASYNC, (char *)&onoff); + } +#endif /* defined(TN3270) */ } +#ifndef B19200 +#define B19200 B9600 +#endif + +#ifndef B38400 +#define B38400 B19200 +#endif + +#ifndef B57600 +#define B57600 B38400 +#endif + +#ifndef B115200 +#define B115200 B57600 +#endif + +/* + * This code assumes that the values B0, B50, B75... + * are in ascending order. They do not have to be + * contiguous. + */ +struct termspeeds { + long speed; + long value; +} termspeeds[] = { + { 0, B0 }, { 50, B50 }, { 75, B75 }, + { 110, B110 }, { 134, B134 }, { 150, B150 }, + { 200, B200 }, { 300, B300 }, { 600, B600 }, + { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, + { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, + { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, + { -1, B115200 } +}; + +void TerminalSpeeds(long *ispeed, long *ospeed) { + register struct termspeeds *tp; + register long in, out; + + out = cfgetospeed(&old_tc); + in = cfgetispeed(&old_tc); + if (in == 0) + in = out; + + tp = termspeeds; + while ((tp->speed != -1) && (tp->value < in)) + tp++; + *ispeed = tp->speed; + + tp = termspeeds; + while ((tp->speed != -1) && (tp->value < out)) + tp++; + *ospeed = tp->speed; +} + +int TerminalWindowSize(long *rows, long *cols) { +#ifdef TIOCGWINSZ + struct winsize ws; + + if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { + *rows = ws.ws_row; + *cols = ws.ws_col; + return 1; + } +#endif /* TIOCGWINSZ */ + return 0; +} + +/* + * EmptyTerminal - called to make sure that the terminal buffer is + * empty. Note that we consider the buffer to run all the way to the + * kernel (thus the select). + */ +void EmptyTerminal(void) { + fd_set o; + FD_ZERO(&o); + + if (TTYBYTES() == 0) { + FD_SET(tout, &o); + select(tout+1, NULL, &o, NULL, NULL); /* wait for TTLOWAT */ + } + else { + while (TTYBYTES()) { + ttyflush(0); + FD_SET(tout, &o); + select(tout+1, NULL, &o, NULL, NULL); /* wait for TTLOWAT */ + } + } +} + +int +TerminalAutoFlush(void) +{ +#if defined(LNOFLSH) + int flush; + + ioctl(tin, TIOCLGET, (char *)&flush); + return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ +#else /* LNOFLSH */ + return 1; +#endif /* LNOFLSH */ +} + +/* + * Flush output to the terminal + */ void -setcommandmode() +TerminalFlushOutput() { - TerminalNewMode(-1); +#ifdef TIOCFLUSH + (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); +#else + (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); +#endif +} + + void +TerminalSaveState() +{ +#ifndef USE_TERMIO + ioctl(0, TIOCGETP, (char *)&ottyb); + ioctl(0, TIOCGETC, (char *)&otc); + ioctl(0, TIOCGLTC, (char *)&oltc); + ioctl(0, TIOCLGET, (char *)&olmode); + + ntc = otc; + nltc = oltc; + nttyb = ottyb; + +#else /* USE_TERMIO */ + tcgetattr(0, &old_tc); + + new_tc = old_tc; + +#ifndef VDISCARD + termFlushChar = CONTROL('O'); +#endif +#ifndef VWERASE + termWerasChar = CONTROL('W'); +#endif +#ifndef VREPRINT + termRprntChar = CONTROL('R'); +#endif +#ifndef VLNEXT + termLiteralNextChar = CONTROL('V'); +#endif +#ifndef VSTART + termStartChar = CONTROL('Q'); +#endif +#ifndef VSTOP + termStopChar = CONTROL('S'); +#endif +#ifndef VSTATUS + termAytChar = CONTROL('T'); +#endif +#endif /* USE_TERMIO */ +} + +void TerminalDefaultChars(void) { +#ifndef USE_TERMIO + ntc = otc; + nltc = oltc; + nttyb.sg_kill = ottyb.sg_kill; + nttyb.sg_erase = ottyb.sg_erase; +#else /* USE_TERMIO */ + memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); +#ifndef VDISCARD + termFlushChar = CONTROL('O'); +#endif +#ifndef VWERASE + termWerasChar = CONTROL('W'); +#endif +#ifndef VREPRINT + termRprntChar = CONTROL('R'); +#endif +#ifndef VLNEXT + termLiteralNextChar = CONTROL('V'); +#endif +#ifndef VSTART + termStartChar = CONTROL('Q'); +#endif +#ifndef VSTOP + termStopChar = CONTROL('S'); +#endif +#ifndef VSTATUS + termAytChar = CONTROL('T'); +#endif +#endif /* USE_TERMIO */ } Index: terminal.h =================================================================== RCS file: terminal.h diff -N terminal.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ terminal.h 11 Aug 2002 19:42:08 -0000 1.7 @@ -0,0 +1,11 @@ +#define TTYADD(c) {if (!(SYNCHing||flushout)) ringbuf_putch(ttyoring,c);} +#define TTYBYTES() (ringbuf_full_count(ttyoring)) +#define TTYROOM() (ringbuf_empty_count(ttyoring)) + +void tlink_init(void); + +void EmptyTerminal(void); + + +int tlink_getifd(void); +int tlink_getofd(void); Index: tn3270.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/tn3270.c,v retrieving revision 1.3 retrieving revision 1.9 diff -w -u -r1.3 -r1.9 --- tn3270.c 16 Jul 1996 07:57:25 -0000 1.3 +++ tn3270.c 13 Aug 1996 09:08:34 -0000 1.9 @@ -35,18 +35,14 @@ * From: @(#)tn3270.c 5.2 (Berkeley) 3/1/91 */ char tn3270_rcsid[] = - "$Id: tn3270.c,v 1.3 1996/07/16 07:57:25 dholland Exp $"; + "$Id: tn3270.c,v 1.9 1996/08/13 09:08:34 dholland Exp $"; -#include #include #include -#include "general.h" - #include "defines.h" #include "ring.h" #include "externs.h" -#include "fdset.h" #include "proto.h" #if defined(TN3270) @@ -57,15 +53,12 @@ #include "../tn3270/telextrn.h" #include "../tn3270/ctlr/externs.h" -#if defined(unix) -int - HaveInput, /* There is input available to scan */ - cursesdata, /* Do we dump curses data? */ - sigiocount; /* Number of times we got a SIGIO */ +int HaveInput; /* There is input available to scan */ +int cursesdata; /* Do we dump curses data? */ +int sigiocount; /* Number of times we got a SIGIO */ char tline[200]; char *transcom = 0; /* transparent mode command (default: none) */ -#endif /* defined(unix) */ char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; @@ -75,30 +68,24 @@ IAC, SE }; #define SBTERMMODEL 13 -static int - Sent3270TerminalType; /* Have we said we are a 3270? */ +static int Sent3270TerminalType; /* Have we said we are a 3270? */ #endif /* defined(TN3270) */ - void -init_3270() -{ +void init_3270(void) { #if defined(TN3270) -#if defined(unix) HaveInput = 0; sigiocount = 0; -#endif /* defined(unix) */ Sent3270TerminalType = 0; Ifrontp = Ibackp = Ibuf; init_ctlr(); /* Initialize some things */ init_keyboard(); init_screen(); init_system(); -#endif /* defined(TN3270) */ +#endif /* TN3270 */ } - #if defined(TN3270) /* @@ -110,12 +97,12 @@ * only client needs for us to do that. */ - int -DataToNetwork(buffer, count, done) - register char *buffer; /* where the data is */ - register int count; /* how much to send */ - int done; /* is this the last of a logical block */ -{ +/* + * buffer: where the data is + * count: how much to send + * done: is this the last of a logical block + */ +int DataToNetwork(char *buffer, int count, int done) { register int loop, c; int origCount; @@ -130,7 +117,7 @@ netflush(); while (NETROOM() < 6) { FD_SET(net, &o); - (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, + select(net+1, (fd_set *) 0, &o, (fd_set *) 0, (struct timeval *) 0); netflush(); } @@ -148,7 +135,7 @@ loop--; } if ((c = c-loop)) { - ring_supply_data(&netoring, buffer-c, c); + netoring.supply_data(buffer-c, c); count -= c; } if (loop) { @@ -165,20 +152,13 @@ return(origCount - count); } - -#if defined(unix) - void -inputAvailable() -{ +void inputAvailable(void) { HaveInput = 1; sigiocount++; } -#endif /* defined(unix) */ - void -outputPurge() -{ - (void) ttyflush(1); +void outputPurge(void) { + ttyflush(1); } @@ -194,11 +174,11 @@ * *all* the data at one time (thus the select). */ - int -DataToTerminal(buffer, count) - register char *buffer; /* where the data is */ - register int count; /* how much to send */ -{ +/* + * buffer: where the data is + * count: how much to send + */ +int DataToTerminal(char *buffer, int count) { register int c; int origCount; @@ -206,40 +186,32 @@ while (count) { if (TTYROOM() == 0) { -#if defined(unix) - fd_set o; + fd_set o; FD_ZERO(&o); -#endif /* defined(unix) */ - (void) ttyflush(0); + ttyflush(0); while (TTYROOM() == 0) { -#if defined(unix) FD_SET(tout, &o); - (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, - (struct timeval *) 0); -#endif /* defined(unix) */ - (void) ttyflush(0); + select(tout+1, NULL, &o, NULL, NULL); + ttyflush(0); } } c = TTYROOM(); if (c > count) { c = count; } - ring_supply_data(&ttyoring, buffer, c); + ttyoring.supply_data(buffer, c); count -= c; buffer += c; } - return(origCount); + return origCount; } /* * Push3270 - Try to send data along the 3270 output (to screen) direction. */ - - int -Push3270() -{ +int Push3270(void) { int save = ring_full_count(&netiring); if (save) { @@ -262,30 +234,18 @@ * Finish3270 - get the last dregs of 3270 data out to the terminal * before quitting. */ - - void -Finish3270() -{ +void Finish3270(void) { while (Push3270() || !DoTerminalOutput()) { -#if defined(unix) HaveInput = 0; -#endif /* defined(unix) */ - ; } } /* StringToTerminal - output a null terminated string to the terminal */ - - void -StringToTerminal(s) - char *s; -{ - int count; - - count = strlen(s); +void StringToTerminal(char *s) { + int count = strlen(s); if (count) { - (void) DataToTerminal(s, count); /* we know it always goes... */ + DataToTerminal(s, count); /* we know it always goes... */ } } @@ -295,29 +255,26 @@ * curses(3x) can call us to send out data. */ - void -_putchar(c) - char c; -{ +void _putchar(char c) { #if defined(sun) /* SunOS 4.0 bug */ c &= 0x7f; -#endif /* defined(sun) */ +#endif if (cursesdata) { Dump('>', &c, 1); } if (!TTYROOM()) { - (void) DataToTerminal(&c, 1); - } else { + DataToTerminal(&c, 1); + } + else { TTYADD(c); } } #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ - void -SetIn3270() -{ +void SetIn3270(void) { if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY) - && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) { + && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) + { if (!In3270) { In3270 = 1; Init3270(); /* Initialize 3270 functions */ @@ -325,7 +282,8 @@ InitTerminal(); /* Start terminal going */ setconnmode(0); } - } else { + } + else { if (In3270) { StopScreen(1); In3270 = 0; @@ -343,9 +301,7 @@ * Return '0' if no more responses to send; '1' if a response sent. */ - int -tn3270_ttype() -{ +int tn3270_ttype(void) { /* * Try to send a 3270 type terminal name. Decide which one based * on the format of our screen, and (in the future) color @@ -358,15 +314,18 @@ MaxNumberLines = 27; MaxNumberColumns = 132; sb_terminal[SBTERMMODEL] = '5'; - } else if (MaxNumberLines >= 43) { + } + else if (MaxNumberLines >= 43) { MaxNumberLines = 43; MaxNumberColumns = 80; sb_terminal[SBTERMMODEL] = '4'; - } else if (MaxNumberLines >= 32) { + } + else if (MaxNumberLines >= 32) { MaxNumberLines = 32; MaxNumberColumns = 80; sb_terminal[SBTERMMODEL] = '3'; - } else { + } + else { MaxNumberLines = 24; MaxNumberColumns = 80; sb_terminal[SBTERMMODEL] = '2'; @@ -380,21 +339,16 @@ /*NOTREACHED*/ } printsub('>', sb_terminal+2, sizeof sb_terminal-2); - ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); + netoring.supply_data(sb_terminal, sizeof(sb_terminal)); return 1; - } else { + } + else { return 0; } } -#if defined(unix) - int -settranscom(argc, argv) - int argc; - char *argv[]; -{ +int settranscom(int argc, char *argv[]) { int i; - if (argc == 1 && transcom) { transcom = 0; } @@ -402,12 +356,11 @@ return; } transcom = tline; - (void) strcpy(transcom, argv[1]); + strcpy(transcom, argv[1]); for (i = 2; i < argc; ++i) { - (void) strcat(transcom, " "); - (void) strcat(transcom, argv[i]); + strcat(transcom, " "); + strcat(transcom, argv[i]); } } -#endif /* defined(unix) */ #endif /* defined(TN3270) */ Index: types.h =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/types.h,v retrieving revision 1.1 retrieving revision 1.2 diff -w -u -r1.1 -r1.2 --- types.h 16 Jul 1996 05:17:22 -0000 1.1 +++ types.h 27 Jul 1996 00:45:54 -0000 1.2 @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)types.h 5.1 (Berkeley) 9/14/90 - * $Id: types.h,v 1.1 1996/07/16 05:17:22 dholland Exp $ + * $Id: types.h,v 1.2 1996/07/27 00:45:54 dholland Exp $ */ typedef struct { @@ -42,12 +42,11 @@ extern Modelist modelist[]; typedef struct { - int - system, /* what the current time is */ - echotoggle, /* last time user entered echo character */ - modenegotiated, /* last time operating mode negotiated */ - didnetreceive, /* last time we read data from network */ - gotDM; /* when did we last see a data mark */ + int system; /* what the current time is */ + int echotoggle; /* last time user entered echo character */ + int modenegotiated; /* last time operating mode negotiated */ + int didnetreceive; /* last time we read data from network */ + int gotDM; /* when did we last see a data mark */ } Clocks; extern Clocks clocks; Index: utilities.c =================================================================== RCS file: /home/dholland/projects/linuxstuff/netkit/CVSREPO/netkit/src/netkit-telnet/telnet/utilities.c,v retrieving revision 1.3 retrieving revision 1.24 diff -w -u -r1.3 -r1.24 --- utilities.c 16 Jul 1996 09:23:59 -0000 1.3 +++ utilities.c 11 Aug 2002 23:23:33 -0000 1.24 @@ -35,108 +35,66 @@ * From: @(#)utilities.c 5.3 (Berkeley) 3/22/91 */ char util_rcsid[] = - "$Id: utilities.c,v 1.3 1996/07/16 09:23:59 dholland Exp $"; + "$Id: utilities.c,v 1.24 2002/08/11 23:23:33 dholland Exp $"; #define TELOPTS #define TELCMDS #define SLC_NAMES -#include -#include + #include #include #include #include +#include #include -#include -#include +#include -#include "general.h" -#include "fdset.h" #include "ring.h" #include "defines.h" #include "externs.h" #include "proto.h" +#include "terminal.h" -FILE *NetTrace = 0; /* Not in bss, since needs to stay */ -int prettydump; +FILE *NetTrace = 0; /* Not in bss, since needs to stay */ /* ? */ +char NetTraceFile[256] = "(standard output)"; /* * upcase() * * Upcase (in place) the argument. */ - - void -upcase(argument) - register char *argument; -{ - register int c; - - while ((c = *argument) != 0) { - if (islower(c)) { - *argument = toupper(c); - } - argument++; - } -} - -/* - * SetSockOpt() - * - * Compensate for differences in 4.2 and 4.3 systems. - */ - -int -SetSockOpt(int fd, int level, int option, int yesno) -{ -#ifndef NOT43 - return setsockopt(fd, level, option, - (char *)&yesno, sizeof yesno); -#else /* NOT43 */ - if (yesno == 0) { /* Can't do that in 4.2! */ - fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", - option); - return -1; +void upcase(char *str) { + int i; + for (i=0; str[i]; i++) { + if (islower(str[i])) str[i] = toupper(str[i]); } - return setsockopt(fd, level, option, 0, 0); -#endif /* NOT43 */ } /* * The following are routines used to print out debugging information. */ -unsigned char NetTraceFile[256] = "(standard output)"; - - void -SetNetTrace(file) - register char *file; -{ +void SetNetTrace(const char *file) { if (NetTrace && NetTrace != stdout) fclose(NetTrace); - if (file && (strcmp(file, "-") != 0)) { + if (file && strcmp(file, "-")) { NetTrace = fopen(file, "w"); if (NetTrace) { - strcpy((char *)NetTraceFile, file); + strlcpy(NetTraceFile, file, sizeof(NetTraceFile)); return; } fprintf(stderr, "Cannot open %s.\n", file); } NetTrace = stdout; - strcpy((char *)NetTraceFile, "(standard output)"); + strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile)); } - void -Dump(direction, buffer, length) - char direction; - unsigned char *buffer; - int length; -{ # define BYTES_PER_LINE 32 # define min(x,y) ((x' */ - unsigned char *pointer; /* where suboption data sits */ - int length; /* length of suboption data */ -{ +/* direction: '<' or '>' */ +/* pointer: where suboption data sits */ +/* length: length of suboption data */ +void printsub(int direction, unsigned char *pointer, int length) { register int i = 0; - char buf[512]; - extern int want_status_response; if (showoptions || direction == 0 || (want_status_response && (pointer[0] == TELOPT_STATUS))) { @@ -333,7 +287,7 @@ fprintf(NetTrace, "(Empty suboption???)"); return; } - switch (pointer[0]) { + switch ((unsigned char)(pointer[0])) { case TELOPT_TTYPE: fprintf(NetTrace, "TERMINAL-TYPE "); switch (pointer[1]) { @@ -413,151 +367,13 @@ fprintf(NetTrace, " ?%d?", pointer[i]); break; -#if defined(AUTHENTICATE) - case TELOPT_AUTHENTICATION: - fprintf(NetTrace, "AUTHENTICATION"); - if (length < 2) { - fprintf(NetTrace, " (empty suboption???)"); - break; - } - switch (pointer[1]) { - case TELQUAL_REPLY: - case TELQUAL_IS: - fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? - "IS" : "REPLY"); - if (AUTHTYPE_NAME_OK(pointer[2])) - fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); - else - fprintf(NetTrace, "%d ", pointer[2]); - if (length < 3) { - fprintf(NetTrace, "(partial suboption???)"); - break; - } - fprintf(NetTrace, "%s|%s", - ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - - auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - fprintf(NetTrace, "%s", buf); - break; - - case TELQUAL_SEND: - i = 2; - fprintf(NetTrace, " SEND "); - while (i < length) { - if (AUTHTYPE_NAME_OK(pointer[i])) - fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); - else - fprintf(NetTrace, "%d ", pointer[i]); - if (++i >= length) { - fprintf(NetTrace, "(partial suboption???)"); - break; - } - fprintf(NetTrace, "%s|%s ", - ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - ++i; - } - break; - - case TELQUAL_NAME: - i = 2; - fprintf(NetTrace, " NAME \""); - while (i < length) - putc(pointer[i++], NetTrace); - putc('"', NetTrace); - break; - - default: - for (i = 2; i < length; i++) - fprintf(NetTrace, " ?%d?", pointer[i]); - break; - } - break; -#endif - -#if defined(ENCRYPT) - case TELOPT_ENCRYPT: - fprintf(NetTrace, "ENCRYPT"); - if (length < 2) { - fprintf(NetTrace, " (empty suboption???)"); - break; - } - switch (pointer[1]) { - case ENCRYPT_START: - fprintf(NetTrace, " START"); - break; - - case ENCRYPT_END: - fprintf(NetTrace, " END"); - break; - - case ENCRYPT_REQSTART: - fprintf(NetTrace, " REQUEST-START"); - break; - - case ENCRYPT_REQEND: - fprintf(NetTrace, " REQUEST-END"); - break; - - case ENCRYPT_IS: - case ENCRYPT_REPLY: - fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? - "IS" : "REPLY"); - if (length < 3) { - fprintf(NetTrace, " (partial suboption???)"); - break; - } - if (ENCTYPE_NAME_OK(pointer[2])) - fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); - else - fprintf(NetTrace, " %d (unknown)", pointer[2]); - - encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - fprintf(NetTrace, "%s", buf); - break; - - case ENCRYPT_SUPPORT: - i = 2; - fprintf(NetTrace, " SUPPORT "); - while (i < length) { - if (ENCTYPE_NAME_OK(pointer[i])) - fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); - else - fprintf(NetTrace, "%d ", pointer[i]); - i++; - } - break; - - case ENCRYPT_ENC_KEYID: - fprintf(NetTrace, " ENC_KEYID "); - goto encommon; - - case ENCRYPT_DEC_KEYID: - fprintf(NetTrace, " DEC_KEYID "); - goto encommon; - - default: - fprintf(NetTrace, " %d (unknown)", pointer[1]); - encommon: - for (i = 2; i < length; i++) - fprintf(NetTrace, " %d", pointer[i]); - break; - } - break; -#endif - case TELOPT_LINEMODE: fprintf(NetTrace, "LINEMODE "); if (length < 2) { fprintf(NetTrace, " (empty suboption???)"); break; } - switch (pointer[1]) { + switch ((unsigned char)(pointer[1])) { case WILL: fprintf(NetTrace, "WILL "); goto common; @@ -574,7 +390,7 @@ fprintf(NetTrace, "(no option???)"); break; } - switch (pointer[2]) { + switch ((unsigned char)(pointer[2])) { case LM_FORWARDMASK: fprintf(NetTrace, "Forward Mask"); for (i = 3; i < length; i++) @@ -629,7 +445,7 @@ } { char tbuf[64]; - sprintf(tbuf, "%s%s%s%s%s", + snprintf(tbuf, sizeof(tbuf), "%s%s%s%s%s", pointer[2]&MODE_EDIT ? "|EDIT" : "", pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", @@ -650,8 +466,8 @@ break; case TELOPT_STATUS: { - register char *cp; - register int j, k; + const char *cp; + int j, k; fprintf(NetTrace, "STATUS"); @@ -673,7 +489,7 @@ fprintf(NetTrace, " IS\n"); for (i = 2; i < length; i++) { - switch(pointer[i]) { + switch((unsigned char)(pointer[i])) { case DO: cp = "DO"; goto common2; case DONT: cp = "DONT"; goto common2; case WILL: cp = "WILL"; goto common2; @@ -819,41 +635,7 @@ } } -/* EmptyTerminal - called to make sure that the terminal buffer is empty. - * Note that we consider the buffer to run all the - * way to the kernel (thus the select). - */ - - void -EmptyTerminal() -{ -#if defined(unix) - fd_set o; - - FD_ZERO(&o); -#endif /* defined(unix) */ - - if (TTYBYTES() == 0) { -#if defined(unix) - FD_SET(tout, &o); - (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, - (struct timeval *) 0); /* wait for TTLOWAT */ -#endif /* defined(unix) */ - } else { - while (TTYBYTES()) { - (void) ttyflush(0); -#if defined(unix) - FD_SET(tout, &o); - (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, - (struct timeval *) 0); /* wait for TTLOWAT */ -#endif /* defined(unix) */ - } - } -} - - void -SetForExit() -{ +static void SetForExit(void) { setconnmode(0); #if defined(TN3270) if (In3270) { @@ -861,9 +643,9 @@ } #else /* defined(TN3270) */ do { - (void)telrcv(); /* Process any incoming data */ + telrcv(); /* Process any incoming data */ EmptyTerminal(); - } while (ring_full_count(&netiring)); /* While there is any */ + } while (ringbuf_full_count(netiring)); /* While there is any */ #endif /* defined(TN3270) */ setcommandmode(); fflush(stdout); @@ -878,16 +660,12 @@ setcommandmode(); } -void -Exit(int returnCode) -{ +void Exit(int returnCode) { SetForExit(); exit(returnCode); } -void -ExitString(const char *string, int returnCode) -{ +void ExitString(const char *string, int returnCode) { SetForExit(); fwrite(string, 1, strlen(string), stderr); exit(returnCode);