diff --git a/appl/telnet/telnetd/authenc.c b/appl/telnet/telnetd/authenc.c index 78beda515..46ee0076c 100644 --- a/appl/telnet/telnetd/authenc.c +++ b/appl/telnet/telnetd/authenc.c @@ -31,57 +31,52 @@ * SUCH DAMAGE. */ -#include -#ifdef SOCKS -#include -#endif +#include "telnetd.h" RCSID("$Id$"); -#if defined(AUTHENTICATION) || defined(ENCRYPTION) -#include "telnetd.h" -#include +#ifdef AUTHENTICATION - int +int net_write(unsigned char *str, int len) { - if (nfrontp + len < netobuf + BUFSIZ) { - memmove(nfrontp, str, len); - nfrontp += len; - return(len); - } - return(0); + if (nfrontp + len < netobuf + BUFSIZ) { + memmove(nfrontp, str, len); + nfrontp += len; + return(len); + } + return(0); } - void +void net_encrypt(void) { -#if defined(ENCRYPTION) - char *s = (nclearto > nbackp) ? nclearto : nbackp; - if (s < nfrontp && encrypt_output) { - (*encrypt_output)((unsigned char *)s, nfrontp - s); - } - nclearto = nfrontp; +#ifdef ENCRYPTION + char *s = (nclearto > nbackp) ? nclearto : nbackp; + if (s < nfrontp && encrypt_output) { + (*encrypt_output)((unsigned char *)s, nfrontp - s); + } + nclearto = nfrontp; #endif } - int +int telnet_spin(void) { - ttloop(); - return(0); + ttloop(); + return(0); } - char * +char * telnet_getenv(char *val) { - extern char *getenv(const char *); - return(getenv(val)); + extern char *getenv(const char *); + return(getenv(val)); } - char * +char * telnet_gets(char *prompt, char *result, int length, int echo) { - return NULL; + return NULL; } #endif diff --git a/appl/telnet/telnetd/defs.h b/appl/telnet/telnetd/defs.h index 80268efee..3f4fc15a9 100644 --- a/appl/telnet/telnetd/defs.h +++ b/appl/telnet/telnetd/defs.h @@ -36,8 +36,9 @@ /* * Telnet server defines */ -#include -#include + +#ifndef __DEFS_H__ +#define __DEFS_H__ #ifndef BSD # define BSD 43 @@ -49,82 +50,6 @@ #define SLC_NAMES #endif -#include -#ifdef TIME_WITH_SYS_TIME -#include -#include -#elif defined(HAVE_SYS_TIME_H) -#include -#else -#include -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif /* HAVE_SYS_RESOURCE_H */ -#ifndef CRAY -#include -#endif /* CRAY */ -#include -#include -#include - -/* including both and in SunOS 4 generates a - lot of warnings */ - -#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4 -#include -#endif -#ifdef HAVE_SYS_FILIO_H -#include -#endif - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#ifndef LOG_DAEMON -#define LOG_DAEMON 0 -#endif -#ifndef LOG_ODELAY -#define LOG_ODELAY 0 -#endif -#include -#include - -#include -#include - -#ifndef _POSIX_VDISABLE -# ifdef VDISABLE -# define _POSIX_VDISABLE VDISABLE -# else -# define _POSIX_VDISABLE ((unsigned char)'\377') -# endif -#endif - - -#ifdef CRAY -# ifdef CRAY1 -# include -# ifndef FD_ZERO -# include -# endif /* FD_ZERO */ -# endif /* CRAY1 */ - -#include -#endif /* CRAY */ - -#ifdef __hpux -#include -#endif - #if !defined(TIOCSCTTY) && defined(TCSETCTTY) # define TIOCSCTTY TCSETCTTY #endif @@ -156,7 +81,7 @@ typedef struct fd_set { int fds_bits[1]; } fd_set; * I/O data buffers defines */ #define NETSLOP 64 -#ifdef CRAY +#ifdef _CRAY #undef BUFSIZ #define BUFSIZ 2048 #endif @@ -169,15 +94,6 @@ typedef struct fd_set { int fds_bits[1]; } fd_set; #define settimer(x) (clocks.x = ++clocks.system) #define sequenceIs(x,y) (clocks.x < clocks.y) -/* - * Linemode support states, in decreasing order of importance - */ -#define REAL_LINEMODE 0x04 -#define KLUDGE_OK 0x03 -#define NO_AUTOKLUDGE 0x02 -#define KLUDGE_LINEMODE 0x01 -#define NO_LINEMODE 0x00 - /* * Structures of information for each special character function. */ @@ -281,3 +197,5 @@ typedef struct { #define his_will_wont_is_changing my_do_dont_is_changing #define his_do_dont_is_changing my_will_wont_is_changing + +#endif /* __DEFS_H__ */ diff --git a/appl/telnet/telnetd/ext.h b/appl/telnet/telnetd/ext.h index a6a261940..8bc76ebeb 100644 --- a/appl/telnet/telnetd/ext.h +++ b/appl/telnet/telnetd/ext.h @@ -35,29 +35,22 @@ /* $Id$ */ +#ifndef __EXT_H__ +#define __EXT_H__ + /* * Telnet server variable declarations */ extern char options[256]; extern char do_dont_resp[256]; extern char will_wont_resp[256]; -extern int linemode; /* linemode on/off */ -#ifdef LINEMODE -extern int uselinemode; /* what linemode to use (on/off) */ -extern int editmode; /* edit modes in use */ -extern int useeditmode; /* edit modes to use */ -extern int alwayslinemode; /* command line option */ -# ifdef KLUDGELINEMODE -extern int lmodetype; /* Client support for linemode */ -# endif /* KLUDGELINEMODE */ -#endif /* LINEMODE */ extern int flowmode; /* current flow control state */ extern int restartany; /* restart output on any character state */ #ifdef DIAGNOSTICS extern int diagnostic; /* telnet diagnostic capabilities */ #endif /* DIAGNOSTICS */ extern int require_otp; -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION extern int auth_level; #endif extern char *new_login; @@ -82,101 +75,84 @@ extern int ourpty, net; extern char *line; extern int SYNCHing; /* we are in TELNET SYNCH mode */ -extern void - _termstat (void), - add_slc (int, int, int), - check_slc (void), - change_slc (int, int, int), - cleanup (int), - clientstat (int, int, int), - copy_termbuf (char *, int), - deferslc (void), - defer_terminit (void), - do_opt_slc (unsigned char *, int), - doeof (void), - dooption (int), - dontoption (int), - edithost (char *, char *), - fatal (int, char *), - fatalperror (int, char *), - get_slc_defaults (void), - init_env (void), - init_termbuf (void), - interrupt (void), - localstat (void), - flowstat (void), - netclear (void), - netflush (void), -#ifdef DIAGNOSTICS - printoption (char *, int), - printdata (char *, char *, int), - printsub (int, unsigned char *, int), -#endif - ptyflush (void), - putchr (int), - putf (char *, char *), - recv_ayt (void), - send_do (int, int), - send_dont (int, int), - send_slc (void), - send_status (void), - send_will (int, int), - send_wont (int, int), - sendbrk (void), - sendsusp (void), - set_termbuf (void), - start_login (char *, int, char *), - start_slc (int), -#if defined(AUTHENTICATION) - start_slave (char *), -#else - start_slave (char *, int, char *), -#endif - suboption (void), - telrcv (void), - ttloop (void), - tty_binaryin (int), - tty_binaryout (int); +int net_write (unsigned char *str, int len); +void net_encrypt (void); +int telnet_spin (void); +char *telnet_getenv (char *val); +char *telnet_gets (char *prompt, char *result, int length, int echo); +void get_slc_defaults (void); +void telrcv (void); +void send_do (int option, int init); +void willoption (int option); +void send_dont (int option, int init); +void wontoption (int option); +void send_will (int option, int init); +void dooption (int option); +void send_wont (int option, int init); +void dontoption (int option); +void suboption (void); +void doclientstat (void); +void send_status (void); +void init_termbuf (void); +void set_termbuf (void); +int spcset (int func, cc_t *valp, cc_t **valpp); +void set_utid (void); +int getpty (int *ptynum); +int tty_isecho (void); +int tty_flowmode (void); +int tty_restartany (void); +void tty_setecho (int on); +int tty_israw (void); +void tty_binaryin (int on); +void tty_binaryout (int on); +int tty_isbinaryin (void); +int tty_isbinaryout (void); +int tty_issofttab (void); +void tty_setsofttab (int on); +int tty_islitecho (void); +void tty_setlitecho (int on); +int tty_iscrnl (void); +void tty_tspeed (int val); +void tty_rspeed (int val); +void getptyslave (void); +int cleanopen (char *line); +void startslave (char *host, int autologin, char *autoname); +void init_env (void); +void start_login (char *host, int autologin, char *name); +void cleanup (int sig); +int main (int argc, char **argv); +void usage (void); +int getterminaltype (char *name); +void _gettermname (void); +int terminaltypeok (char *s); +void doit (struct sockaddr_in *who); +void telnet (int f, int p); +void interrupt (void); +void sendbrk (void); +void sendsusp (void); +void recv_ayt (void); +void doeof (void); +void flowstat (void); +void clientstat (int code, int parm1, int parm2); +void ttloop (void); +int stilloob (int s); +void ptyflush (void); +char *nextitem (char *current); +void netclear (void); +void netflush (void); +void writenet (unsigned char *ptr, int len); +void fatal (int f, char *msg); +void fatalperror (int f, char *msg); +void edithost (char *pat, char *host); +void putstr (char *s); +void putchr (int cc); +void putf (char *cp, char *where); +void printoption (char *fmt, int option); +void printsub (int direction, unsigned char *pointer, int length); +void printdata (char *tag, char *ptr, int cnt); -extern int - end_slc (unsigned char **), - getnpty (void), -#ifndef convex - getpty (int *), -#endif - login_tty (int), - spcset (int, cc_t *, cc_t **), - stilloob (int), - terminit (void), - termstat (void), - tty_flowmode (void), - tty_restartany (void), - tty_isbinaryin (void), - tty_isbinaryout (void), - tty_iscrnl (void), - tty_isecho (void), - tty_isediting (void), - tty_islitecho (void), - tty_isnewmap (void), - tty_israw (void), - tty_issofttab (void), - tty_istrapsig (void), - tty_linemode (void); -extern void - tty_rspeed (int), - tty_setecho (int), - tty_setedit (int), - tty_setlinemode (int), - tty_setlitecho (int), - tty_setsig (int), - tty_setsofttab (int), - tty_tspeed (int), - willoption (int), - wontoption (int), - writenet (unsigned char *, int); - -#if defined(ENCRYPTION) +#ifdef ENCRYPTION extern void (*encrypt_output) (unsigned char *, int); extern int (*decrypt_input) (int); extern char *nclearto; @@ -223,4 +199,6 @@ extern int really_stream; # endif #endif -#define DEFAULT_IM "\r\n\r\n" USE_IM "\r\n\r\n\n\r" +#define DEFAULT_IM "\r\n\r\n" USE_IM "\r\n\r\n\r\n" + +#endif /* __EXT_H__ */ diff --git a/appl/telnet/telnetd/global.c b/appl/telnet/telnetd/global.c index db77a963e..c7fcb7f29 100644 --- a/appl/telnet/telnetd/global.c +++ b/appl/telnet/telnetd/global.c @@ -34,17 +34,10 @@ /* a *lot* of ugly global definitions that really should be removed... */ -#include -#ifdef SOCKS -#include -#endif +#include "telnetd.h" RCSID("$Id$"); -#include "defs.h" -#include "ext.h" - - /* * Telnet server variable declarations */ @@ -52,15 +45,6 @@ char options[256]; char do_dont_resp[256]; char will_wont_resp[256]; int linemode; /* linemode on/off */ -#ifdef LINEMODE -int uselinemode; /* what linemode to use (on/off) */ -int editmode; /* edit modes in use */ -int useeditmode; /* edit modes to use */ -int alwayslinemode; /* command line option */ -# ifdef KLUDGELINEMODE -int lmodetype; /* Client support for linemode */ -# endif /* KLUDGELINEMODE */ -#endif /* LINEMODE */ int flowmode; /* current flow control state */ int restartany; /* restart output on any character state */ #ifdef DIAGNOSTICS @@ -100,3 +84,24 @@ int log_unauth; /* do not print warning if connection is not encrypted */ int no_warn; + +/* + * This function appends data to nfrontp and advances nfrontp. + */ + +int +output_data (const char *format, ...) +{ + va_list args; + size_t remaining, ret; + + va_start(args, format); + remaining = BUFSIZ - (nfrontp - netobuf); + ret = vsnprintf (nfrontp, + remaining, + format, + args); + nfrontp += ret; + va_end(args); + return ret; +} diff --git a/appl/telnet/telnetd/slc.c b/appl/telnet/telnetd/slc.c index de2e20cd5..45e95a277 100644 --- a/appl/telnet/telnetd/slc.c +++ b/appl/telnet/telnetd/slc.c @@ -31,466 +31,27 @@ * SUCH DAMAGE. */ -#include -#ifdef SOCKS -#include -#endif - -RCSID("$Id$"); - #include "telnetd.h" -#ifdef LINEMODE -/* - * local varibles - */ -static unsigned char *def_slcbuf = (unsigned char *)0; -static int def_slclen = 0; -static int slcchange; /* change to slc is requested */ -static unsigned char *slcptr; /* pointer into slc buffer */ -static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */ - -/* - * send_slc - * - * Write out the current special characters to the client. - */ - void -send_slc() -{ - int i; - - /* - * Send out list of triplets of special characters - * to client. We only send info on the characters - * that are currently supported. - */ - for (i = 1; i <= NSLC; i++) { - if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT) - continue; - add_slc((unsigned char)i, slctab[i].current.flag, - slctab[i].current.val); - } - -} /* end of send_slc */ - -/* - * default_slc - * - * Set pty special characters to all the defaults. - */ - void -default_slc() -{ - int i; - - for (i = 1; i <= NSLC; i++) { - slctab[i].current.val = slctab[i].defset.val; - if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE)) - slctab[i].current.flag = SLC_NOSUPPORT; - else - slctab[i].current.flag = slctab[i].defset.flag; - if (slctab[i].sptr) { - *(slctab[i].sptr) = slctab[i].defset.val; - } - } - slcchange = 1; - -} /* end of default_slc */ -#endif /* LINEMODE */ +RCSID("$Id$"); /* * get_slc_defaults * * Initialize the slc mapping table. */ - void +void get_slc_defaults(void) { - int i; - - init_termbuf(); - - for (i = 1; i <= NSLC; i++) { - slctab[i].defset.flag = - spcset(i, &slctab[i].defset.val, &slctab[i].sptr); - slctab[i].current.flag = SLC_NOSUPPORT; - slctab[i].current.val = 0; - } - -} /* end of get_slc_defaults */ - -#ifdef LINEMODE -/* - * add_slc - * - * Add an slc triplet to the slc buffer. - */ - void -add_slc(func, flag, val) - char func, flag; - cc_t val; -{ - - if ((*slcptr++ = (unsigned char)func) == 0xff) - *slcptr++ = 0xff; - - if ((*slcptr++ = (unsigned char)flag) == 0xff) - *slcptr++ = 0xff; - - if ((*slcptr++ = (unsigned char)val) == 0xff) - *slcptr++ = 0xff; - -} /* end of add_slc */ - -/* - * start_slc - * - * Get ready to process incoming slc's and respond to them. - * - * The parameter getit is non-zero if it is necessary to grab a copy - * of the terminal control structures. - */ - void -start_slc(getit) - int getit; -{ - - slcchange = 0; - if (getit) - init_termbuf(); - snprintf((char *)slcbuf, sizeof(slcbuf), - "%c%c%c%c", - IAC, SB, TELOPT_LINEMODE, LM_SLC); - slcptr = slcbuf + 4; - -} /* end of start_slc */ - -/* - * end_slc - * - * Finish up the slc negotiation. If something to send, then send it. - */ - int -end_slc(bufp) - unsigned char **bufp; -{ - int len; - void netflush(); - - /* - * If a change has occured, store the new terminal control - * structures back to the terminal driver. - */ - if (slcchange) { - set_termbuf(); - } - - /* - * If the pty state has not yet been fully processed and there is a - * deferred slc request from the client, then do not send any - * sort of slc negotiation now. We will respond to the client's - * request very soon. - */ - if (def_slcbuf && (terminit() == 0)) { - return(0); - } - - if (slcptr > (slcbuf + 4)) { - if (bufp) { - *bufp = &slcbuf[4]; - return(slcptr - slcbuf - 4); - } else { - snprintf((char *)slcptr, sizeof(slcbuf) - (slcptr - slcbuf), - "%c%c", IAC, SE); - slcptr += 2; - len = slcptr - slcbuf; - writenet(slcbuf, len); - netflush(); /* force it out immediately */ - DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2);); - } - } - return (0); - -} /* end of end_slc */ - -/* - * process_slc - * - * Figure out what to do about the client's slc - */ - void -process_slc(func, flag, val) - unsigned char func, flag; - cc_t val; -{ - int hislevel, mylevel, ack; - - /* - * Ensure that we know something about this function - */ - if (func > NSLC) { - add_slc(func, SLC_NOSUPPORT, 0); - return; - } - - /* - * Process the special case requests of 0 SLC_DEFAULT 0 - * and 0 SLC_VARIABLE 0. Be a little forgiving here, don't - * worry about whether the value is actually 0 or not. - */ - if (func == 0) { - if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) { - default_slc(); - send_slc(); - } else if (flag == SLC_VARIABLE) { - send_slc(); - } - return; - } - - /* - * Appears to be a function that we know something about. So - * get on with it and see what we know. - */ - - hislevel = flag & SLC_LEVELBITS; - mylevel = slctab[func].current.flag & SLC_LEVELBITS; - ack = flag & SLC_ACK; - /* - * ignore the command if: - * the function value and level are the same as what we already have; - * or the level is the same and the ack bit is set - */ - if (hislevel == mylevel && (val == slctab[func].current.val || ack)) { - return; - } else if (ack) { - /* - * If we get here, we got an ack, but the levels don't match. - * This shouldn't happen. If it does, it is probably because - * we have sent two requests to set a variable without getting - * a response between them, and this is the first response. - * So, ignore it, and wait for the next response. - */ - return; - } else { - change_slc(func, flag, val); - } - -} /* end of process_slc */ - -/* - * change_slc - * - * Process a request to change one of our special characters. - * Compare client's request with what we are capable of supporting. - */ - void -change_slc(func, flag, val) - char func, flag; - cc_t val; -{ - int hislevel, mylevel; - - hislevel = flag & SLC_LEVELBITS; - mylevel = slctab[func].defset.flag & SLC_LEVELBITS; - /* - * If client is setting a function to NOSUPPORT - * or DEFAULT, then we can easily and directly - * accomodate the request. - */ - if (hislevel == SLC_NOSUPPORT) { - slctab[func].current.flag = flag; - slctab[func].current.val = (cc_t)_POSIX_VDISABLE; - flag |= SLC_ACK; - add_slc(func, flag, val); - return; - } - if (hislevel == SLC_DEFAULT) { - /* - * Special case here. If client tells us to use - * the default on a function we don't support, then - * return NOSUPPORT instead of what we may have as a - * default level of DEFAULT. - */ - if (mylevel == SLC_DEFAULT) { - slctab[func].current.flag = SLC_NOSUPPORT; - } else { - slctab[func].current.flag = slctab[func].defset.flag; - } - slctab[func].current.val = slctab[func].defset.val; - add_slc(func, slctab[func].current.flag, - slctab[func].current.val); - return; - } - - /* - * Client wants us to change to a new value or he - * is telling us that he can't change to our value. - * Some of the slc's we support and can change, - * some we do support but can't change, - * and others we don't support at all. - * If we can change it then we have a pointer to - * the place to put the new value, so change it, - * otherwise, continue the negotiation. - */ - if (slctab[func].sptr) { - /* - * We can change this one. - */ - slctab[func].current.val = val; - *(slctab[func].sptr) = val; - slctab[func].current.flag = flag; - flag |= SLC_ACK; - slcchange = 1; - add_slc(func, flag, val); - } else { - /* - * It is not possible for us to support this - * request as he asks. - * - * If our level is DEFAULT, then just ack whatever was - * sent. - * - * If he can't change and we can't change, - * then degenerate to NOSUPPORT. - * - * Otherwise we send our level back to him, (CANTCHANGE - * or NOSUPPORT) and if CANTCHANGE, send - * our value as well. - */ - if (mylevel == SLC_DEFAULT) { - slctab[func].current.flag = flag; - slctab[func].current.val = val; - flag |= SLC_ACK; - } else if (hislevel == SLC_CANTCHANGE && - mylevel == SLC_CANTCHANGE) { - flag &= ~SLC_LEVELBITS; - flag |= SLC_NOSUPPORT; - slctab[func].current.flag = flag; - } else { - flag &= ~SLC_LEVELBITS; - flag |= mylevel; - slctab[func].current.flag = flag; - if (mylevel == SLC_CANTCHANGE) { - slctab[func].current.val = - slctab[func].defset.val; - val = slctab[func].current.val; - } - } - add_slc(func, flag, val); - } - -} /* end of change_slc */ - -#if VEOF == VMIN -cc_t oldeofc = '\004'; -#endif - -/* - * check_slc - * - * Check the special characters in use and notify the client if any have - * changed. Only those characters that are capable of being changed are - * likely to have changed. If a local change occurs, kick the support level - * and flags up to the defaults. - */ - void -check_slc() -{ - int i; - - for (i = 1; i <= NSLC; i++) { -#if VEOF == VMIN - /* - * In a perfect world this would be a neat little - * function. But in this world, we should not notify - * client of changes to the VEOF char when - * ICANON is off, because it is not representing - * a special character. - */ - if (i == SLC_EOF) { - if (!tty_isediting()) - continue; - else if (slctab[i].sptr) - oldeofc = *(slctab[i].sptr); - } -#endif - if (slctab[i].sptr && - (*(slctab[i].sptr) != slctab[i].current.val)) { - slctab[i].current.val = *(slctab[i].sptr); - if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE) - slctab[i].current.flag = SLC_NOSUPPORT; - else - slctab[i].current.flag = slctab[i].defset.flag; - add_slc((unsigned char)i, slctab[i].current.flag, - slctab[i].current.val); - } - } -} /* check_slc */ - -/* - * do_opt_slc - * - * Process an slc option buffer. Defer processing of incoming slc's - * until after the terminal state has been processed. Save the first slc - * request that comes along, but discard all others. - * - * ptr points to the beginning of the buffer, len is the length. - */ - void -do_opt_slc(ptr, len) - unsigned char *ptr; - int len; -{ - unsigned char func, flag; - cc_t val; - unsigned char *end = ptr + len; - - if (terminit()) { /* go ahead */ - while (ptr < end) { - func = *ptr++; - if (ptr >= end) break; - flag = *ptr++; - if (ptr >= end) break; - val = (cc_t)*ptr++; - - process_slc(func, flag, val); - - } - } else { - /* - * save this slc buffer if it is the first, otherwise dump - * it. - */ - if (def_slcbuf == (unsigned char *)0) { - def_slclen = len; - def_slcbuf = (unsigned char *)malloc((unsigned)len); - if (def_slcbuf == (unsigned char *)0) - return; /* too bad */ - memmove(def_slcbuf, ptr, len); - } - } - -} /* end of do_opt_slc */ - -/* - * deferslc - * - * Do slc stuff that was deferred. - */ - void -deferslc() -{ - if (def_slcbuf) { - start_slc(1); - do_opt_slc(def_slcbuf, def_slclen); - end_slc(0); - free(def_slcbuf); - def_slcbuf = (unsigned char *)0; - def_slclen = 0; - } - -} /* end of deferslc */ - -#endif /* LINEMODE */ + int i; + + init_termbuf(); + + for (i = 1; i <= NSLC; i++) { + slctab[i].defset.flag = + spcset(i, &slctab[i].defset.val, &slctab[i].sptr); + slctab[i].current.flag = SLC_NOSUPPORT; + slctab[i].current.val = 0; + } + +} diff --git a/appl/telnet/telnetd/state.c b/appl/telnet/telnetd/state.c index a416283c4..7414394e5 100644 --- a/appl/telnet/telnetd/state.c +++ b/appl/telnet/telnetd/state.c @@ -31,18 +31,10 @@ * SUCH DAMAGE. */ -#include -#ifdef SOCKS -#include -#endif +#include "telnetd.h" RCSID("$Id$"); -#include "telnetd.h" -#if defined(AUTHENTICATION) -#include -#endif - unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; unsigned char will[] = { IAC, WILL, '%', 'c', 0 }; @@ -58,8 +50,8 @@ unsigned char subbuffer[2048], *subpointer= subbuffer, *subend= subbuffer; #define SB_CLEAR() subpointer = subbuffer #define SB_TERM() { subend = subpointer; SB_CLEAR(); } #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ - *subpointer++ = (c); \ - } + *subpointer++ = (c); \ + } #define SB_GET() ((*subpointer++)&0xff) #define SB_EOF() (subpointer >= subend) #define SB_LEN() (subend - subpointer) @@ -84,282 +76,270 @@ unsigned char *subsave; #define TS_DO 7 /* do -''- */ #define TS_DONT 8 /* dont -''- */ - void +void telrcv(void) { - int c; - static int state = TS_DATA; + int c; + static int state = TS_DATA; - while (ncc > 0) { - if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) - break; - c = *netip++ & 0377, ncc--; -#if defined(ENCRYPTION) + while (ncc > 0) { + if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) + break; + c = *netip++ & 0377, ncc--; +#ifdef ENCRYPTION + if (decrypt_input) + c = (*decrypt_input)(c); +#endif + switch (state) { + + case TS_CR: + state = TS_DATA; + /* Strip off \n or \0 after a \r */ + if ((c == 0) || (c == '\n')) { + break; + } + /* FALL THROUGH */ + + case TS_DATA: + if (c == IAC) { + state = TS_IAC; + break; + } + /* + * We now map \r\n ==> \r for pragmatic reasons. + * Many client implementations send \r\n when + * the user hits the CarriageReturn key. + * + * We USED to map \r\n ==> \n, since \r\n says + * that we want to be in column 1 of the next + * printable line, and \n is the standard + * unix way of saying that (\r is only good + * if CRMOD is set, which it normally is). + */ + if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { + int nc = *netip; +#ifdef ENCRYPTION if (decrypt_input) - c = (*decrypt_input)(c); + nc = (*decrypt_input)(nc & 0xff); #endif - switch (state) { - - case TS_CR: - state = TS_DATA; - /* Strip off \n or \0 after a \r */ - if ((c == 0) || (c == '\n')) { - break; - } - /* FALL THROUGH */ - - case TS_DATA: - if (c == IAC) { - state = TS_IAC; - break; - } - /* - * We now map \r\n ==> \r for pragmatic reasons. - * Many client implementations send \r\n when - * the user hits the CarriageReturn key. - * - * We USED to map \r\n ==> \n, since \r\n says - * that we want to be in column 1 of the next - * printable line, and \n is the standard - * unix way of saying that (\r is only good - * if CRMOD is set, which it normally is). - */ - if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { - int nc = *netip; -#if defined(ENCRYPTION) - if (decrypt_input) - nc = (*decrypt_input)(nc & 0xff); + { +#ifdef ENCRYPTION + if (decrypt_input) + (void)(*decrypt_input)(-1); #endif -#ifdef LINEMODE - /* - * If we are operating in linemode, - * convert to local end-of-line. - */ - if (linemode && (ncc > 0) && (('\n' == nc) || - ((0 == nc) && tty_iscrnl())) ) { - netip++; ncc--; - c = '\n'; - } else -#endif - { -#if defined(ENCRYPTION) - if (decrypt_input) - (void)(*decrypt_input)(-1); -#endif - state = TS_CR; - } - } - *pfrontp++ = c; - break; - - case TS_IAC: -gotiac: switch (c) { - - /* - * Send the process on the pty side an - * interrupt. Do this with a NULL or - * interrupt char; depending on the tty mode. - */ - case IP: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - interrupt(); - break; - - case BREAK: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - sendbrk(); - break; - - /* - * Are You There? - */ - case AYT: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - recv_ayt(); - break; - - /* - * Abort Output - */ - case AO: - { - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - - if (slctab[SLC_AO].sptr && - *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { - *pfrontp++ = - (unsigned char)*slctab[SLC_AO].sptr; - } - - netclear(); /* clear buffer back */ - *nfrontp++ = IAC; - *nfrontp++ = DM; - neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - break; - } - - /* - * Erase Character and - * Erase Line - */ - case EC: - case EL: - { - cc_t ch; - - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - if (c == EC) - ch = *slctab[SLC_EC].sptr; - else - ch = *slctab[SLC_EL].sptr; - if (ch != (cc_t)(_POSIX_VDISABLE)) - *pfrontp++ = (unsigned char)ch; - break; - } - - /* - * Check for urgent data... - */ - case DM: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - SYNCHing = stilloob(net); - settimer(gotDM); - break; - - - /* - * Begin option subnegotiation... - */ - case SB: - state = TS_SB; - SB_CLEAR(); - continue; - - case WILL: - state = TS_WILL; - continue; - - case WONT: - state = TS_WONT; - continue; - - case DO: - state = TS_DO; - continue; - - case DONT: - state = TS_DONT; - continue; - case EOR: - if (his_state_is_will(TELOPT_EOR)) - doeof(); - break; - - /* - * Handle RFC 10xx Telnet linemode option additions - * to command stream (EOF, SUSP, ABORT). - */ - case xEOF: - doeof(); - break; - - case SUSP: - sendsusp(); - break; - - case ABORT: - sendbrk(); - break; - - case IAC: - *pfrontp++ = c; - break; - } - state = TS_DATA; - break; - - case TS_SB: - if (c == IAC) { - state = TS_SE; - } else { - SB_ACCUM(c); - } - break; - - case TS_SE: - if (c != SE) { - if (c != IAC) { - /* - * bad form of suboption negotiation. - * handle it in such a way as to avoid - * damage to local state. Parse - * suboption buffer found so far, - * then treat remaining stream as - * another command sequence. - */ - - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(c); - subpointer -= 2; - - SB_TERM(); - suboption(); - state = TS_IAC; - goto gotiac; - } - SB_ACCUM(c); - state = TS_SB; - } else { - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(SE); - subpointer -= 2; - - SB_TERM(); - suboption(); /* handle sub-option */ - state = TS_DATA; - } - break; - - case TS_WILL: - willoption(c); - state = TS_DATA; - continue; - - case TS_WONT: - wontoption(c); - state = TS_DATA; - continue; - - case TS_DO: - dooption(c); - state = TS_DATA; - continue; - - case TS_DONT: - dontoption(c); - state = TS_DATA; - continue; - - default: - syslog(LOG_ERR, "telnetd: panic state=%d\n", state); - printf("telnetd: panic state=%d\n", state); - exit(1); + state = TS_CR; } + } + *pfrontp++ = c; + break; + + case TS_IAC: + gotiac: switch (c) { + + /* + * Send the process on the pty side an + * interrupt. Do this with a NULL or + * interrupt char; depending on the tty mode. + */ + case IP: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + interrupt(); + break; + + case BREAK: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + sendbrk(); + break; + + /* + * Are You There? + */ + case AYT: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + recv_ayt(); + break; + + /* + * Abort Output + */ + case AO: + { + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + + if (slctab[SLC_AO].sptr && + *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { + *pfrontp++ = + (unsigned char)*slctab[SLC_AO].sptr; + } + + netclear(); /* clear buffer back */ + output_data ("%c%c", IAC, DM); + neturg = nfrontp-1; /* off by one XXX */ + DIAG(TD_OPTIONS, + printoption("td: send IAC", DM)); + break; + } + + /* + * Erase Character and + * Erase Line + */ + case EC: + case EL: + { + cc_t ch; + + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + if (c == EC) + ch = *slctab[SLC_EC].sptr; + else + ch = *slctab[SLC_EL].sptr; + if (ch != (cc_t)(_POSIX_VDISABLE)) + *pfrontp++ = (unsigned char)ch; + break; + } + + /* + * Check for urgent data... + */ + case DM: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + SYNCHing = stilloob(net); + settimer(gotDM); + break; + + + /* + * Begin option subnegotiation... + */ + case SB: + state = TS_SB; + SB_CLEAR(); + continue; + + case WILL: + state = TS_WILL; + continue; + + case WONT: + state = TS_WONT; + continue; + + case DO: + state = TS_DO; + continue; + + case DONT: + state = TS_DONT; + continue; + case EOR: + if (his_state_is_will(TELOPT_EOR)) + doeof(); + break; + + /* + * Handle RFC 10xx Telnet linemode option additions + * to command stream (EOF, SUSP, ABORT). + */ + case xEOF: + doeof(); + break; + + case SUSP: + sendsusp(); + break; + + case ABORT: + sendbrk(); + break; + + case IAC: + *pfrontp++ = c; + break; } + state = TS_DATA; + break; + + case TS_SB: + if (c == IAC) { + state = TS_SE; + } else { + SB_ACCUM(c); + } + break; + + case TS_SE: + if (c != SE) { + if (c != IAC) { + /* + * bad form of suboption negotiation. + * handle it in such a way as to avoid + * damage to local state. Parse + * suboption buffer found so far, + * then treat remaining stream as + * another command sequence. + */ + + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(c); + subpointer -= 2; + + SB_TERM(); + suboption(); + state = TS_IAC; + goto gotiac; + } + SB_ACCUM(c); + state = TS_SB; + } else { + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(SE); + subpointer -= 2; + + SB_TERM(); + suboption(); /* handle sub-option */ + state = TS_DATA; + } + break; + + case TS_WILL: + willoption(c); + state = TS_DATA; + continue; + + case TS_WONT: + wontoption(c); + state = TS_DATA; + continue; + + case TS_DO: + dooption(c); + state = TS_DATA; + continue; + + case TS_DONT: + dontoption(c); + state = TS_DATA; + continue; + + default: + syslog(LOG_ERR, "telnetd: panic state=%d\n", state); + printf("telnetd: panic state=%d\n", state); + exit(1); + } + } } /* end of telrcv */ /* @@ -418,319 +398,246 @@ gotiac: switch (c) { * is complete. * */ - void +void send_do(int option, int init) { - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || - his_want_state_is_will(option)) - return; - /* - * Special case for TELOPT_TM: We send a DO, but pretend - * that we sent a DONT, so that we can send more DOs if - * we want to. - */ - if (option == TELOPT_TM) - set_his_want_state_wont(option); - else - set_his_want_state_will(option); - do_dont_resp[option]++; - } - snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - (char *)doopt, option); - nfrontp += sizeof (dont) - 2; + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || + his_want_state_is_will(option)) + return; + /* + * Special case for TELOPT_TM: We send a DO, but pretend + * that we sent a DONT, so that we can send more DOs if + * we want to. + */ + if (option == TELOPT_TM) + set_his_want_state_wont(option); + else + set_his_want_state_will(option); + do_dont_resp[option]++; + } + output_data((const char *)doopt, option); - DIAG(TD_OPTIONS, printoption("td: send do", option)); + DIAG(TD_OPTIONS, printoption("td: send do", option)); } #ifdef AUTHENTICATION extern void auth_request(void); #endif -#ifdef LINEMODE -extern void doclientstat(); -#endif #ifdef ENCRYPTION extern void encrypt_send_support(); #endif - void +void willoption(int option) { - int changeok = 0; - void (*func)() = 0; + int changeok = 0; + void (*func)() = 0; - /* - * process input from peer. - */ + /* + * process input from peer. + */ - DIAG(TD_OPTIONS, printoption("td: recv will", option)); + DIAG(TD_OPTIONS, printoption("td: recv will", option)); - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_will(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_wont(option)) { - switch (option) { + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_will(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_wont(option)) { + switch (option) { - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(1); - set_termbuf(); - changeok++; - break; + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(1); + set_termbuf(); + changeok++; + break; - case TELOPT_ECHO: - /* - * See comments below for more info. - */ - not42 = 0; /* looks like a 4.2 system */ - break; + case TELOPT_ECHO: + /* + * See comments below for more info. + */ + not42 = 0; /* looks like a 4.2 system */ + break; - case TELOPT_TM: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * This telnetd implementation does not really - * support timing marks, it just uses them to - * support the kludge linemode stuff. If we - * receive a will or wont TM in response to our - * do TM request that may have been sent to - * determine kludge linemode support, process - * it, otherwise TM should get a negative - * response back. - */ - /* - * Handle the linemode kludge stuff. - * If we are not currently supporting any - * linemode at all, then we assume that this - * is the client telling us to use kludge - * linemode in response to our query. Set the - * linemode type that is to be supported, note - * that the client wishes to use linemode, and - * eat the will TM as though it never arrived. - */ - if (lmodetype < KLUDGE_LINEMODE) { - lmodetype = KLUDGE_LINEMODE; - clientstat(TELOPT_LINEMODE, WILL, 0); - send_wont(TELOPT_SGA, 1); - } else if (lmodetype == NO_AUTOKLUDGE) { - lmodetype = KLUDGE_OK; - } -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - /* - * We never respond to a WILL TM, and - * we leave the state WONT. - */ - return; + case TELOPT_TM: + /* + * We never respond to a WILL TM, and + * we leave the state WONT. + */ + return; - case TELOPT_LFLOW: - /* - * If we are going to support flow control - * option, then don't worry peer that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_DEFAULT; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; - case TELOPT_TTYPE: - case TELOPT_SGA: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_XDISPLOC: - case TELOPT_NEW_ENVIRON: - case TELOPT_OLD_ENVIRON: - changeok++; - break; + case TELOPT_LFLOW: + /* + * If we are going to support flow control + * option, then don't worry peer that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_DEFAULT; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; + case TELOPT_TTYPE: + case TELOPT_SGA: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_XDISPLOC: + case TELOPT_NEW_ENVIRON: + case TELOPT_OLD_ENVIRON: + changeok++; + break; -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * Note client's desire to use linemode. - */ - lmodetype = REAL_LINEMODE; -# endif /* KLUDGELINEMODE */ - func = doclientstat; - changeok++; - break; -#endif /* LINEMODE */ #ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - changeok++; - break; + case TELOPT_AUTHENTICATION: + func = auth_request; + changeok++; + break; #endif #ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - changeok++; - break; + case TELOPT_ENCRYPT: + func = encrypt_send_support; + changeok++; + break; #endif - default: - break; - } - if (changeok) { - set_his_want_state_will(option); - send_do(option, 0); - } else { - do_dont_resp[option]++; - send_dont(option, 0); - } + default: + break; + } + if (changeok) { + set_his_want_state_will(option); + send_do(option, 0); } else { + do_dont_resp[option]++; + send_dont(option, 0); + } + } else { + /* + * Option processing that should happen when + * we receive conformation of a change in + * state that we had requested. + */ + switch (option) { + case TELOPT_ECHO: + not42 = 0; /* looks like a 4.2 system */ /* - * Option processing that should happen when - * we receive conformation of a change in - * state that we had requested. + * Egads, he responded "WILL ECHO". Turn + * it off right now! */ - switch (option) { - case TELOPT_ECHO: - not42 = 0; /* looks like a 4.2 system */ - /* - * Egads, he responded "WILL ECHO". Turn - * it off right now! - */ - send_dont(option, 1); - /* - * "WILL ECHO". Kludge upon kludge! - * A 4.2 client is now echoing user input at - * the tty. This is probably undesireable and - * it should be stopped. The client will - * respond WONT TM to the DO TM that we send to - * check for kludge linemode. When the WONT TM - * arrives, linemode will be turned off and a - * change propogated to the pty. This change - * will cause us to process the new pty state - * in localstat(), which will notice that - * linemode is off and send a WILL ECHO - * so that we are properly in character mode and - * all is well. - */ - break; -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * Note client's desire to use linemode. - */ - lmodetype = REAL_LINEMODE; -# endif /* KLUDGELINEMODE */ - func = doclientstat; - break; -#endif /* LINEMODE */ + send_dont(option, 1); + /* + * "WILL ECHO". Kludge upon kludge! + * A 4.2 client is now echoing user input at + * the tty. This is probably undesireable and + * it should be stopped. The client will + * respond WONT TM to the DO TM that we send to + * check for kludge linemode. When the WONT TM + * arrives, linemode will be turned off and a + * change propogated to the pty. This change + * will cause us to process the new pty state + * in localstat(), which will notice that + * linemode is off and send a WILL ECHO + * so that we are properly in character mode and + * all is well. + */ + break; #ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - break; + case TELOPT_AUTHENTICATION: + func = auth_request; + break; #endif #ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - break; + case TELOPT_ENCRYPT: + func = encrypt_send_support; + break; #endif - case TELOPT_LFLOW: - func = flowstat; - break; - } + case TELOPT_LFLOW: + func = flowstat; + break; } } - set_his_state_will(option); - if (func) - (*func)(); + } + set_his_state_will(option); + if (func) + (*func)(); } /* end of willoption */ - void +void send_dont(int option, int init) { - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || - his_want_state_is_wont(option)) - return; - set_his_want_state_wont(option); - do_dont_resp[option]++; - } - snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - (char *)dont, option); - nfrontp += sizeof (doopt) - 2; + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || + his_want_state_is_wont(option)) + return; + set_his_want_state_wont(option); + do_dont_resp[option]++; + } + output_data((const char *)dont, option); - DIAG(TD_OPTIONS, printoption("td: send dont", option)); + DIAG(TD_OPTIONS, printoption("td: send dont", option)); } - void +void wontoption(int option) { - /* - * Process client input. + /* + * Process client input. */ - DIAG(TD_OPTIONS, printoption("td: recv wont", option)); + DIAG(TD_OPTIONS, printoption("td: recv wont", option)); - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_wont(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_will(option)) { - /* it is always ok to change to negative state */ - switch (option) { - case TELOPT_ECHO: - not42 = 1; /* doesn't seem to be a 4.2 system */ - break; + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_wont(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_will(option)) { + /* it is always ok to change to negative state */ + switch (option) { + case TELOPT_ECHO: + not42 = 1; /* doesn't seem to be a 4.2 system */ + break; - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(0); - set_termbuf(); - break; + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(0); + set_termbuf(); + break; -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * If real linemode is supported, then client is - * asking to turn linemode off. - */ - if (lmodetype != REAL_LINEMODE) - break; -# endif /* KLUDGELINEMODE */ - clientstat(TELOPT_LINEMODE, WONT, 0); - break; -#endif /* LINEMODE */ + case TELOPT_TM: + /* + * If we get a WONT TM, and had sent a DO TM, + * don't respond with a DONT TM, just leave it + * as is. Short circut the state machine to + * achive this. + */ + set_his_want_state_wont(TELOPT_TM); + return; - case TELOPT_TM: - /* - * If we get a WONT TM, and had sent a DO TM, - * don't respond with a DONT TM, just leave it - * as is. Short circut the state machine to - * achive this. - */ - set_his_want_state_wont(TELOPT_TM); - return; + case TELOPT_LFLOW: + /* + * If we are not going to support flow control + * option, then let peer know that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; + break; - case TELOPT_LFLOW: - /* - * If we are not going to support flow control - * option, then let peer know that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; - break; - -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; #endif /* @@ -741,77 +648,66 @@ wontoption(int option) * to the sub-negotiation, (by updating the timers) * so that we'll break out of the loop. */ - case TELOPT_TTYPE: - settimer(ttypesubopt); - break; + case TELOPT_TTYPE: + settimer(ttypesubopt); + break; - case TELOPT_TSPEED: - settimer(tspeedsubopt); - break; + case TELOPT_TSPEED: + settimer(tspeedsubopt); + break; - case TELOPT_XDISPLOC: - settimer(xdisplocsubopt); - break; + case TELOPT_XDISPLOC: + settimer(xdisplocsubopt); + break; - case TELOPT_OLD_ENVIRON: - settimer(oenvironsubopt); - break; + case TELOPT_OLD_ENVIRON: + settimer(oenvironsubopt); + break; - case TELOPT_NEW_ENVIRON: - settimer(environsubopt); - break; + case TELOPT_NEW_ENVIRON: + settimer(environsubopt); + break; - default: - break; - } - set_his_want_state_wont(option); - if (his_state_is_will(option)) - send_dont(option, 0); - } else { - switch (option) { - case TELOPT_TM: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - if (lmodetype < NO_AUTOKLUDGE) { - lmodetype = NO_LINEMODE; - clientstat(TELOPT_LINEMODE, WONT, 0); - send_will(TELOPT_SGA, 1); - send_will(TELOPT_ECHO, 1); - } -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - break; + default: + break; + } + set_his_want_state_wont(option); + if (his_state_is_will(option)) + send_dont(option, 0); + } else { + switch (option) { + case TELOPT_TM: + break; -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; #endif - default: - break; - } + default: + break; } } - set_his_state_wont(option); + } + set_his_state_wont(option); } /* end of wontoption */ - void +void send_will(int option, int init) { - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| - my_want_state_is_will(option)) - return; - set_my_want_state_will(option); - will_wont_resp[option]++; - } - snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - (char *)will, option); - nfrontp += sizeof (doopt) - 2; + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| + my_want_state_is_will(option)) + return; + set_my_want_state_will(option); + will_wont_resp[option]++; + } + output_data ((const char *)will, option); - DIAG(TD_OPTIONS, printoption("td: send will", option)); + DIAG(TD_OPTIONS, printoption("td: send will", option)); } -#if !defined(LINEMODE) || !defined(KLUDGELINEMODE) /* * When we get a DONT SGA, we will try once to turn it * back on. If the other side responds DONT SGA, we @@ -820,236 +716,169 @@ send_will(int option, int init) * we'll keep them in char-at-a-time mode. */ int turn_on_sga = 0; -#endif - void +void dooption(int option) { - int changeok = 0; + int changeok = 0; - /* - * Process client input. - */ + /* + * Process client input. + */ - DIAG(TD_OPTIONS, printoption("td: recv do", option)); + DIAG(TD_OPTIONS, printoption("td: recv do", option)); - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_will(option)) - will_wont_resp[option]--; - } - if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { - switch (option) { - case TELOPT_ECHO: -#ifdef LINEMODE -# ifdef KLUDGELINEMODE - if (lmodetype == NO_LINEMODE) -# else - if (his_state_is_wont(TELOPT_LINEMODE)) -# endif + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_will(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { + switch (option) { + case TELOPT_ECHO: + { + init_termbuf(); + tty_setecho(1); + set_termbuf(); + } + changeok++; + break; + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(1); + set_termbuf(); + changeok++; + break; + + case TELOPT_SGA: + turn_on_sga = 0; + changeok++; + break; + + case TELOPT_STATUS: + changeok++; + break; + + case TELOPT_TM: + /* + * Special case for TM. We send a WILL, but + * pretend we sent a WONT. + */ + send_will(option, 0); + set_my_want_state_wont(option); + set_my_state_wont(option); + return; + + case TELOPT_LOGOUT: + /* + * When we get a LOGOUT option, respond + * with a WILL LOGOUT, make sure that + * it gets written out to the network, + * and then just go away... + */ + set_my_want_state_will(TELOPT_LOGOUT); + send_will(TELOPT_LOGOUT, 0); + set_my_state_will(TELOPT_LOGOUT); + netflush(); + cleanup(0); + /* NOT REACHED */ + break; + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + changeok++; + break; #endif - { - init_termbuf(); - tty_setecho(1); - set_termbuf(); - } - changeok++; - break; - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(1); - set_termbuf(); - changeok++; - break; - - case TELOPT_SGA: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * If kludge linemode is in use, then we must - * process an incoming do SGA for linemode - * purposes. - */ - if (lmodetype == KLUDGE_LINEMODE) { - /* - * Receipt of "do SGA" in kludge - * linemode is the peer asking us to - * turn off linemode. Make note of - * the request. - */ - clientstat(TELOPT_LINEMODE, WONT, 0); - /* - * If linemode did not get turned off - * then don't tell peer that we did. - * Breaking here forces a wont SGA to - * be returned. - */ - if (linemode) - break; - } -#else - turn_on_sga = 0; -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - changeok++; - break; - - case TELOPT_STATUS: - changeok++; - break; - - case TELOPT_TM: - /* - * Special case for TM. We send a WILL, but - * pretend we sent a WONT. - */ - send_will(option, 0); - set_my_want_state_wont(option); - set_my_state_wont(option); - return; - - case TELOPT_LOGOUT: - /* - * When we get a LOGOUT option, respond - * with a WILL LOGOUT, make sure that - * it gets written out to the network, - * and then just go away... - */ - set_my_want_state_will(TELOPT_LOGOUT); - send_will(TELOPT_LOGOUT, 0); - set_my_state_will(TELOPT_LOGOUT); - netflush(); - cleanup(0); - /* NOT REACHED */ - break; - -#if defined(ENCRYPTION) - case TELOPT_ENCRYPT: - changeok++; - break; -#endif - case TELOPT_LINEMODE: - case TELOPT_TTYPE: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_LFLOW: - case TELOPT_XDISPLOC: + case TELOPT_LINEMODE: + case TELOPT_TTYPE: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_LFLOW: + case TELOPT_XDISPLOC: #ifdef TELOPT_ENVIRON - case TELOPT_NEW_ENVIRON: + case TELOPT_NEW_ENVIRON: #endif - case TELOPT_OLD_ENVIRON: - default: - break; - } - if (changeok) { - set_my_want_state_will(option); - send_will(option, 0); - } else { - will_wont_resp[option]++; - send_wont(option, 0); - } + case TELOPT_OLD_ENVIRON: + default: + break; } - set_my_state_will(option); + if (changeok) { + set_my_want_state_will(option); + send_will(option, 0); + } else { + will_wont_resp[option]++; + send_wont(option, 0); + } + } + set_my_state_will(option); } /* end of dooption */ - void +void send_wont(int option, int init) { - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || - my_want_state_is_wont(option)) - return; - set_my_want_state_wont(option); - will_wont_resp[option]++; - } - snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - (char *)wont, option); - nfrontp += sizeof (wont) - 2; + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || + my_want_state_is_wont(option)) + return; + set_my_want_state_wont(option); + will_wont_resp[option]++; + } + output_data ((const char *)wont, option); - DIAG(TD_OPTIONS, printoption("td: send wont", option)); + DIAG(TD_OPTIONS, printoption("td: send wont", option)); } - void +void dontoption(int option) { - /* - * Process client input. + /* + * Process client input. */ - DIAG(TD_OPTIONS, printoption("td: recv dont", option)); + DIAG(TD_OPTIONS, printoption("td: recv dont", option)); - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_wont(option)) - will_wont_resp[option]--; + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_wont(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { + switch (option) { + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(0); + set_termbuf(); + break; + + case TELOPT_ECHO: /* we should stop echoing */ + { + init_termbuf(); + tty_setecho(0); + set_termbuf(); + } + break; + + case TELOPT_SGA: + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + set_my_state_wont(option); + if (turn_on_sga ^= 1) + send_will(option, 1); + return; + + default: + break; } - if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { - switch (option) { - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(0); - set_termbuf(); - break; - case TELOPT_ECHO: /* we should stop echoing */ -#ifdef LINEMODE -# ifdef KLUDGELINEMODE - if ((lmodetype != REAL_LINEMODE) && - (lmodetype != KLUDGE_LINEMODE)) -# else - if (his_state_is_wont(TELOPT_LINEMODE)) -# endif -#endif - { - init_termbuf(); - tty_setecho(0); - set_termbuf(); - } - break; - - case TELOPT_SGA: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * If kludge linemode is in use, then we - * must process an incoming do SGA for - * linemode purposes. - */ - if ((lmodetype == KLUDGE_LINEMODE) || - (lmodetype == KLUDGE_OK)) { - /* - * The client is asking us to turn - * linemode on. - */ - lmodetype = KLUDGE_LINEMODE; - clientstat(TELOPT_LINEMODE, WILL, 0); - /* - * If we did not turn line mode on, - * then what do we say? Will SGA? - * This violates design of telnet. - * Gross. Very Gross. - */ - } - break; -#else - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); - set_my_state_wont(option); - if (turn_on_sga ^= 1) - send_will(option, 1); - return; -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - - default: - break; - } - - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); - } - set_my_state_wont(option); + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + } + set_my_state_wont(option); } /* end of dontoption */ @@ -1074,7 +903,7 @@ int env_ovalue = -1; * Window size * Terminal speed */ - void +void suboption(void) { int subchar; @@ -1087,18 +916,18 @@ suboption(void) int xspeed, rspeed; if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ - break; + break; settimer(tspeedsubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; + return; xspeed = atoi((char *)subpointer); while (SB_GET() != ',' && !SB_EOF()); if (SB_EOF()) - return; + return; rspeed = atoi((char *)subpointer); clientstat(TELOPT_TSPEED, xspeed, rspeed); @@ -1111,7 +940,7 @@ suboption(void) static char terminalname[41]; if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ - break; + break; settimer(ttypesubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) { @@ -1121,7 +950,7 @@ suboption(void) terminaltype = terminalname; while ((terminaltype < (terminalname + sizeof terminalname-1)) && - !SB_EOF()) { + !SB_EOF()) { int c; c = SB_GET(); @@ -1139,19 +968,19 @@ suboption(void) int xwinsize, ywinsize; if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ - break; + break; if (SB_EOF()) - return; + return; xwinsize = SB_GET() << 8; if (SB_EOF()) - return; + return; xwinsize |= SB_GET(); if (SB_EOF()) - return; + return; ywinsize = SB_GET() << 8; if (SB_EOF()) - return; + return; ywinsize |= SB_GET(); clientstat(TELOPT_NAWS, xwinsize, ywinsize); @@ -1159,54 +988,6 @@ suboption(void) } /* end of case TELOPT_NAWS */ -#ifdef LINEMODE - case TELOPT_LINEMODE: { - int request; - - if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ - break; - /* - * Process linemode suboptions. - */ - if (SB_EOF()) - break; /* garbage was sent */ - request = SB_GET(); /* get will/wont */ - - if (SB_EOF()) - break; /* another garbage check */ - - if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */ - /* - * Process suboption buffer of slc's - */ - start_slc(1); - do_opt_slc(subpointer, subend - subpointer); - end_slc(0); - break; - } else if (request == LM_MODE) { - if (SB_EOF()) - return; - useeditmode = SB_GET(); /* get mode flag */ - clientstat(LM_MODE, 0, 0); - break; - } - - if (SB_EOF()) - break; - switch (SB_GET()) { /* what suboption? */ - case LM_FORWARDMASK: - /* - * According to spec, only server can send request for - * forwardmask, and client can only return a positive response. - * So don't worry about it. - */ - - default: - break; - } - break; - } /* end of case TELOPT_LINEMODE */ -#endif case TELOPT_STATUS: { int mode; @@ -1230,7 +1011,7 @@ suboption(void) case TELOPT_XDISPLOC: { if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; + return; settimer(xdisplocsubopt); subpointer[SB_LEN()] = '\0'; setenv("DISPLAY", (char *)subpointer, 1); @@ -1245,15 +1026,15 @@ suboption(void) char *cp, *varp, *valp; if (SB_EOF()) - return; + return; c = SB_GET(); if (c == TELQUAL_IS) { - if (subchar == TELOPT_OLD_ENVIRON) - settimer(oenvironsubopt); - else - settimer(environsubopt); + if (subchar == TELOPT_OLD_ENVIRON) + settimer(oenvironsubopt); + else + settimer(environsubopt); } else if (c != TELQUAL_INFO) { - return; + return; } #ifdef TELOPT_NEW_ENVIRON @@ -1261,232 +1042,230 @@ suboption(void) while (!SB_EOF()) { c = SB_GET(); if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) - break; + break; } } else #endif - { + { #ifdef ENV_HACK - /* - * We only want to do this if we haven't already decided - * whether or not the other side has its VALUE and VAR - * reversed. - */ - if (env_ovar < 0) { - int last = -1; /* invalid value */ - int empty = 0; - int got_var = 0, got_value = 0, got_uservar = 0; - /* - * The other side might have its VALUE and VAR values - * reversed. To be interoperable, we need to determine - * which way it is. If the first recognized character - * is a VAR or VALUE, then that will tell us what - * type of client it is. If the fist recognized - * character is a USERVAR, then we continue scanning - * the suboption looking for two consecutive - * VAR or VALUE fields. We should not get two - * consecutive VALUE fields, so finding two - * consecutive VALUE or VAR fields will tell us - * what the client is. + * We only want to do this if we haven't already decided + * whether or not the other side has its VALUE and VAR + * reversed. */ - SB_SAVE(); - while (!SB_EOF()) { + if (env_ovar < 0) { + int last = -1; /* invalid value */ + int empty = 0; + int got_var = 0, got_value = 0, got_uservar = 0; + + /* + * The other side might have its VALUE and VAR values + * reversed. To be interoperable, we need to determine + * which way it is. If the first recognized character + * is a VAR or VALUE, then that will tell us what + * type of client it is. If the fist recognized + * character is a USERVAR, then we continue scanning + * the suboption looking for two consecutive + * VAR or VALUE fields. We should not get two + * consecutive VALUE fields, so finding two + * consecutive VALUE or VAR fields will tell us + * what the client is. + */ + SB_SAVE(); + while (!SB_EOF()) { c = SB_GET(); switch(c) { case OLD_ENV_VAR: - if (last < 0 || last == OLD_ENV_VAR - || (empty && (last == OLD_ENV_VALUE))) - goto env_ovar_ok; - got_var++; - last = OLD_ENV_VAR; - break; + if (last < 0 || last == OLD_ENV_VAR + || (empty && (last == OLD_ENV_VALUE))) + goto env_ovar_ok; + got_var++; + last = OLD_ENV_VAR; + break; case OLD_ENV_VALUE: - if (last < 0 || last == OLD_ENV_VALUE - || (empty && (last == OLD_ENV_VAR))) - goto env_ovar_wrong; - got_value++; - last = OLD_ENV_VALUE; - break; + if (last < 0 || last == OLD_ENV_VALUE + || (empty && (last == OLD_ENV_VAR))) + goto env_ovar_wrong; + got_value++; + last = OLD_ENV_VALUE; + break; case ENV_USERVAR: - /* count strings of USERVAR as one */ - if (last != ENV_USERVAR) - got_uservar++; - if (empty) { - if (last == OLD_ENV_VALUE) - goto env_ovar_ok; - if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - last = ENV_USERVAR; - break; + /* count strings of USERVAR as one */ + if (last != ENV_USERVAR) + got_uservar++; + if (empty) { + if (last == OLD_ENV_VALUE) + goto env_ovar_ok; + if (last == OLD_ENV_VAR) + goto env_ovar_wrong; + } + last = ENV_USERVAR; + break; case ENV_ESC: - if (!SB_EOF()) - c = SB_GET(); - /* FALL THROUGH */ + if (!SB_EOF()) + c = SB_GET(); + /* FALL THROUGH */ default: - empty = 0; - continue; + empty = 0; + continue; } empty = 1; - } - if (empty) { + } + if (empty) { if (last == OLD_ENV_VALUE) - goto env_ovar_ok; + goto env_ovar_ok; if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - /* - * Ok, the first thing was a USERVAR, and there - * are not two consecutive VAR or VALUE commands, - * and none of the VAR or VALUE commands are empty. - * If the client has sent us a well-formed option, - * then the number of VALUEs received should always - * be less than or equal to the number of VARs and - * USERVARs received. - * - * If we got exactly as many VALUEs as VARs and - * USERVARs, the client has the same definitions. - * - * If we got exactly as many VARs as VALUEs and - * USERVARS, the client has reversed definitions. - */ - if (got_uservar + got_var == got_value) { - env_ovar_ok: + goto env_ovar_wrong; + } + /* + * Ok, the first thing was a USERVAR, and there + * are not two consecutive VAR or VALUE commands, + * and none of the VAR or VALUE commands are empty. + * If the client has sent us a well-formed option, + * then the number of VALUEs received should always + * be less than or equal to the number of VARs and + * USERVARs received. + * + * If we got exactly as many VALUEs as VARs and + * USERVARs, the client has the same definitions. + * + * If we got exactly as many VARs as VALUEs and + * USERVARS, the client has reversed definitions. + */ + if (got_uservar + got_var == got_value) { + env_ovar_ok: env_ovar = OLD_ENV_VAR; env_ovalue = OLD_ENV_VALUE; - } else if (got_uservar + got_value == got_var) { - env_ovar_wrong: + } else if (got_uservar + got_value == got_var) { + env_ovar_wrong: env_ovar = OLD_ENV_VALUE; env_ovalue = OLD_ENV_VAR; - DIAG(TD_OPTIONS, {snprintf(nfrontp, - BUFSIZ - - (nfrontp - netobuf), - "ENVIRON VALUE and VAR are reversed!\r\n"); - nfrontp += strlen(nfrontp);}); + DIAG(TD_OPTIONS, { + output_data("ENVIRON VALUE and VAR are reversed!\r\n"); + }); + } } - } - SB_RESTORE(); + SB_RESTORE(); #endif - while (!SB_EOF()) { - c = SB_GET(); - if ((c == env_ovar) || (c == ENV_USERVAR)) + while (!SB_EOF()) { + c = SB_GET(); + if ((c == env_ovar) || (c == ENV_USERVAR)) break; + } } - } if (SB_EOF()) - return; + return; cp = varp = (char *)subpointer; valp = 0; while (!SB_EOF()) { + c = SB_GET(); + if (subchar == TELOPT_OLD_ENVIRON) { + if (c == env_ovar) + c = NEW_ENV_VAR; + else if (c == env_ovalue) + c = NEW_ENV_VALUE; + } + switch (c) { + + case NEW_ENV_VALUE: + *cp = '\0'; + cp = valp = (char *)subpointer; + break; + + case NEW_ENV_VAR: + case ENV_USERVAR: + *cp = '\0'; + if (valp) + setenv(varp, valp, 1); + else + unsetenv(varp); + cp = varp = (char *)subpointer; + valp = 0; + break; + + case ENV_ESC: + if (SB_EOF()) + break; c = SB_GET(); - if (subchar == TELOPT_OLD_ENVIRON) { - if (c == env_ovar) - c = NEW_ENV_VAR; - else if (c == env_ovalue) - c = NEW_ENV_VALUE; - } - switch (c) { - - case NEW_ENV_VALUE: - *cp = '\0'; - cp = valp = (char *)subpointer; - break; - - case NEW_ENV_VAR: - case ENV_USERVAR: - *cp = '\0'; - if (valp) - setenv(varp, valp, 1); - else - unsetenv(varp); - cp = varp = (char *)subpointer; - valp = 0; - break; - - case ENV_ESC: - if (SB_EOF()) - break; - c = SB_GET(); - /* FALL THROUGH */ - default: - *cp++ = c; - break; - } + /* FALL THROUGH */ + default: + *cp++ = c; + break; + } } *cp = '\0'; if (valp) - setenv(varp, valp, 1); + setenv(varp, valp, 1); else - unsetenv(varp); + unsetenv(varp); break; } /* end of case TELOPT_NEW_ENVIRON */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: if (SB_EOF()) - break; + break; switch(SB_GET()) { case TELQUAL_SEND: case TELQUAL_REPLY: - /* - * These are sent by us and cannot be sent by - * the client. - */ - break; + /* + * These are sent by us and cannot be sent by + * the client. + */ + break; case TELQUAL_IS: - auth_is(subpointer, SB_LEN()); - break; + auth_is(subpointer, SB_LEN()); + break; case TELQUAL_NAME: - auth_name(subpointer, SB_LEN()); - break; + auth_name(subpointer, SB_LEN()); + break; } break; #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION case TELOPT_ENCRYPT: if (SB_EOF()) - break; + break; switch(SB_GET()) { case ENCRYPT_SUPPORT: - encrypt_support(subpointer, SB_LEN()); - break; + encrypt_support(subpointer, SB_LEN()); + break; case ENCRYPT_IS: - encrypt_is(subpointer, SB_LEN()); - break; + encrypt_is(subpointer, SB_LEN()); + break; case ENCRYPT_REPLY: - encrypt_reply(subpointer, SB_LEN()); - break; + encrypt_reply(subpointer, SB_LEN()); + break; case ENCRYPT_START: - encrypt_start(subpointer, SB_LEN()); - break; + encrypt_start(subpointer, SB_LEN()); + break; case ENCRYPT_END: - encrypt_end(); - break; + encrypt_end(); + break; case ENCRYPT_REQSTART: - encrypt_request_start(subpointer, SB_LEN()); - break; + encrypt_request_start(subpointer, SB_LEN()); + break; case ENCRYPT_REQEND: - /* - * 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; + /* + * 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_ENC_KEYID: - encrypt_enc_keyid(subpointer, SB_LEN()); - break; + encrypt_enc_keyid(subpointer, SB_LEN()); + break; case ENCRYPT_DEC_KEYID: - encrypt_dec_keyid(subpointer, SB_LEN()); - break; + encrypt_dec_keyid(subpointer, SB_LEN()); + break; default: - break; + break; } break; #endif @@ -1497,100 +1276,79 @@ suboption(void) } /* end of suboption */ - void +void doclientstat(void) { - clientstat(TELOPT_LINEMODE, WILL, 0); + clientstat(TELOPT_LINEMODE, WILL, 0); } #define ADD(c) *ncp++ = c #define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } - void + +void send_status(void) { - unsigned char statusbuf[256]; - unsigned char *ncp; - unsigned char i; + unsigned char statusbuf[256]; + unsigned char *ncp; + unsigned char i; - ncp = statusbuf; + ncp = statusbuf; - netflush(); /* get rid of anything waiting to go out */ + netflush(); /* get rid of anything waiting to go out */ - ADD(IAC); + ADD(IAC); + ADD(SB); + ADD(TELOPT_STATUS); + ADD(TELQUAL_IS); + + /* + * We check the want_state rather than the current state, + * because if we received a DO/WILL for an option that we + * don't support, and the other side didn't send a DONT/WONT + * in response to our WONT/DONT, then the "state" will be + * WILL/DO, and the "want_state" will be WONT/DONT. We + * need to go by the latter. + */ + for (i = 0; i < (unsigned char)NTELOPTS; i++) { + if (my_want_state_is_will(i)) { + ADD(WILL); + ADD_DATA(i); + } + if (his_want_state_is_will(i)) { + ADD(DO); + ADD_DATA(i); + } + } + + if (his_want_state_is_will(TELOPT_LFLOW)) { ADD(SB); - ADD(TELOPT_STATUS); - ADD(TELQUAL_IS); - - /* - * We check the want_state rather than the current state, - * because if we received a DO/WILL for an option that we - * don't support, and the other side didn't send a DONT/WONT - * in response to our WONT/DONT, then the "state" will be - * WILL/DO, and the "want_state" will be WONT/DONT. We - * need to go by the latter. - */ - for (i = 0; i < (unsigned char)NTELOPTS; i++) { - if (my_want_state_is_will(i)) { - ADD(WILL); - ADD_DATA(i); - } - if (his_want_state_is_will(i)) { - ADD(DO); - ADD_DATA(i); - } + ADD(TELOPT_LFLOW); + if (flowmode) { + ADD(LFLOW_ON); + } else { + ADD(LFLOW_OFF); } - - if (his_want_state_is_will(TELOPT_LFLOW)) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (flowmode) { - ADD(LFLOW_ON); - } else { - ADD(LFLOW_OFF); - } - ADD(SE); - - if (restartany >= 0) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (restartany) { - ADD(LFLOW_RESTART_ANY); - } else { - ADD(LFLOW_RESTART_XON); - } - ADD(SE); - } - } - -#ifdef LINEMODE - if (his_want_state_is_will(TELOPT_LINEMODE)) { - unsigned char *cp, *cpe; - int len; - - ADD(SB); - ADD(TELOPT_LINEMODE); - ADD(LM_MODE); - ADD_DATA(editmode); - ADD(SE); - - ADD(SB); - ADD(TELOPT_LINEMODE); - ADD(LM_SLC); - start_slc(0); - send_slc(); - len = end_slc(&cp); - for (cpe = cp + len; cp < cpe; cp++) - ADD_DATA(*cp); - ADD(SE); - } -#endif /* LINEMODE */ - - ADD(IAC); ADD(SE); - writenet(statusbuf, ncp - statusbuf); - netflush(); /* Send it on its way */ + if (restartany >= 0) { + ADD(SB); + ADD(TELOPT_LFLOW); + if (restartany) { + ADD(LFLOW_RESTART_ANY); + } else { + ADD(LFLOW_RESTART_XON); + } + ADD(SE); + } + } - DIAG(TD_OPTIONS, - {printsub('>', statusbuf, ncp - statusbuf); netflush();}); + + ADD(IAC); + ADD(SE); + + writenet(statusbuf, ncp - statusbuf); + netflush(); /* Send it on its way */ + + DIAG(TD_OPTIONS, + {printsub('>', statusbuf, ncp - statusbuf); netflush();}); } diff --git a/appl/telnet/telnetd/sys_term.c b/appl/telnet/telnetd/sys_term.c index 23c81af1c..7fb81b15d 100644 --- a/appl/telnet/telnetd/sys_term.c +++ b/appl/telnet/telnetd/sys_term.c @@ -31,35 +31,21 @@ * SUCH DAMAGE. */ -#include -#ifdef SOCKS -#include -#endif +#include "telnetd.h" RCSID("$Id$"); -#include "telnetd.h" -#include "pathnames.h" - -#ifdef AUTHENTICATION -#include -#endif - -#if defined(CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H)) +#if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H)) # define PARENT_DOES_UTMP #endif -#ifdef NEWINIT -#error NEWINIT not supported -#endif - -#ifdef HAVE_UTMPX_H +#ifdef HAVE_UTMPX #include struct utmpx wtmp; #else #include struct utmp wtmp; -#endif /* HAVE_UTMPX_H */ +#endif /* HAVE_UTMPX */ #ifdef HAVE_UT_HOST int utmp_len = sizeof(wtmp.ut_host); @@ -73,7 +59,7 @@ char utmpf[] = "/etc/utmp"; char wtmpf[] = "/etc/wtmp"; #endif /* PARENT_DOES_UTMP */ -#ifdef CRAY +#ifdef _CRAY #include #include #endif /* CRAY */ @@ -127,6 +113,10 @@ char wtmpf[] = "/etc/wtmp"; #endif #endif +#ifdef HAVE_UTIL_H +#include +#endif + # ifndef TCSANOW # ifdef TCSETS # define TCSANOW TCSETS @@ -145,25 +135,25 @@ char wtmpf[] = "/etc/wtmp"; # endif # define tcsetattr(f, a, t) ioctl(f, a, t) # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ - (tp)->c_cflag |= (val) +(tp)->c_cflag |= (val) # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) # ifdef CIBAUD # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ - (tp)->c_cflag |= ((val)<c_cflag |= ((val)<c_cflag & CIBAUD)>>IBSHIFT) # else # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ - (tp)->c_cflag |= (val) + (tp)->c_cflag |= (val) # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) # endif # endif /* TCSANOW */ -struct termios termbuf, termbuf2; /* pty control structure */ + struct termios termbuf, termbuf2; /* pty control structure */ # ifdef STREAMSPTY -static int ttyfd = -1; -int really_stream = 0; + static int ttyfd = -1; + int really_stream = 0; # endif -char *new_login = LOGIN_PATH; + char *new_login = LOGIN_PATH; /* * init_termbuf() @@ -176,44 +166,31 @@ char *new_login = LOGIN_PATH; * set_termbuf() writes the structure into the kernel. */ -void -init_termbuf(void) + void + init_termbuf(void) { # ifdef STREAMSPTY - if (really_stream) - tcgetattr(ttyfd, &termbuf); - else + if (really_stream) + tcgetattr(ttyfd, &termbuf); + else # endif - tcgetattr(ourpty, &termbuf); - termbuf2 = termbuf; + tcgetattr(ourpty, &termbuf); + termbuf2 = termbuf; } -#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) - void -copy_termbuf(cp, len) - char *cp; - int len; -{ - if (len > sizeof(termbuf)) - len = sizeof(termbuf); - memmove(&termbuf, cp, len); - termbuf2 = termbuf; -} -#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ - - void +void set_termbuf(void) { - /* - * Only make the necessary changes. + /* + * Only make the necessary changes. */ - if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) + if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) # ifdef STREAMSPTY - if (really_stream) - tcsetattr(ttyfd, TCSANOW, &termbuf); - else + if (really_stream) + tcsetattr(ttyfd, TCSANOW, &termbuf); + else # endif - tcsetattr(ourpty, TCSANOW, &termbuf); + tcsetattr(ourpty, TCSANOW, &termbuf); } @@ -229,115 +206,115 @@ set_termbuf(void) */ - int +int spcset(int func, cc_t *valp, cc_t **valpp) { #define setval(a, b) *valp = termbuf.c_cc[a]; \ - *valpp = &termbuf.c_cc[a]; \ - return(b); + *valpp = &termbuf.c_cc[a]; \ + return(b); #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); - switch(func) { - case SLC_EOF: - setval(VEOF, SLC_VARIABLE); - case SLC_EC: - setval(VERASE, SLC_VARIABLE); - case SLC_EL: - setval(VKILL, SLC_VARIABLE); - case SLC_IP: - setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_ABORT: - setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_XON: + switch(func) { + case SLC_EOF: + setval(VEOF, SLC_VARIABLE); + case SLC_EC: + setval(VERASE, SLC_VARIABLE); + case SLC_EL: + setval(VKILL, SLC_VARIABLE); + case SLC_IP: + setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_ABORT: + setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_XON: #ifdef VSTART - setval(VSTART, SLC_VARIABLE); + setval(VSTART, SLC_VARIABLE); #else - defval(0x13); + defval(0x13); #endif - case SLC_XOFF: + case SLC_XOFF: #ifdef VSTOP - setval(VSTOP, SLC_VARIABLE); + setval(VSTOP, SLC_VARIABLE); #else - defval(0x11); + defval(0x11); #endif - case SLC_EW: + case SLC_EW: #ifdef VWERASE - setval(VWERASE, SLC_VARIABLE); + setval(VWERASE, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_RP: + case SLC_RP: #ifdef VREPRINT - setval(VREPRINT, SLC_VARIABLE); + setval(VREPRINT, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_LNEXT: + case SLC_LNEXT: #ifdef VLNEXT - setval(VLNEXT, SLC_VARIABLE); + setval(VLNEXT, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_AO: + case SLC_AO: #if !defined(VDISCARD) && defined(VFLUSHO) # define VDISCARD VFLUSHO #endif #ifdef VDISCARD - setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); + setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); #else - defval(0); + defval(0); #endif - case SLC_SUSP: + case SLC_SUSP: #ifdef VSUSP - setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); + setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); #else - defval(0); + defval(0); #endif #ifdef VEOL - case SLC_FORW1: - setval(VEOL, SLC_VARIABLE); + case SLC_FORW1: + setval(VEOL, SLC_VARIABLE); #endif #ifdef VEOL2 - case SLC_FORW2: - setval(VEOL2, SLC_VARIABLE); + case SLC_FORW2: + setval(VEOL2, SLC_VARIABLE); #endif - case SLC_AYT: + case SLC_AYT: #ifdef VSTATUS - setval(VSTATUS, SLC_VARIABLE); + setval(VSTATUS, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_BRK: - case SLC_SYNCH: - case SLC_EOR: - defval(0); + case SLC_BRK: + case SLC_SYNCH: + case SLC_EOR: + defval(0); - default: - *valp = 0; - *valpp = 0; - return(SLC_NOSUPPORT); - } + default: + *valp = 0; + *valpp = 0; + return(SLC_NOSUPPORT); + } } -#ifdef CRAY +#ifdef _CRAY /* * getnpty() * * Return the number of pty's configured into the system. */ - int +int getnpty() { #ifdef _SC_CRAY_NPTY - int numptys; + int numptys; - if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) - return numptys; - else + if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) + return numptys; + else #endif /* _SC_CRAY_NPTY */ - return 128; + return 128; } #endif /* CRAY */ @@ -356,22 +333,22 @@ char *line = Xline; char *line_nodev; char *line_notty; -#ifdef CRAY -char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +#ifdef _CRAY +char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; #endif /* CRAY */ #ifndef HAVE_PTSNAME static char *ptsname(int fd) { #ifdef HAVE_TTYNAME - return ttyname(fd); + return ttyname(fd); #else - return NULL; + return NULL; #endif } #endif -#ifdef HAVE_UTMPX_H +#ifdef HAVE_UTMPX static char utid[32]; /* XXX larger than ut_id */ void @@ -406,44 +383,46 @@ set_utid(void) int getpty(int *ptynum) { #ifdef __osf__ /* XXX */ - int master; - int slave; - if(openpty(&master, &slave, line, 0, 0) == 0){ - close(slave); - return master; - } - return -1; + int master; + int slave; + if(openpty(&master, &slave, line, 0, 0) == 0){ + close(slave); + return master; + } + return -1; #else #if IRIX == 4 - int master, slave; - char *p; - p = _getpty(&master, O_RDWR, 0600, 1); - if(p == NULL) - return -1; - strcpy(line, p); - return master; + int master, slave; + char *p; + p = _getpty(&master, O_RDWR, 0600, 1); + if(p == NULL) + return -1; + strcpy(line, p); + return master; #else - int p; - char *cp, *p1, *p2; - int i; - int dummy; + int p; + char *cp, *p1, *p2; + int i; +#if SunOS == 4 + int dummy; +#endif #if 0 /* && defined(HAVE_OPENPTY) */ - int master; - int slave; - if(openpty(&master, &slave, line, 0, 0) == 0){ - close(slave); - return master; - } + int master; + int slave; + if(openpty(&master, &slave, line, 0, 0) == 0){ + close(slave); + return master; + } #else #ifdef STREAMSPTY - char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", - "/dev/ptym/clone", 0 }; + char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", + "/dev/ptym/clone", 0 }; - char **q; - for(q=clone; *q; q++){ - p=open(*q, O_RDWR); - if(p >= 0){ + char **q; + for(q=clone; *q; q++){ + p=open(*q, O_RDWR); + if(p >= 0){ #ifdef HAVE_GRANTPT grantpt(p); #endif @@ -453,332 +432,241 @@ int getpty(int *ptynum) strcpy(line, ptsname(p)); really_stream = 1; return p; - } } + } #endif /* STREAMSPTY */ -#ifndef CRAY +#ifndef _CRAY #ifndef __hpux - snprintf(line, sizeof(Xline), "/dev/ptyXX"); - p1 = &line[8]; - p2 = &line[9]; + snprintf(line, sizeof(Xline), "/dev/ptyXX"); + p1 = &line[8]; + p2 = &line[9]; #else - snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); - p1 = &line[13]; - p2 = &line[14]; + snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); + p1 = &line[13]; + p2 = &line[14]; #endif - for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { - struct stat stb; + for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { + struct stat stb; - *p1 = *cp; - *p2 = '0'; - /* - * This stat() check is just to keep us from - * looping through all 256 combinations if there - * aren't that many ptys available. - */ - if (stat(line, &stb) < 0) - break; - for (i = 0; i < 16; i++) { - *p2 = "0123456789abcdef"[i]; - p = open(line, O_RDWR); - if (p > 0) { + *p1 = *cp; + *p2 = '0'; + /* + * This stat() check is just to keep us from + * looping through all 256 combinations if there + * aren't that many ptys available. + */ + if (stat(line, &stb) < 0) + break; + for (i = 0; i < 16; i++) { + *p2 = "0123456789abcdef"[i]; + p = open(line, O_RDWR); + if (p > 0) { #ifndef __hpux - line[5] = 't'; + line[5] = 't'; #else - for (p1 = &line[8]; *p1; p1++) - *p1 = *(p1+1); - line[9] = 't'; + for (p1 = &line[8]; *p1; p1++) + *p1 = *(p1+1); + line[9] = 't'; #endif - chown(line, 0, 0); - chmod(line, 0600); + chown(line, 0, 0); + chmod(line, 0600); #if SunOS == 4 - if (ioctl(p, TIOCGPGRP, &dummy) == 0 - || errno != EIO) { - chmod(line, 0666); - close(p); - line[5] = 'p'; - } else + if (ioctl(p, TIOCGPGRP, &dummy) == 0 + || errno != EIO) { + chmod(line, 0666); + close(p); + line[5] = 'p'; + } else #endif /* SunOS == 4 */ - return(p); - } - } + return(p); + } } + } #else /* CRAY */ - extern lowpty, highpty; - struct stat sb; + extern lowpty, highpty; + struct stat sb; - for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { - snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); - p = open(myline, 2); - if (p < 0) - continue; - snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); - /* - * Here are some shenanigans to make sure that there - * are no listeners lurking on the line. - */ - if(stat(line, &sb) < 0) { - close(p); - continue; - } - if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { - chown(line, 0, 0); - chmod(line, 0600); - close(p); - p = open(myline, 2); - if (p < 0) - continue; - } - /* - * Now it should be safe...check for accessability. - */ - if (access(line, 6) == 0) - return(p); - else { - /* no tty side to pty so skip it */ - close(p); - } + for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { + snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); + p = open(myline, 2); + if (p < 0) + continue; + snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); + /* + * Here are some shenanigans to make sure that there + * are no listeners lurking on the line. + */ + if(stat(line, &sb) < 0) { + close(p); + continue; } + if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { + chown(line, 0, 0); + chmod(line, 0600); + close(p); + p = open(myline, 2); + if (p < 0) + continue; + } + /* + * Now it should be safe...check for accessability. + */ + if (access(line, 6) == 0) + return(p); + else { + /* no tty side to pty so skip it */ + close(p); + } + } #endif /* CRAY */ #endif /* STREAMSPTY */ #endif /* OPENPTY */ - return(-1); + return(-1); #endif } -#ifdef LINEMODE -/* - * tty_flowmode() Find out if flow control is enabled or disabled. - * tty_linemode() Find out if linemode (external processing) is enabled. - * tty_setlinemod(on) Turn on/off linemode. - * tty_isecho() Find out if echoing is turned on. - * tty_setecho(on) Enable/disable character echoing. - * tty_israw() Find out if terminal is in RAW mode. - * tty_binaryin(on) Turn on/off BINARY on input. - * tty_binaryout(on) Turn on/off BINARY on output. - * tty_isediting() Find out if line editing is enabled. - * tty_istrapsig() Find out if signal trapping is enabled. - * tty_setedit(on) Turn on/off line editing. - * tty_setsig(on) Turn on/off signal trapping. - * tty_issofttab() Find out if tab expansion is enabled. - * tty_setsofttab(on) Turn on/off soft tab expansion. - * tty_islitecho() Find out if typed control chars are echoed literally - * tty_setlitecho() Turn on/off literal echo of control chars - * tty_tspeed(val) Set transmit speed to val. - * tty_rspeed(val) Set receive speed to val. - */ - - int -tty_linemode() -{ - return(termbuf.c_lflag & EXTPROC); -} - - void -tty_setlinemode(on) - int on; -{ -#ifdef TIOCEXT - set_termbuf(); - ioctl(ourpty, TIOCEXT, (char *)&on); - init_termbuf(); -#else /* !TIOCEXT */ -# ifdef EXTPROC - if (on) - termbuf.c_lflag |= EXTPROC; - else - termbuf.c_lflag &= ~EXTPROC; -# endif -#endif /* TIOCEXT */ -} -#endif /* LINEMODE */ - - int +int tty_isecho(void) { - return (termbuf.c_lflag & ECHO); + return (termbuf.c_lflag & ECHO); } - int +int tty_flowmode(void) { - return((termbuf.c_iflag & IXON) ? 1 : 0); + return((termbuf.c_iflag & IXON) ? 1 : 0); } - int +int tty_restartany(void) { - return((termbuf.c_iflag & IXANY) ? 1 : 0); + return((termbuf.c_iflag & IXANY) ? 1 : 0); } - void +void tty_setecho(int on) { - if (on) - termbuf.c_lflag |= ECHO; - else - termbuf.c_lflag &= ~ECHO; + if (on) + termbuf.c_lflag |= ECHO; + else + termbuf.c_lflag &= ~ECHO; } - int +int tty_israw(void) { - return(!(termbuf.c_lflag & ICANON)); + return(!(termbuf.c_lflag & ICANON)); } -#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - int -tty_setraw(on) -{ - if (on) - termbuf.c_lflag &= ~ICANON; - else - termbuf.c_lflag |= ICANON; -} -#endif - - void +void tty_binaryin(int on) { - if (on) { - termbuf.c_iflag &= ~ISTRIP; - } else { - termbuf.c_iflag |= ISTRIP; - } + if (on) { + termbuf.c_iflag &= ~ISTRIP; + } else { + termbuf.c_iflag |= ISTRIP; + } } - void +void tty_binaryout(int on) { - if (on) { - termbuf.c_cflag &= ~(CSIZE|PARENB); - termbuf.c_cflag |= CS8; - termbuf.c_oflag &= ~OPOST; - } else { - termbuf.c_cflag &= ~CSIZE; - termbuf.c_cflag |= CS7|PARENB; - termbuf.c_oflag |= OPOST; - } + if (on) { + termbuf.c_cflag &= ~(CSIZE|PARENB); + termbuf.c_cflag |= CS8; + termbuf.c_oflag &= ~OPOST; + } else { + termbuf.c_cflag &= ~CSIZE; + termbuf.c_cflag |= CS7|PARENB; + termbuf.c_oflag |= OPOST; + } } - int +int tty_isbinaryin(void) { - return(!(termbuf.c_iflag & ISTRIP)); + return(!(termbuf.c_iflag & ISTRIP)); } - int +int tty_isbinaryout(void) { - return(!(termbuf.c_oflag&OPOST)); + return(!(termbuf.c_oflag&OPOST)); } -#ifdef LINEMODE - int -tty_isediting() -{ - return(termbuf.c_lflag & ICANON); -} - int -tty_istrapsig() -{ - return(termbuf.c_lflag & ISIG); -} - - void -tty_setedit(on) - int on; -{ - if (on) - termbuf.c_lflag |= ICANON; - else - termbuf.c_lflag &= ~ICANON; -} - - void -tty_setsig(on) - int on; -{ - if (on) - termbuf.c_lflag |= ISIG; - else - termbuf.c_lflag &= ~ISIG; -} -#endif /* LINEMODE */ - - int +int tty_issofttab(void) { # ifdef OXTABS - return (termbuf.c_oflag & OXTABS); + return (termbuf.c_oflag & OXTABS); # endif # ifdef TABDLY - return ((termbuf.c_oflag & TABDLY) == TAB3); + return ((termbuf.c_oflag & TABDLY) == TAB3); # endif } - void +void tty_setsofttab(int on) { - if (on) { + if (on) { # ifdef OXTABS - termbuf.c_oflag |= OXTABS; + termbuf.c_oflag |= OXTABS; # endif # ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB3; + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB3; # endif - } else { + } else { # ifdef OXTABS - termbuf.c_oflag &= ~OXTABS; + termbuf.c_oflag &= ~OXTABS; # endif # ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB0; + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB0; # endif - } + } } - int +int tty_islitecho(void) { # ifdef ECHOCTL - return (!(termbuf.c_lflag & ECHOCTL)); + return (!(termbuf.c_lflag & ECHOCTL)); # endif # ifdef TCTLECH - return (!(termbuf.c_lflag & TCTLECH)); + return (!(termbuf.c_lflag & TCTLECH)); # endif # if !defined(ECHOCTL) && !defined(TCTLECH) - return (0); /* assumes ctl chars are echoed '^x' */ + return (0); /* assumes ctl chars are echoed '^x' */ # endif } - void +void tty_setlitecho(int on) { # ifdef ECHOCTL - if (on) - termbuf.c_lflag &= ~ECHOCTL; - else - termbuf.c_lflag |= ECHOCTL; + if (on) + termbuf.c_lflag &= ~ECHOCTL; + else + termbuf.c_lflag |= ECHOCTL; # endif # ifdef TCTLECH - if (on) - termbuf.c_lflag &= ~TCTLECH; - else - termbuf.c_lflag |= TCTLECH; + if (on) + termbuf.c_lflag &= ~TCTLECH; + else + termbuf.c_lflag |= TCTLECH; # endif } - int +int tty_iscrnl(void) { - return (termbuf.c_iflag & ICRNL); + return (termbuf.c_iflag & ICRNL); } /* @@ -794,72 +682,72 @@ tty_iscrnl(void) * A table of available terminal speeds */ struct termspeeds { - int speed; - int value; + int speed; + int 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 }, + { 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 }, #ifdef B7200 - { 7200, B7200 }, + { 7200, B7200 }, #endif - { 9600, B9600 }, + { 9600, B9600 }, #ifdef B14400 - { 14400, B14400 }, + { 14400, B14400 }, #endif #ifdef B19200 - { 19200, B19200 }, + { 19200, B19200 }, #endif #ifdef B28800 - { 28800, B28800 }, + { 28800, B28800 }, #endif #ifdef B38400 - { 38400, B38400 }, + { 38400, B38400 }, #endif #ifdef B57600 - { 57600, B57600 }, + { 57600, B57600 }, #endif #ifdef B115200 - { 115200, B115200 }, + { 115200, B115200 }, #endif #ifdef B230400 - { 230400, B230400 }, + { 230400, B230400 }, #endif - { -1, 0 } + { -1, 0 } }; #endif /* DECODE_BUAD */ - void +void tty_tspeed(int val) { #ifdef DECODE_BAUD - struct termspeeds *tp; + struct termspeeds *tp; - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetospeed(&termbuf, tp->value); + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetospeed(&termbuf, tp->value); #else /* DECODE_BUAD */ - cfsetospeed(&termbuf, val); + cfsetospeed(&termbuf, val); #endif /* DECODE_BUAD */ } - void +void tty_rspeed(int val) { #ifdef DECODE_BAUD - struct termspeeds *tp; + struct termspeeds *tp; - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetispeed(&termbuf, tp->value); + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetispeed(&termbuf, tp->value); #else /* DECODE_BAUD */ - cfsetispeed(&termbuf, val); + cfsetispeed(&termbuf, val); #endif /* DECODE_BAUD */ } @@ -879,55 +767,55 @@ extern void utmp_sig_notify (int); static int my_find(int fd, char *module) { #if defined(I_FIND) && defined(I_LIST) - static int flag; - static struct str_list sl; - int n; - int i; + static int flag; + static struct str_list sl; + int n; + int i; - if(!flag){ - n = ioctl(fd, I_LIST, 0); - if(n < 0){ - perror("ioctl(fd, I_LIST, 0)"); - return -1; + if(!flag){ + n = ioctl(fd, I_LIST, 0); + if(n < 0){ + perror("ioctl(fd, I_LIST, 0)"); + return -1; + } + sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist)); + sl.sl_nmods = n; + n = ioctl(fd, I_LIST, &sl); + if(n < 0){ + perror("ioctl(fd, I_LIST, n)"); + return -1; + } + flag = 1; } - sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist)); - sl.sl_nmods = n; - n = ioctl(fd, I_LIST, &sl); - if(n < 0){ - perror("ioctl(fd, I_LIST, n)"); - return -1; - } - flag = 1; - } - for(i=0; i= modules; p--){ - err = ioctl(fd, I_PUSH, *p); - if(err < 0 && errno != EINVAL) - fatalperror(net, "I_PUSH"); - } + for(p--; p >= modules; p--){ + err = ioctl(fd, I_PUSH, *p); + if(err < 0 && errno != EINVAL) + fatalperror(net, "I_PUSH"); + } } #endif @@ -940,153 +828,136 @@ static void maybe_push_modules(int fd, char **modules) */ void getptyslave(void) { - int t = -1; + int t = -1; -# ifdef LINEMODE - int waslm; -# endif - struct winsize ws; - extern int def_row, def_col; - extern int def_tspeed, def_rspeed; - /* - * Opening the slave side may cause initilization of the - * kernel tty structure. We need remember the state of - * if linemode was turned on - * terminal window size - * terminal speed - * so that we can re-set them if we need to. - */ -# ifdef LINEMODE - waslm = tty_linemode(); -# endif + struct winsize ws; + extern int def_row, def_col; + extern int def_tspeed, def_rspeed; + /* + * Opening the slave side may cause initilization of the + * kernel tty structure. We need remember the state of + * if linemode was turned on + * terminal window size + * terminal speed + * so that we can re-set them if we need to. + */ - /* - * Make sure that we don't have a controlling tty, and - * that we are the session (process group) leader. - */ + /* + * Make sure that we don't have a controlling tty, and + * that we are the session (process group) leader. + */ #ifdef HAVE_SETSID - if(setsid()<0) - fatalperror(net, "setsid()"); + if(setsid()<0) + fatalperror(net, "setsid()"); #else # ifdef TIOCNOTTY - t = open(_PATH_TTY, O_RDWR); - if (t >= 0) { - ioctl(t, TIOCNOTTY, (char *)0); - close(t); - } + t = open(_PATH_TTY, O_RDWR); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + close(t); + } # endif #endif # ifdef PARENT_DOES_UTMP - /* - * Wait for our parent to get the utmp stuff to get done. - */ - utmp_sig_wait(); + /* + * Wait for our parent to get the utmp stuff to get done. + */ + utmp_sig_wait(); # endif - t = cleanopen(line); - if (t < 0) - fatalperror(net, line); + t = cleanopen(line); + if (t < 0) + fatalperror(net, line); #ifdef STREAMSPTY - ttyfd = t; + ttyfd = t; - /* - * Not all systems have (or need) modules ttcompat and pckt so - * don't flag it as a fatal error if they don't exist. - */ + /* + * Not all systems have (or need) modules ttcompat and pckt so + * don't flag it as a fatal error if they don't exist. + */ - if (really_stream) + if (really_stream) { - /* these are the streams modules that we want pushed. note - that they are in reverse order, ptem will be pushed - first. maybe_push_modules() will try to push all modules - before the first one that isn't already pushed. i.e if - ldterm is pushed, only ttcompat will be attempted. + /* these are the streams modules that we want pushed. note + that they are in reverse order, ptem will be pushed + first. maybe_push_modules() will try to push all modules + before the first one that isn't already pushed. i.e if + ldterm is pushed, only ttcompat will be attempted. - all this is because we don't know which modules are - available, and we don't know which modules are already - pushed (via autopush, for instance). + all this is because we don't know which modules are + available, and we don't know which modules are already + pushed (via autopush, for instance). - */ + */ - char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; - char *ptymodules[] = { "pckt", NULL }; + char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; + char *ptymodules[] = { "pckt", NULL }; - maybe_push_modules(t, ttymodules); - maybe_push_modules(ourpty, ptymodules); + maybe_push_modules(t, ttymodules); + maybe_push_modules(ourpty, ptymodules); } #endif - /* - * set up the tty modes as we like them to be. - */ - init_termbuf(); + /* + * set up the tty modes as we like them to be. + */ + init_termbuf(); # ifdef TIOCSWINSZ - if (def_row || def_col) { - memset(&ws, 0, sizeof(ws)); - ws.ws_col = def_col; - ws.ws_row = def_row; - ioctl(t, TIOCSWINSZ, (char *)&ws); - } + if (def_row || def_col) { + memset(&ws, 0, sizeof(ws)); + ws.ws_col = def_col; + ws.ws_row = def_row; + ioctl(t, TIOCSWINSZ, (char *)&ws); + } # endif - /* - * Settings for sgtty based systems - */ + /* + * Settings for sgtty based systems + */ - /* - * Settings for UNICOS (and HPUX) - */ -# if defined(CRAY) || defined(__hpux) - termbuf.c_oflag = OPOST|ONLCR|TAB3; - termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; - termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; - termbuf.c_cflag = EXTB|HUPCL|CS8; + /* + * Settings for UNICOS (and HPUX) + */ +# if defined(_CRAY) || defined(__hpux) + termbuf.c_oflag = OPOST|ONLCR|TAB3; + termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; + termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; + termbuf.c_cflag = EXTB|HUPCL|CS8; # endif - /* - * Settings for all other termios/termio based - * systems, other than 4.4BSD. In 4.4BSD the - * kernel does the initial terminal setup. - */ -# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) + /* + * Settings for all other termios/termio based + * systems, other than 4.4BSD. In 4.4BSD the + * kernel does the initial terminal setup. + */ +# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) # ifndef OXTABS # define OXTABS 0 # endif - termbuf.c_lflag |= ECHO; - termbuf.c_oflag |= ONLCR|OXTABS; - termbuf.c_iflag |= ICRNL; - termbuf.c_iflag &= ~IXOFF; + termbuf.c_lflag |= ECHO; + termbuf.c_oflag |= ONLCR|OXTABS; + termbuf.c_iflag |= ICRNL; + termbuf.c_iflag &= ~IXOFF; # endif - tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); - tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); -# ifdef LINEMODE - if (waslm) - tty_setlinemode(1); -# endif /* LINEMODE */ + tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); + tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); - /* - * Set the tty modes, and make this our controlling tty. - */ - set_termbuf(); - if (login_tty(t) == -1) - fatalperror(net, "login_tty"); - if (net > 2) - close(net); -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - /* - * Leave the pty open so that we can write out the rlogin - * protocol for /bin/login, if the authentication works. - */ -#else - if (ourpty > 2) { - close(ourpty); - ourpty = -1; - } -#endif + /* + * Set the tty modes, and make this our controlling tty. + */ + set_termbuf(); + if (login_tty(t) == -1) + fatalperror(net, "login_tty"); + if (net > 2) + close(net); + if (ourpty > 2) { + close(ourpty); + ourpty = -1; + } } #ifndef O_NOCTTY @@ -1099,118 +970,103 @@ void getptyslave(void) int cleanopen(char *line) { - int t; + int t; #ifdef STREAMSPTY - if (!really_stream) + if (!really_stream) #endif { - /* - * Make sure that other people can't open the - * slave side of the connection. - */ - chown(line, 0, 0); - chmod(line, 0600); + /* + * Make sure that other people can't open the + * slave side of the connection. + */ + chown(line, 0, 0); + chmod(line, 0600); } -# if !defined(CRAY) && (BSD > 43) - revoke(line); +# if !defined(_CRAY) && (BSD > 43) + revoke(line); # endif - t = open(line, O_RDWR|O_NOCTTY); + t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); + if (t < 0) + return(-1); - /* - * Hangup anybody else using this ttyp, then reopen it for - * ourselves. - */ -# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) - signal(SIGHUP, SIG_IGN); + /* + * Hangup anybody else using this ttyp, then reopen it for + * ourselves. + */ +# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) + signal(SIGHUP, SIG_IGN); #ifdef HAVE_VHANGUP - vhangup(); + vhangup(); #else #endif - signal(SIGHUP, SIG_DFL); - t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); + signal(SIGHUP, SIG_DFL); + t = open(line, O_RDWR|O_NOCTTY); + if (t < 0) + return(-1); # endif -# if defined(CRAY) && defined(TCVHUP) - { - int i; - signal(SIGHUP, SIG_IGN); - ioctl(t, TCVHUP, (char *)0); - signal(SIGHUP, SIG_DFL); +# if defined(_CRAY) && defined(TCVHUP) + { + int i; + signal(SIGHUP, SIG_IGN); + ioctl(t, TCVHUP, (char *)0); + signal(SIGHUP, SIG_DFL); - i = open(line, O_RDWR); + i = open(line, O_RDWR); - if (i < 0) - return(-1); - close(t); - t = i; - } + if (i < 0) + return(-1); + close(t); + t = i; + } # endif /* defined(CRAY) && defined(TCVHUP) */ - return(t); + return(t); } #if !defined(BSD4_4) int login_tty(int t) { -#if 0 /* setsid done in other place */ -#if defined(HAVE_SETSID) && !defined(_AIX) - if (setsid() < 0) { -#ifdef ultrix - /* - * The setsid() may have failed because we - * already have a pgrp == pid. Zero out - * our pgrp and try again... - */ - if ((setpgrp(0, 0) < 0) || (setsid() < 0)) -#endif - fatalperror(net, "setsid()"); - } -#endif /* HAVE_SETSID */ -#endif # if defined(TIOCSCTTY) && !defined(__hpux) - if (ioctl(t, TIOCSCTTY, (char *)0) < 0) - fatalperror(net, "ioctl(sctty)"); -# if defined(CRAY) - /* - * Close the hard fd to /dev/ttypXXX, and re-open through - * the indirect /dev/tty interface. - */ - close(t); - if ((t = open("/dev/tty", O_RDWR)) < 0) - fatalperror(net, "open(/dev/tty)"); + if (ioctl(t, TIOCSCTTY, (char *)0) < 0) + fatalperror(net, "ioctl(sctty)"); +# ifdef _CRAY + /* + * Close the hard fd to /dev/ttypXXX, and re-open through + * the indirect /dev/tty interface. + */ + close(t); + if ((t = open("/dev/tty", O_RDWR)) < 0) + fatalperror(net, "open(/dev/tty)"); # endif # else - /* - * We get our controlling tty assigned as a side-effect - * of opening up a tty device. But on BSD based systems, - * this only happens if our process group is zero. The - * setsid() call above may have set our pgrp, so clear - * it out before opening the tty... - */ -#if defined HAVE_SETPGID - setpgid(0, 0); + /* + * We get our controlling tty assigned as a side-effect + * of opening up a tty device. But on BSD based systems, + * this only happens if our process group is zero. The + * setsid() call above may have set our pgrp, so clear + * it out before opening the tty... + */ +#ifdef HAVE_SETPGID + setpgid(0, 0); #else - setpgrp(0, 0); /* if setpgid isn't available, setpgrp - probably takes arguments */ + setpgrp(0, 0); /* if setpgid isn't available, setpgrp + probably takes arguments */ #endif - close(open(line, O_RDWR)); + close(open(line, O_RDWR)); # endif - if (t != 0) - dup2(t, 0); - if (t != 1) - dup2(t, 1); - if (t != 2) - dup2(t, 2); - if (t > 2) - close(t); - return(0); + if (t != 0) + dup2(t, 0); + if (t != 1) + dup2(t, 1); + if (t != 2) + dup2(t, 2); + if (t > 2) + close(t); + return(0); } #endif /* BSD <= 43 */ @@ -1222,99 +1078,98 @@ int login_tty(int t) */ /* ARGSUSED */ - void +void startslave(char *host, int autologin, char *autoname) { - int i; - char name[256]; + int i; -#if defined(AUTHENTICATION) - if (!autoname || !autoname[0]) - autologin = 0; +#ifdef AUTHENTICATION + if (!autoname || !autoname[0]) + autologin = 0; - if (autologin < auth_level) { - fatal(net, "Authorization failed"); - exit(1); - } + if (autologin < auth_level) { + fatal(net, "Authorization failed"); + exit(1); + } #endif - { + { char *tbuf = - "\r\n*** Connection not encrypted! " - "Communication may be eavesdropped. ***\r\n"; + "\r\n*** Connection not encrypted! " + "Communication may be eavesdropped. ***\r\n"; #ifdef ENCRYPTION if (!no_warn && (encrypt_output == 0 || decrypt_input == 0)) #endif - writenet((unsigned char*)tbuf, strlen(tbuf)); - } + writenet((unsigned char*)tbuf, strlen(tbuf)); + } # ifdef PARENT_DOES_UTMP - utmp_sig_init(); + utmp_sig_init(); # endif /* PARENT_DOES_UTMP */ - if ((i = fork()) < 0) - fatalperror(net, "fork"); - if (i) { + if ((i = fork()) < 0) + fatalperror(net, "fork"); + if (i) { # ifdef PARENT_DOES_UTMP - /* - * Cray parent will create utmp entry for child and send - * signal to child to tell when done. Child waits for signal - * before doing anything important. - */ - int pid = i; - void sigjob (int); + /* + * Cray parent will create utmp entry for child and send + * signal to child to tell when done. Child waits for signal + * before doing anything important. + */ + int pid = i; + void sigjob (int); - setpgrp(); - utmp_sig_reset(); /* reset handler to default */ - /* - * Create utmp entry for child - */ - time(&wtmp.ut_time); - wtmp.ut_type = LOGIN_PROCESS; - wtmp.ut_pid = pid; - SCPYN(wtmp.ut_user, "LOGIN"); - SCPYN(wtmp.ut_host, host); - SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); + setpgrp(); + utmp_sig_reset(); /* reset handler to default */ + /* + * Create utmp entry for child + */ + time(&wtmp.ut_time); + wtmp.ut_type = LOGIN_PROCESS; + wtmp.ut_pid = pid; + SCPYN(wtmp.ut_user, "LOGIN"); + SCPYN(wtmp.ut_host, host); + SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); #ifndef __hpux - SCPYN(wtmp.ut_id, wtmp.ut_line+3); + SCPYN(wtmp.ut_id, wtmp.ut_line+3); #else - SCPYN(wtmp.ut_id, wtmp.ut_line+7); + SCPYN(wtmp.ut_id, wtmp.ut_line+7); #endif - pututline(&wtmp); - endutent(); - if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { - write(i, &wtmp, sizeof(struct utmp)); - close(i); - } -#ifdef CRAY - signal(WJSIGNAL, sigjob); -#endif - utmp_sig_notify(pid); -# endif /* PARENT_DOES_UTMP */ - } else { - getptyslave(); - start_login(host, autologin, autoname); - /*NOTREACHED*/ + pututline(&wtmp); + endutent(); + if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { + write(i, &wtmp, sizeof(struct utmp)); + close(i); } +#ifdef _CRAY + signal(WJSIGNAL, sigjob); +#endif + utmp_sig_notify(pid); +# endif /* PARENT_DOES_UTMP */ + } else { + getptyslave(); + start_login(host, autologin, autoname); + /*NOTREACHED*/ + } } char *envinit[3]; extern char **environ; - void +void init_env(void) { - extern char *getenv(const char *); - char **envp; + extern char *getenv(const char *); + char **envp; - envp = envinit; - if (*envp = getenv("TZ")) - *envp++ -= 3; -#if defined(CRAY) || defined(__hpux) - else - *envp++ = "TZ=GMT0"; + envp = envinit; + if (*envp = getenv("TZ")) + *envp++ -= 3; +#if defined(_CRAY) || defined(__hpux) + else + *envp++ = "TZ=GMT0"; #endif - *envp = 0; - environ = envinit; + *envp = 0; + environ = envinit; } /* @@ -1327,29 +1182,29 @@ init_env(void) static void scrub_env(void) { - static char *remove[] = { "LD_", "_RLD_", "LIBPATH=", "IFS=", NULL }; + static char *remove[] = { "LD_", "_RLD_", "LIBPATH=", "IFS=", NULL }; - char **cpp, **cpp2; - char **p; + char **cpp, **cpp2; + char **p; - for (cpp2 = cpp = environ; *cpp; cpp++) { - for(p = remove; *p; p++) - if(strncmp(*cpp, *p, strlen(*p)) == 0) - break; - if(*p == NULL) - *cpp2++ = *cpp; - } - *cpp2 = 0; + for (cpp2 = cpp = environ; *cpp; cpp++) { + for(p = remove; *p; p++) + if(strncmp(*cpp, *p, strlen(*p)) == 0) + break; + if(*p == NULL) + *cpp2++ = *cpp; + } + *cpp2 = 0; } struct arg_val { - int size; - int argc; - char **argv; + int size; + int argc; + char **argv; }; -int addarg(struct arg_val*, char*); +static int addarg(struct arg_val*, char*); /* * start_login(host) @@ -1360,250 +1215,121 @@ int addarg(struct arg_val*, char*); void start_login(char *host, int autologin, char *name) { - char *cp; - struct arg_val argv; - struct timeval tmp; + struct arg_val argv; -#ifdef HAVE_UTMPX_H - char id_buf[3]; - int ptynum; - int pid = getpid(); - struct utmpx utmpx; +#ifdef HAVE_UTMPX + char id_buf[3]; + int ptynum; + int pid = getpid(); + struct utmpx utmpx; + struct timeval tmp; - /* - * Create utmp entry for child - */ + /* + * Create utmp entry for child + */ - memset(&utmpx, 0, sizeof(utmpx)); - SCPYN(utmpx.ut_user, ".telnet"); + memset(&utmpx, 0, sizeof(utmpx)); + SCPYN(utmpx.ut_user, ".telnet"); - SCPYN(utmpx.ut_line, line_nodev); - utmpx.ut_pid = pid; - SCPYN(utmpx.ut_id, utid); + SCPYN(utmpx.ut_line, line_nodev); + utmpx.ut_pid = pid; + SCPYN(utmpx.ut_id, utid); - utmpx.ut_type = LOGIN_PROCESS; + utmpx.ut_type = LOGIN_PROCESS; - gettimeofday (&tmp, NULL); - utmpx.ut_tv.tv_sec = tmp.tv_sec; - utmpx.ut_tv.tv_usec = tmp.tv_usec; - if (pututxline(&utmpx) == NULL) - fatal(net, "pututxline failed"); + gettimeofday (&tmp, NULL); + utmpx.ut_tv.tv_sec = tmp.tv_sec; + utmpx.ut_tv.tv_usec = tmp.tv_usec; + if (pututxline(&utmpx) == NULL) + fatal(net, "pututxline failed"); #endif - scrub_env(); + scrub_env(); - /* - * -h : pass on name of host. - * WARNING: -h is accepted by login if and only if - * getuid() == 0. - * -p : don't clobber the environment (so terminal type stays set). - * - * -f : force this login, he has already been authenticated - */ + /* + * -h : pass on name of host. + * WARNING: -h is accepted by login if and only if + * getuid() == 0. + * -p : don't clobber the environment (so terminal type stays set). + * + * -f : force this login, he has already been authenticated + */ - /* init argv structure */ - argv.size=0; - argv.argc=0; - argv.argv=(char**)malloc(0); /*so we can call realloc later */ - - addarg(&argv, "login"); - -#if !defined(NO_LOGIN_H) - -# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - /* - * Don't add the "-h host" option if we are going - * to be adding the "-r host" option down below... - */ - if ((auth_level < 0) || (autologin != AUTH_VALID)) -# endif - { - addarg(&argv, "-h"); - addarg(&argv, host); + /* init argv structure */ + argv.size=0; + argv.argc=0; + argv.argv=(char**)malloc(0); /*so we can call realloc later */ + addarg(&argv, "login"); + addarg(&argv, "-h"); + addarg(&argv, host); + addarg(&argv, "-p"); +#ifdef AUTHENTICATION + if (auth_level < 0 || autologin != AUTH_VALID) { + if(!no_warn) + printf("User not authenticated. " + "Using plaintext username and password\r\n"); + if (require_otp) { + addarg(&argv, "-a"); + addarg(&argv, "otp"); } + if(log_unauth) { + char *u; + if(name[0]) u = name; + else u=getenv("USER"); + u = u ? u : "unknown user"; + syslog(LOG_INFO, "unauthenticated access from %s (%s)", + host, u); + } + } + if (auth_level >= 0 && autologin == AUTH_VALID) { + addarg(&argv, "-f"); + addarg(&argv, "--"); + addarg(&argv, name); + } /* else */ /* esc@magic.fi; removed stupid else */ #endif -#if !defined(NO_LOGIN_P) - addarg(&argv, "-p"); -#endif -#ifdef LINEMODE + if (getenv("USER")) { + addarg(&argv, "--"); + addarg(&argv, strdup(getenv("USER"))); /* - * Set the environment variable "LINEMODE" to either - * "real" or "kludge" if we are operating in either - * real or kludge linemode. + * Assume that login will set the USER variable + * correctly. For SysV systems, this means that + * USER will no longer be set, just LOGNAME by + * login. (The problem is that if the auto-login + * fails, and the user then specifies a different + * account name, he can get logged in with both + * LOGNAME and USER in his environment, but the + * USER value will be wrong. */ - if (lmodetype == REAL_LINEMODE) - setenv("LINEMODE", "real", 1); -# ifdef KLUDGELINEMODE - else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) - setenv("LINEMODE", "kludge", 1); -# endif -#endif -#if defined (AUTHENTICATION) - if (auth_level < 0 || autologin != AUTH_VALID) { - if(!no_warn) - printf("User not authenticated. " - "Using plaintext username and password\r\n"); - if (require_otp) { - addarg(&argv, "-a"); - addarg(&argv, "otp"); - } - if(log_unauth) { - char *u; - if(name[0]) u = name; - else u=getenv("USER"); - u = u ? u : "unknown user"; - syslog(LOG_INFO, "unauthenticated access from %s (%s)", - host, u); - } - } - if (auth_level >= 0 && autologin == AUTH_VALID) { -# if !defined(NO_LOGIN_F) - addarg(&argv, "-f"); - addarg(&argv, "--"); - addarg(&argv, name); -# else -# if defined(LOGIN_R) - /* - * We don't have support for "login -f", but we - * can fool /bin/login into thinking that we are - * rlogind, and allow us to log in without a - * password. The rlogin protocol expects - * local-user\0remote-user\0term/speed\0 - */ + unsetenv("USER"); + } + closelog(); + /* + * This sleep(1) is in here so that telnetd can + * finish up with the tty. There's a race condition + * the login banner message gets lost... + */ + sleep(1); - if (ourpty > 2) { - char *cp; - char speed[128]; - int isecho, israw, xpty, len; - extern int def_rspeed; -# ifndef LOGIN_HOST - /* - * Tell login that we are coming from "localhost". - * If we passed in the real host name, then the - * user would have to allow .rhost access from - * every machine that they want authenticated - * access to work from, which sort of defeats - * the purpose of an authenticated login... - * So, we tell login that the session is coming - * from "localhost", and the user will only have - * to have "localhost" in their .rhost file. - */ -# define LOGIN_HOST "localhost" -# endif /* LOGIN_HOST */ - addarg(&argv, "-r"); - addarg(&argv, LOGIN_HOST); + execv(new_login, argv.argv); - xpty = ourpty; -#ifdef STREAMSPTY - if (really_stream) - ttyfd = 0; - else -#endif - pty = 0; - - init_termbuf(); - isecho = tty_isecho(); - israw = tty_israw(); - if (isecho || !israw) { - tty_setecho(0); /* Turn off echo */ - tty_setraw(1); /* Turn on raw */ - set_termbuf(); - } - len = strlen(name)+1; - write(xpty, name, len); - write(xpty, name, len); - snprintf(speed, sizeof(speed), - "%s/%d", (cp = getenv("TERM")) ? cp : "", - (def_rspeed > 0) ? def_rspeed : 9600); - len = strlen(speed)+1; - write(xpty, speed, len); - - if (isecho || !israw) { - init_termbuf(); - tty_setecho(isecho); - tty_setraw(israw); - set_termbuf(); - if (!israw) { - /* - * Write a newline to ensure - * that login will be able to - * read the line... - */ - write(xpty, "\n", 1); - } - } - ourpty = xpty; - } -# else /* LOGIN_R */ - addarg(&argv, "--"); - addarg(&argv, name); -# endif -# endif /* NO_LOGIN_F */ - } /* else */ /* esc@magic.fi; removed stupid else */ -#endif - if (getenv("USER")) { - addarg(&argv, "--"); - addarg(&argv, getenv("USER")); -#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) - { - char **cpp; - for (cpp = environ; *cpp; cpp++) { - addarg(&argv, *cpp); - } - } -#endif - /* - * Assume that login will set the USER variable - * correctly. For SysV systems, this means that - * USER will no longer be set, just LOGNAME by - * login. (The problem is that if the auto-login - * fails, and the user then specifies a different - * account name, he can get logged in with both - * LOGNAME and USER in his environment, but the - * USER value will be wrong. - */ - unsetenv("USER"); - } -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - if (ourpty > 2) - close(ourpty); -#endif - closelog(); - /* - * This sleep(1) is in here so that telnetd can - * finish up with the tty. There's a race condition - * the login banner message gets lost... - */ - sleep(1); -#ifdef SHOW_LOGIN_ARGS - { - int i; - for(i=0;argv.argv[i];i++) - fprintf(stderr, "%s ", argv.argv[i]); - fprintf(stderr, "\n"); - } -#endif - - execv(new_login, argv.argv); - - syslog(LOG_ERR, "%s: %m\n", new_login); - fatalperror(net, new_login); - /*NOTREACHED*/ + syslog(LOG_ERR, "%s: %m\n", new_login); + fatalperror(net, new_login); + /*NOTREACHED*/ } -int addarg(struct arg_val *argv, char *val) +static int addarg(struct arg_val *argv, char *val) { - if(argv->size <= argv->argc+1){ - argv->argv = (char**)realloc(argv->argv, sizeof(char*) * (argv->size + 10)); - if(argv->argv == NULL) - return 1; /* this should probably be handled better */ - argv->size+=10; - } - argv->argv[argv->argc++]=val; - argv->argv[argv->argc]=NULL; - return 0; + if(argv->size <= argv->argc+1){ + argv->argv = (char**)realloc(argv->argv, sizeof(char*) * (argv->size + 10)); + if(argv->argv == NULL) + return 1; /* this should probably be handled better */ + argv->size+=10; + } + argv->argv[argv->argc++]=val; + argv->argv[argv->argc]=NULL; + return 0; } @@ -1614,147 +1340,142 @@ int addarg(struct arg_val *argv, char *val) * remove the utmp entry for this person. */ -#ifdef HAVE_UTMPX_H +#ifdef HAVE_UTMPX static void rmut(void) { - int f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - struct timeval tmp; - struct utmpx *utxp, utmpx; + int f; + int found = 0; + struct utmp *u, *utmp; + int nutmp; + struct stat statbf; + struct timeval tmp; + struct utmpx *utxp, utmpx; - /* - * This updates the utmpx and utmp entries and make a wtmp/x entry - */ + /* + * This updates the utmpx and utmp entries and make a wtmp/x entry + */ - setutxent(); - memset(&utmpx, 0, sizeof(utmpx)); - strncpy(utmpx.ut_id, utid, sizeof(utmpx.ut_id)); - utmpx.ut_type = LOGIN_PROCESS; - utxp = getutxid(&utmpx); - if (utxp) { - strcpy(utxp->ut_user, ""); - utxp->ut_type = DEAD_PROCESS; -#ifdef __osf__ /* XXX */ - utxp->ut_exit.ut_termination = 0; - utxp->ut_exit.ut_exit = 0; -#else + setutxent(); + memset(&utmpx, 0, sizeof(utmpx)); + strncpy(utmpx.ut_id, utid, sizeof(utmpx.ut_id)); + utmpx.ut_type = LOGIN_PROCESS; + utxp = getutxid(&utmpx); + if (utxp) { + strcpy(utxp->ut_user, ""); + utxp->ut_type = DEAD_PROCESS; #ifdef _STRUCT___EXIT_STATUS - utxp->ut_exit.__e_termination = 0; - utxp->ut_exit.__e_exit = 0; + utxp->ut_exit.__e_termination = 0; + utxp->ut_exit.__e_exit = 0; #else - utxp->ut_exit.e_termination = 0; - utxp->ut_exit.e_exit = 0; + utxp->ut_exit.e_termination = 0; + utxp->ut_exit.e_exit = 0; #endif -#endif - gettimeofday(&tmp, NULL); - utxp->ut_tv.tv_sec = tmp.tv_sec; - utxp->ut_tv.tv_usec = tmp.tv_usec; - pututxline(utxp); + gettimeofday(&tmp, NULL); + utxp->ut_tv.tv_sec = tmp.tv_sec; + utxp->ut_tv.tv_usec = tmp.tv_usec; + pututxline(utxp); #ifdef WTMPX_FILE - updwtmpx(WTMPX_FILE, utxp); + updwtmpx(WTMPX_FILE, utxp); #endif - } - endutxent(); + } + endutxent(); } /* end of rmut */ #endif -#if !defined(HAVE_UTMPX_H) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 +#if !defined(HAVE_UTMPX) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43 static void rmut(void) { - int f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; + int f; + int found = 0; + struct utmp *u, *utmp; + int nutmp; + struct stat statbf; - f = open(utmpf, O_RDWR); + f = open(utmpf, O_RDWR); + if (f >= 0) { + fstat(f, &statbf); + utmp = (struct utmp *)malloc((unsigned)statbf.st_size); + if (!utmp) + syslog(LOG_ERR, "utmp malloc failed"); + if (statbf.st_size && utmp) { + nutmp = read(f, utmp, (int)statbf.st_size); + nutmp /= sizeof(struct utmp); + + for (u = utmp ; u < &utmp[nutmp] ; u++) { + if (SCMPN(u->ut_line, line+5) || + u->ut_name[0]==0) + continue; + lseek(f, ((long)u)-((long)utmp), L_SET); + SCPYN(u->ut_name, ""); +#ifdef HAVE_UT_HOST + SCPYN(u->ut_host, ""); +#endif + time(&u->ut_time); + write(f, u, sizeof(wtmp)); + found++; + } + } + close(f); + } + if (found) { + f = open(wtmpf, O_WRONLY|O_APPEND); if (f >= 0) { - fstat(f, &statbf); - utmp = (struct utmp *)malloc((unsigned)statbf.st_size); - if (!utmp) - syslog(LOG_ERR, "utmp malloc failed"); - if (statbf.st_size && utmp) { - nutmp = read(f, utmp, (int)statbf.st_size); - nutmp /= sizeof(struct utmp); - - for (u = utmp ; u < &utmp[nutmp] ; u++) { - if (SCMPN(u->ut_line, line+5) || - u->ut_name[0]==0) - continue; - lseek(f, ((long)u)-((long)utmp), L_SET); - SCPYN(u->ut_name, ""); + SCPYN(wtmp.ut_line, line+5); + SCPYN(wtmp.ut_name, ""); #ifdef HAVE_UT_HOST - SCPYN(u->ut_host, ""); + SCPYN(wtmp.ut_host, ""); #endif - time(&u->ut_time); - write(f, u, sizeof(wtmp)); - found++; - } - } - close(f); + time(&wtmp.ut_time); + write(f, &wtmp, sizeof(wtmp)); + close(f); } - if (found) { - f = open(wtmpf, O_WRONLY|O_APPEND); - if (f >= 0) { - SCPYN(wtmp.ut_line, line+5); - SCPYN(wtmp.ut_name, ""); -#ifdef HAVE_UT_HOST - SCPYN(wtmp.ut_host, ""); -#endif - time(&wtmp.ut_time); - write(f, &wtmp, sizeof(wtmp)); - close(f); - } - } - chmod(line, 0666); - chown(line, 0, 0); - line[strlen("/dev/")] = 'p'; - chmod(line, 0666); - chown(line, 0, 0); + } + chmod(line, 0666); + chown(line, 0, 0); + line[strlen("/dev/")] = 'p'; + chmod(line, 0666); + chown(line, 0, 0); } /* end of rmut */ #endif /* CRAY */ -#if defined(__hpux) && !defined(HAVE_UTMPX_H) +#if defined(__hpux) && !defined(HAVE_UTMPX) static void rmut (char *line) { - struct utmp utmp; - struct utmp *utptr; - int fd; /* for /etc/wtmp */ + struct utmp utmp; + struct utmp *utptr; + int fd; /* for /etc/wtmp */ - utmp.ut_type = USER_PROCESS; - strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); - setutent(); - utptr = getutid(&utmp); - /* write it out only if it exists */ - if (utptr) { - utptr->ut_type = DEAD_PROCESS; - utptr->ut_time = time((long *) 0); - pututline(utptr); - /* set wtmp entry if wtmp file exists */ - if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { - write(fd, utptr, sizeof(utmp)); - close(fd); - } + utmp.ut_type = USER_PROCESS; + strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); + setutent(); + utptr = getutid(&utmp); + /* write it out only if it exists */ + if (utptr) { + utptr->ut_type = DEAD_PROCESS; + utptr->ut_time = time((long *) 0); + pututline(utptr); + /* set wtmp entry if wtmp file exists */ + if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { + write(fd, utptr, sizeof(utmp)); + close(fd); } - endutent(); + } + endutent(); - chmod(line, 0666); - chown(line, 0, 0); - line[14] = line[13]; - line[13] = line[12]; - line[8] = 'm'; - line[9] = '/'; - line[10] = 'p'; - line[11] = 't'; - line[12] = 'y'; - chmod(line, 0666); - chown(line, 0, 0); + chmod(line, 0666); + chown(line, 0, 0); + line[14] = line[13]; + line[13] = line[12]; + line[8] = 'm'; + line[9] = '/'; + line[10] = 'p'; + line[11] = 't'; + line[12] = 'y'; + chmod(line, 0666); + chown(line, 0, 0); } #endif @@ -1770,7 +1491,7 @@ rmut (char *line) void cleanup(int sig) { -# ifdef CRAY +#ifdef _CRAY static int incleanup = 0; int t; int child_status; /* status of child process as returned by waitpid */ @@ -1798,22 +1519,22 @@ cleanup(int sig) } t = sigblock(sigmask(SIGCHLD)); if (incleanup) { - sigsetmask(t); - return; + sigsetmask(t); + return; } incleanup = 1; sigsetmask(t); t = cleantmp(&wtmp); setutent(); /* just to make sure */ -# endif /* CRAY */ +#endif /* CRAY */ rmut(line); close(ourpty); shutdown(net, 2); -# ifdef CRAY +#ifdef _CRAY if (t == 0) cleantmp(&wtmp); -# endif /* CRAY */ +#endif /* CRAY */ exit(1); } @@ -1822,7 +1543,7 @@ cleanup(int sig) void cleanup(int sig) { -#if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP) +#if defined(HAVE_UTMPX) || !defined(HAVE_LOGWTMP) rmut(); #ifdef HAVE_VHANGUP vhangup(); /* XXX */ @@ -1845,7 +1566,7 @@ cleanup(int sig) #endif /* PARENT_DOES_UTMP */ -#if defined(PARENT_DOES_UTMP) +#ifdef PARENT_DOES_UTMP /* * _utmp_sig_rcv * utmp_sig_init @@ -1859,28 +1580,28 @@ cleanup(int sig) static int caught=0; /* NZ when signal intercepted */ static void (*func)(); /* address of previous handler */ - void +void _utmp_sig_rcv(sig) - int sig; + int sig; { - caught = 1; - signal(SIGUSR1, func); + caught = 1; + signal(SIGUSR1, func); } - void +void utmp_sig_init() { - /* - * register signal handler for UTMP creation - */ - if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) - fatalperror(net, "telnetd/signal"); + /* + * register signal handler for UTMP creation + */ + if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) + fatalperror(net, "telnetd/signal"); } - void +void utmp_sig_reset() { - signal(SIGUSR1, func); /* reset handler to default */ + signal(SIGUSR1, func); /* reset handler to default */ } # ifdef __hpux @@ -1888,44 +1609,44 @@ utmp_sig_reset() # define sigon() /* do nothing */ # endif - void +void utmp_sig_wait() { - /* - * Wait for parent to write our utmp entry. + /* + * Wait for parent to write our utmp entry. */ - sigoff(); - while (caught == 0) { - pause(); /* wait until we get a signal (sigon) */ - sigoff(); /* turn off signals while we check caught */ - } - sigon(); /* turn on signals again */ + sigoff(); + while (caught == 0) { + pause(); /* wait until we get a signal (sigon) */ + sigoff(); /* turn off signals while we check caught */ + } + sigon(); /* turn on signals again */ } - void +void utmp_sig_notify(pid) { - kill(pid, SIGUSR1); + kill(pid, SIGUSR1); } -# ifdef CRAY +#ifdef _CRAY static int gotsigjob = 0; /*ARGSUSED*/ - void +void sigjob(sig) - int sig; + int sig; { - int jid; - struct jobtemp *jp; + int jid; + struct jobtemp *jp; - while ((jid = waitjob(NULL)) != -1) { - if (jid == 0) { - return; - } - gotsigjob++; - jobend(jid, NULL, NULL); + while ((jid = waitjob(NULL)) != -1) { + if (jid == 0) { + return; } + gotsigjob++; + jobend(jid, NULL, NULL); + } } /* @@ -1934,20 +1655,20 @@ sigjob(sig) * to find the correct $TMPDIR to cleanup. */ - struct utmp * +struct utmp * jid_getutid(jid) - int jid; + int jid; { - struct utmp *cur = NULL; + struct utmp *cur = NULL; - setutent(); /* just to make sure */ - while (cur = getutent()) { - if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { - return(cur); - } + setutent(); /* just to make sure */ + while (cur = getutent()) { + if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { + return(cur); } + } - return(0); + return(0); } /* @@ -1958,132 +1679,132 @@ jid_getutid(jid) * when this is called the second time it will wait * for the signal that the job is done. */ - int +int cleantmp(wtp) - struct utmp *wtp; + struct utmp *wtp; { - struct utmp *utp; - static int first = 1; - int mask, omask, ret; - extern struct utmp *getutid (const struct utmp *_Id); + struct utmp *utp; + static int first = 1; + int mask, omask, ret; + extern struct utmp *getutid (const struct utmp *_Id); - mask = sigmask(WJSIGNAL); + mask = sigmask(WJSIGNAL); - if (first == 0) { - omask = sigblock(mask); - while (gotsigjob == 0) - sigpause(omask); - return(1); - } - first = 0; - setutent(); /* just to make sure */ - - utp = getutid(wtp); - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } - /* - * Nothing to clean up if the user shell was never started. - */ - if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) - return(1); - - /* - * Block the WJSIGNAL while we are in jobend(). - */ + if (first == 0) { omask = sigblock(mask); - ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); - sigsetmask(omask); - return(ret); + while (gotsigjob == 0) + sigpause(omask); + return(1); + } + first = 0; + setutent(); /* just to make sure */ + + utp = getutid(wtp); + if (utp == 0) { + syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); + return(-1); + } + /* + * Nothing to clean up if the user shell was never started. + */ + if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) + return(1); + + /* + * Block the WJSIGNAL while we are in jobend(). + */ + omask = sigblock(mask); + ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); + sigsetmask(omask); + return(ret); } - int +int jobend(jid, path, user) - int jid; - char *path; - char *user; + int jid; + char *path; + char *user; { - static int saved_jid = 0; - static int pty_saved_jid = 0; - static char saved_path[sizeof(wtmp.ut_tpath)+1]; - static char saved_user[sizeof(wtmp.ut_user)+1]; + static int saved_jid = 0; + static int pty_saved_jid = 0; + static char saved_path[sizeof(wtmp.ut_tpath)+1]; + static char saved_user[sizeof(wtmp.ut_user)+1]; - /* - * this little piece of code comes into play - * only when ptyreconnect is used to reconnect - * to an previous session. - * - * this is the only time when the - * "saved_jid != jid" code is executed. - */ + /* + * this little piece of code comes into play + * only when ptyreconnect is used to reconnect + * to an previous session. + * + * this is the only time when the + * "saved_jid != jid" code is executed. + */ - if ( saved_jid && saved_jid != jid ) { - if (!path) { /* called from signal handler */ - pty_saved_jid = jid; - } else { - pty_saved_jid = saved_jid; - } + if ( saved_jid && saved_jid != jid ) { + if (!path) { /* called from signal handler */ + pty_saved_jid = jid; + } else { + pty_saved_jid = saved_jid; + } + } + + if (path) { + strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); + strncpy(saved_user, user, sizeof(wtmp.ut_user)); + saved_path[sizeof(saved_path)] = '\0'; + saved_user[sizeof(saved_user)] = '\0'; + } + if (saved_jid == 0) { + saved_jid = jid; + return(0); + } + + /* if the jid has changed, get the correct entry from the utmp file */ + + if ( saved_jid != jid ) { + struct utmp *utp = NULL; + struct utmp *jid_getutid(); + + utp = jid_getutid(pty_saved_jid); + + if (utp == 0) { + syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); + return(-1); } - if (path) { - strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); - strncpy(saved_user, user, sizeof(wtmp.ut_user)); - saved_path[sizeof(saved_path)] = '\0'; - saved_user[sizeof(saved_user)] = '\0'; - } - if (saved_jid == 0) { - saved_jid = jid; - return(0); - } - - /* if the jid has changed, get the correct entry from the utmp file */ - - if ( saved_jid != jid ) { - struct utmp *utp = NULL; - struct utmp *jid_getutid(); - - utp = jid_getutid(pty_saved_jid); - - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } - - cleantmpdir(jid, utp->ut_tpath, utp->ut_user); - return(1); - } - - cleantmpdir(jid, saved_path, saved_user); + cleantmpdir(jid, utp->ut_tpath, utp->ut_user); return(1); + } + + cleantmpdir(jid, saved_path, saved_user); + return(1); } /* * Fork a child process to clean up the TMPDIR */ cleantmpdir(jid, tpath, user) - int jid; - char *tpath; - char *user; + int jid; + char *tpath; + char *user; { - switch(fork()) { - case -1: - syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", - tpath); - break; - case 0: - execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); - syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", - tpath, CLEANTMPCMD); - exit(1); - default: - /* - * Forget about child. We will exit, and - * /etc/init will pick it up. - */ - break; - } + switch(fork()) { + case -1: + syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", + tpath); + break; + case 0: + execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); + syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", + tpath, CLEANTMPCMD); + exit(1); + default: + /* + * Forget about child. We will exit, and + * /etc/init will pick it up. + */ + break; + } } -# endif /* CRAY */ -#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ +#endif /* CRAY */ +#endif /* defined(PARENT_DOES_UTMP) */ diff --git a/appl/telnet/telnetd/telnetd.c b/appl/telnet/telnetd/telnetd.c index 9fbc6b83b..b61747c1a 100644 --- a/appl/telnet/telnetd/telnetd.c +++ b/appl/telnet/telnetd/telnetd.c @@ -31,47 +31,23 @@ * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include -#endif -#ifdef SOCKS -#include -#endif +#include "telnetd.h" RCSID("$Id$"); -#include "telnetd.h" -#include "pathnames.h" - -#if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY) -/* - * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can - * use it to tell us to turn off all the socket security code, - * since that is only used in UNICOS 7.0 and later. - */ -# undef _SC_CRAY_SECURE_SYS -#endif - -#if defined(_SC_CRAY_SECURE_SYS) +#ifdef _SC_CRAY_SECURE_SYS #include #include -# ifdef SO_SEC_MULTI /* 8.0 code */ #include #include -# endif /* SO_SEC_MULTI */ int secflag; char tty_dev[16]; struct secdev dv; struct sysv sysv; -# ifdef SO_SEC_MULTI /* 8.0 code */ struct socksec ss; -# else /* SO_SEC_MULTI */ /* 7.0 code */ -struct socket_security ss; -# endif /* SO_SEC_MULTI */ #endif /* _SC_CRAY_SECURE_SYS */ -#if defined(AUTHENTICATION) -#include +#ifdef AUTHENTICATION int auth_level = 0; #endif @@ -87,7 +63,7 @@ int registerd_host_only = 0; #ifdef HAVE_SYS_STREAM_H #include #endif -#if defined(_AIX) +#ifdef _AIX #include #endif # ifdef HAVE_SYS_STRTTY_H @@ -104,6 +80,12 @@ int registerd_host_only = 0; # ifdef HAVE_SYS_PTYVAR_H # include # endif +#ifdef HAVE_CURSES_H +#include +#endif +#ifdef HAVE_TERM_H +#include +#endif /* * Because of the way ptyibuf is used with streams messages, we need @@ -132,7 +114,7 @@ char ptyibuf2[BUFSIZ]; int hostinfo = 1; /* do we print login banner? */ -#ifdef CRAY +#ifdef _CRAY extern int newmap; /* nonzero if \n maps to ^M^J */ int lowpty = 0, highpty; /* low, high pty numbers */ #endif /* CRAY */ @@ -149,373 +131,354 @@ extern void usage (void); * passed off to getopt(). */ char valid_opts[] = { - 'd', ':', 'h', 'k', 'n', 'S', ':', 'u', ':', 'U', + 'B', 'd', ':', 'h', 'k', 'l', 'n', 'S', ':', 'u', ':', 'U', #ifdef AUTHENTICATION - 'a', ':', 'X', ':', + 'a', ':', 'X', ':', #endif #ifdef DIAGNOSTICS - 'D', ':', + 'D', ':', #endif -#ifdef LINEMODE - 'l', +#ifdef _CRAY + 'r', ':', #endif -#ifdef CRAY - 'r', ':', -#endif - 'L', ':', + 'L', ':', #ifdef AUTHENTICATION - 'y', - 'z', + 'y', + 'z', #endif - '\0' + '\0' }; void doit(struct sockaddr_in*); int main(int argc, char **argv) { - struct sockaddr_in from; - int on = 1, fromlen; - int ch; + struct sockaddr_in from; + int on = 1, fromlen; + int ch; #if defined(IPPROTO_IP) && defined(IP_TOS) - int tos = -1; + int tos = -1; #endif #ifdef ENCRYPTION - extern int des_check_key; - des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */ + extern int des_check_key; + des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */ #endif - pfrontp = pbackp = ptyobuf; - netip = netibuf; - nfrontp = nbackp = netobuf; + pfrontp = pbackp = ptyobuf; + netip = netibuf; + nfrontp = nbackp = netobuf; - progname = *argv; -#if defined(ENCRYPTION) - nclearto = 0; + progname = *argv; +#ifdef ENCRYPTION + nclearto = 0; #endif -#ifdef CRAY - /* - * Get number of pty's before trying to process options, - * which may include changing pty range. - */ - highpty = getnpty(); +#ifdef _CRAY + /* + * Get number of pty's before trying to process options, + * which may include changing pty range. + */ + highpty = getnpty(); #endif /* CRAY */ - while ((ch = getopt(argc, argv, valid_opts)) != EOF) { - switch(ch) { + while ((ch = getopt(argc, argv, valid_opts)) != EOF) { + switch(ch) { #ifdef AUTHENTICATION - case 'a': - /* - * Check for required authentication level - */ - if (strcmp(optarg, "debug") == 0) { - auth_debug_mode = 1; - } else if (strcasecmp(optarg, "none") == 0) { - auth_level = 0; - } else if (strcasecmp(optarg, "otp") == 0) { - auth_level = 0; - require_otp = 1; - } else if (strcasecmp(optarg, "other") == 0) { - auth_level = AUTH_OTHER; - } else if (strcasecmp(optarg, "user") == 0) { - auth_level = AUTH_USER; - } else if (strcasecmp(optarg, "valid") == 0) { - auth_level = AUTH_VALID; - } else if (strcasecmp(optarg, "off") == 0) { - /* - * This hack turns off authentication - */ - auth_level = -1; - } else { - fprintf(stderr, - "telnetd: unknown authorization level for -a\n"); - } - break; + case 'a': + /* + * Check for required authentication level + */ + if (strcmp(optarg, "debug") == 0) { + auth_debug_mode = 1; + } else if (strcasecmp(optarg, "none") == 0) { + auth_level = 0; + } else if (strcasecmp(optarg, "otp") == 0) { + auth_level = 0; + require_otp = 1; + } else if (strcasecmp(optarg, "other") == 0) { + auth_level = AUTH_OTHER; + } else if (strcasecmp(optarg, "user") == 0) { + auth_level = AUTH_USER; + } else if (strcasecmp(optarg, "valid") == 0) { + auth_level = AUTH_VALID; + } else if (strcasecmp(optarg, "off") == 0) { + /* + * This hack turns off authentication + */ + auth_level = -1; + } else { + fprintf(stderr, + "telnetd: unknown authorization level for -a\n"); + } + break; #endif /* AUTHENTICATION */ - case 'd': - if (strcmp(optarg, "ebug") == 0) { - debug++; - break; - } - usage(); - /* NOTREACHED */ - break; + case 'B': /* BFTP mode is not supported any more */ + break; + case 'd': + if (strcmp(optarg, "ebug") == 0) { + debug++; + break; + } + usage(); + /* NOTREACHED */ + break; #ifdef DIAGNOSTICS - case 'D': - /* - * Check for desired diagnostics capabilities. - */ - if (!strcmp(optarg, "report")) { - diagnostic |= TD_REPORT|TD_OPTIONS; - } else if (!strcmp(optarg, "exercise")) { - diagnostic |= TD_EXERCISE; - } else if (!strcmp(optarg, "netdata")) { - diagnostic |= TD_NETDATA; - } else if (!strcmp(optarg, "ptydata")) { - diagnostic |= TD_PTYDATA; - } else if (!strcmp(optarg, "options")) { - diagnostic |= TD_OPTIONS; - } else { - usage(); - /* NOT REACHED */ - } - break; + case 'D': + /* + * Check for desired diagnostics capabilities. + */ + if (!strcmp(optarg, "report")) { + diagnostic |= TD_REPORT|TD_OPTIONS; + } else if (!strcmp(optarg, "exercise")) { + diagnostic |= TD_EXERCISE; + } else if (!strcmp(optarg, "netdata")) { + diagnostic |= TD_NETDATA; + } else if (!strcmp(optarg, "ptydata")) { + diagnostic |= TD_PTYDATA; + } else if (!strcmp(optarg, "options")) { + diagnostic |= TD_OPTIONS; + } else { + usage(); + /* NOT REACHED */ + } + break; #endif /* DIAGNOSTICS */ - case 'h': - hostinfo = 0; - break; + case 'h': + hostinfo = 0; + break; -#ifdef LINEMODE - case 'l': - alwayslinemode = 1; - break; -#endif /* LINEMODE */ + case 'k': /* Linemode is not supported any more */ + case 'l': + break; - case 'k': -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - lmodetype = NO_AUTOKLUDGE; -#else - /* ignore -k option if built without kludge linemode */ -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - break; + case 'n': + keepalive = 0; + break; - case 'n': - keepalive = 0; - break; +#ifdef _CRAY + case 'r': + { + char *strchr(); + char *c; -#ifdef CRAY - case 'r': - { - char *strchr(); - char *c; - - /* - * Allow the specification of alterations - * to the pty search range. It is legal to - * specify only one, and not change the - * other from its default. - */ - c = strchr(optarg, '-'); - if (c) { - *c++ = '\0'; - highpty = atoi(c); - } - if (*optarg != '\0') - lowpty = atoi(optarg); - if ((lowpty > highpty) || (lowpty < 0) || - (highpty > 32767)) { - usage(); - /* NOT REACHED */ - } - break; - } + /* + * Allow the specification of alterations + * to the pty search range. It is legal to + * specify only one, and not change the + * other from its default. + */ + c = strchr(optarg, '-'); + if (c) { + *c++ = '\0'; + highpty = atoi(c); + } + if (*optarg != '\0') + lowpty = atoi(optarg); + if ((lowpty > highpty) || (lowpty < 0) || + (highpty > 32767)) { + usage(); + /* NOT REACHED */ + } + break; + } #endif /* CRAY */ - case 'S': + case 'S': #ifdef HAS_GETTOS - if ((tos = parsetos(optarg, "tcp")) < 0) - fprintf(stderr, "%s%s%s\n", - "telnetd: Bad TOS argument '", optarg, - "'; will try to use default TOS"); + if ((tos = parsetos(optarg, "tcp")) < 0) + fprintf(stderr, "%s%s%s\n", + "telnetd: Bad TOS argument '", optarg, + "'; will try to use default TOS"); #else - fprintf(stderr, "%s%s\n", "TOS option unavailable; ", - "-S flag not supported\n"); + fprintf(stderr, "%s%s\n", "TOS option unavailable; ", + "-S flag not supported\n"); #endif - break; + break; - case 'u': - utmp_len = atoi(optarg); - break; + case 'u': + utmp_len = atoi(optarg); + break; - case 'U': - registerd_host_only = 1; - break; + case 'U': + registerd_host_only = 1; + break; #ifdef AUTHENTICATION - case 'X': - /* - * Check for invalid authentication types - */ - auth_disable_name(optarg); - break; - case 'y': - no_warn = 1; - break; - case 'z': - log_unauth = 1; - break; + case 'X': + /* + * Check for invalid authentication types + */ + auth_disable_name(optarg); + break; + case 'y': + no_warn = 1; + break; + case 'z': + log_unauth = 1; + break; #endif /* AUTHENTICATION */ - case 'L': - new_login = optarg; - break; + case 'L': + new_login = optarg; + break; - default: - fprintf(stderr, "telnetd: %c: unknown option\n", ch); - /* FALLTHROUGH */ - case '?': - usage(); - /* NOTREACHED */ - } + default: + fprintf(stderr, "telnetd: %c: unknown option\n", ch); + /* FALLTHROUGH */ + case '?': + usage(); + /* NOTREACHED */ } + } - argc -= optind; - argv += optind; + argc -= optind; + argv += optind; - if (debug) { - int port; - struct servent *sp; + if (debug) { + int port; + struct servent *sp; - if (argc > 1) { - usage (); - } else if (argc == 1) { - sp = getservbyname (*argv, "tcp"); - if (sp) - port = sp->s_port; - else - port = htons(atoi(*argv)); - } else { - port = k_getportbyname ("telnet", "tcp", htons(23)); - } - mini_inetd (port); - } else if (argc > 0) { - usage(); - /* NOT REACHED */ + if (argc > 1) { + usage (); + } else if (argc == 1) { + sp = getservbyname (*argv, "tcp"); + if (sp) + port = sp->s_port; + else + port = htons(atoi(*argv)); + } else { + port = k_getportbyname ("telnet", "tcp", htons(23)); } + mini_inetd (port); + } else if (argc > 0) { + usage(); + /* NOT REACHED */ + } -#if defined(_SC_CRAY_SECURE_SYS) - secflag = sysconf(_SC_CRAY_SECURE_SYS); +#ifdef _SC_CRAY_SECURE_SYS + secflag = sysconf(_SC_CRAY_SECURE_SYS); + + /* + * Get socket's security label + */ + if (secflag) { + int szss = sizeof(ss); + int sock_multi; + int szi = sizeof(int); + + memset(&dv, 0, sizeof(dv)); + + if (getsysv(&sysv, sizeof(struct sysv)) != 0) { + perror("getsysv"); + exit(1); + } /* - * Get socket's security label + * Get socket security label and set device values + * {security label to be set on ttyp device} */ - if (secflag) { - int szss = sizeof(ss); #ifdef SO_SEC_MULTI /* 8.0 code */ - int sock_multi; - int szi = sizeof(int); -#endif /* SO_SEC_MULTI */ - - memset(&dv, 0, sizeof(dv)); - - if (getsysv(&sysv, sizeof(struct sysv)) != 0) { - perror("getsysv"); - exit(1); - } - - /* - * Get socket security label and set device values - * {security label to be set on ttyp device} - */ -#ifdef SO_SEC_MULTI /* 8.0 code */ - if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, - (void *)&ss, &szss) < 0) || - (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, - (void *)&sock_multi, &szi) < 0)) { - perror("getsockopt"); - exit(1); - } else { - dv.dv_actlvl = ss.ss_actlabel.lt_level; - dv.dv_actcmp = ss.ss_actlabel.lt_compart; - if (!sock_multi) { - dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; - dv.dv_valcmp = dv.dv_actcmp; - } else { - dv.dv_minlvl = ss.ss_minlabel.lt_level; - dv.dv_maxlvl = ss.ss_maxlabel.lt_level; - dv.dv_valcmp = ss.ss_maxlabel.lt_compart; - } - dv.dv_devflg = 0; - } -#else /* SO_SEC_MULTI */ /* 7.0 code */ - if (getsockopt(0, SOL_SOCKET, SO_SECURITY, - (void *)&ss, &szss) >= 0) { - dv.dv_actlvl = ss.ss_slevel; - dv.dv_actcmp = ss.ss_compart; - dv.dv_minlvl = ss.ss_minlvl; - dv.dv_maxlvl = ss.ss_maxlvl; - dv.dv_valcmp = ss.ss_maxcmp; - } -#endif /* SO_SEC_MULTI */ + if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, + (void *)&ss, &szss) < 0) || + (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, + (void *)&sock_multi, &szi) < 0)) { + perror("getsockopt"); + exit(1); + } else { + dv.dv_actlvl = ss.ss_actlabel.lt_level; + dv.dv_actcmp = ss.ss_actlabel.lt_compart; + if (!sock_multi) { + dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; + dv.dv_valcmp = dv.dv_actcmp; + } else { + dv.dv_minlvl = ss.ss_minlabel.lt_level; + dv.dv_maxlvl = ss.ss_maxlabel.lt_level; + dv.dv_valcmp = ss.ss_maxlabel.lt_compart; + } + dv.dv_devflg = 0; } +#else /* SO_SEC_MULTI */ /* 7.0 code */ + if (getsockopt(0, SOL_SOCKET, SO_SECURITY, + (void *)&ss, &szss) >= 0) { + dv.dv_actlvl = ss.ss_slevel; + dv.dv_actcmp = ss.ss_compart; + dv.dv_minlvl = ss.ss_minlvl; + dv.dv_maxlvl = ss.ss_maxlvl; + dv.dv_valcmp = ss.ss_maxcmp; + } +#endif /* SO_SEC_MULTI */ + } #endif /* _SC_CRAY_SECURE_SYS */ - openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); - fromlen = sizeof (from); - if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { - fprintf(stderr, "%s: ", progname); - perror("getpeername"); - _exit(1); - } - if (keepalive && - setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, - (void *)&on, sizeof (on)) < 0) { - syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); - } + openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + fprintf(stderr, "%s: ", progname); + perror("getpeername"); + _exit(1); + } + if (keepalive && + setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, + (void *)&on, sizeof (on)) < 0) { + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); + } #if defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT) - { -# if defined(HAS_GETTOS) - struct tosent *tp; - if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) - tos = tp->t_tos; + { +# ifdef 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(0, IPPROTO_IP, IP_TOS, - (void *)&tos, sizeof(tos)) < 0) - && (errno != ENOPROTOOPT) ) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); - } + if (tos < 0) + tos = 020; /* Low Delay bit */ + if (tos + && (setsockopt(0, IPPROTO_IP, IP_TOS, + (void *)&tos, sizeof(tos)) < 0) + && (errno != ENOPROTOOPT) ) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ - net = 0; - doit(&from); - /* NOTREACHED */ + net = 0; + doit(&from); + /* NOTREACHED */ } /* end of main */ - void +void usage() { - fprintf(stderr, "Usage: telnetd"); + fprintf(stderr, "Usage: telnetd"); #ifdef AUTHENTICATION - fprintf(stderr, " [-a (debug|other|otp|user|valid|off|none)]\n\t"); + fprintf(stderr, " [-a (debug|other|otp|user|valid|off|none)]\n\t"); #endif - fprintf(stderr, " [-debug]"); + fprintf(stderr, " [-debug]"); #ifdef DIAGNOSTICS - fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); + fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); #endif #ifdef AUTHENTICATION - fprintf(stderr, " [-edebug]"); + fprintf(stderr, " [-edebug]"); #endif - fprintf(stderr, " [-h]"); -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - fprintf(stderr, " [-k]"); + fprintf(stderr, " [-h]"); + fprintf(stderr, " [-L login]"); + fprintf(stderr, " [-n]"); +#ifdef _CRAY + fprintf(stderr, " [-r[lowpty]-[highpty]]"); #endif -#ifdef LINEMODE - fprintf(stderr, " [-l]"); -#endif - fprintf(stderr, " [-L login]"); - fprintf(stderr, " [-n]"); -#ifdef CRAY - fprintf(stderr, " [-r[lowpty]-[highpty]]"); -#endif - fprintf(stderr, "\n\t"); + fprintf(stderr, "\n\t"); #ifdef HAS_GETTOS - fprintf(stderr, " [-S tos]"); + fprintf(stderr, " [-S tos]"); #endif #ifdef AUTHENTICATION - fprintf(stderr, " [-X auth-type] [-y] [-z]"); + fprintf(stderr, " [-X auth-type] [-y] [-z]"); #endif - fprintf(stderr, " [-u utmp_hostname_length] [-U]"); - fprintf(stderr, " [port]\n"); - exit(1); + fprintf(stderr, " [-u utmp_hostname_length] [-U]"); + fprintf(stderr, " [port]\n"); + exit(1); } /* @@ -525,18 +488,17 @@ usage() * Output is the variable terminaltype filled in. */ static unsigned char ttytype_sbbuf[] = { - IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE + IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE }; - int -getterminaltype(name) - char *name; +int +getterminaltype(char *name) { int retval = -1; void _gettermname(); settimer(baseline); -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION /* * Handle the Authentication option before we do anything else. */ @@ -548,7 +510,7 @@ getterminaltype(name) } #endif -#if defined(ENCRYPTION) +#ifdef ENCRYPTION send_will(TELOPT_ENCRYPT, 1); send_do(TELOPT_ENCRYPT, 1); /* esc@magic.fi */ #endif @@ -558,7 +520,7 @@ getterminaltype(name) send_do(TELOPT_NEW_ENVIRON, 1); send_do(TELOPT_OLD_ENVIRON, 1); while ( -#if defined(ENCRYPTION) +#ifdef ENCRYPTION his_do_dont_is_changing(TELOPT_ENCRYPT) || #endif his_will_wont_is_changing(TELOPT_TTYPE) || @@ -568,7 +530,7 @@ getterminaltype(name) his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { ttloop(); } -#if defined(ENCRYPTION) +#ifdef ENCRYPTION /* * Wait for the negotiation of what type of encryption we can * send with. If autoencrypt is not set, this will just return. @@ -579,42 +541,37 @@ getterminaltype(name) #endif if (his_state_is_will(TELOPT_TSPEED)) { static unsigned char sb[] = - { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; + { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + net_write (sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_XDISPLOC)) { static unsigned char sb[] = - { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; + { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + net_write (sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_NEW_ENVIRON)) { static unsigned char sb[] = - { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; + { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + net_write (sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { static unsigned char sb[] = - { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; + { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; + net_write (sb, sizeof sb); DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); } if (his_state_is_will(TELOPT_TTYPE)) { - memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; + net_write (ttytype_sbbuf, sizeof ttytype_sbbuf); DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); + sizeof ttytype_sbbuf - 2);); } if (his_state_is_will(TELOPT_TSPEED)) { while (sequenceIs(tspeedsubopt, baseline)) @@ -665,7 +622,7 @@ getterminaltype(name) * RFC1091 compliant telnets will cycle back to * the start of the list. */ - _gettermname(); + _gettermname(); if (strncmp(first, terminaltype, sizeof(first)) != 0) strcpy(terminaltype, first); break; @@ -676,7 +633,7 @@ getterminaltype(name) return(retval); } /* end of getterminaltype */ - void +void _gettermname() { /* @@ -687,17 +644,15 @@ _gettermname() if (his_state_is_wont(TELOPT_TTYPE)) return; settimer(baseline); - memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; + net_write (ttytype_sbbuf, sizeof ttytype_sbbuf); DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); + sizeof ttytype_sbbuf - 2);); while (sequenceIs(ttypesubopt, baseline)) ttloop(); } - int -terminaltypeok(s) - char *s; +int +terminaltypeok(char *s) { char buf[1024]; @@ -726,562 +681,504 @@ extern void telnet (int, int); /* * Get a pty, scan input lines. */ -void doit(struct sockaddr_in *who) +void +doit(struct sockaddr_in *who) { - const char *host; - int t; - struct hostent *hp; - int level; - int ptynum; - char user_name[256]; + char *host; + struct hostent *hp; + int level; + int ptynum; + char user_name[256]; - /* - * Find an available pty to use. - */ - ourpty = getpty(&ptynum); - if (ourpty < 0) - fatal(net, "All network ports in use"); - set_utid(); + /* + * Find an available pty to use. + */ + ourpty = getpty(&ptynum); + if (ourpty < 0) + fatal(net, "All network ports in use"); + set_utid(); -#if defined(_SC_CRAY_SECURE_SYS) - /* - * set ttyp line security label - */ - if (secflag) { - char slave_dev[16]; +#ifdef _SC_CRAY_SECURE_SYS + /* + * set ttyp line security label + */ + if (secflag) { + char slave_dev[16]; - snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum); - if (setdevs(tty_dev, &dv) < 0) - fatal(net, "cannot set pty security"); - snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum); - if (setdevs(slave_dev, &dv) < 0) - fatal(net, "cannot set tty security"); - } + snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum); + if (setdevs(tty_dev, &dv) < 0) + fatal(net, "cannot set pty security"); + snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum); + if (setdevs(slave_dev, &dv) < 0) + fatal(net, "cannot set tty security"); + } #endif /* _SC_CRAY_SECURE_SYS */ - /* get name of connected client */ - hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), - who->sin_family); + /* get name of connected client */ + hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), + who->sin_family); - if (hp == NULL && registerd_host_only) { - fatal(net, "Couldn't resolve your address into a host name.\r\n\ - Please contact your net administrator"); - } else if (hp) { - host = hp->h_name; - } else { - host = inet_ntoa(who->sin_addr); - } - /* - * We must make a copy because Kerberos is probably going - * to also do a gethost* and overwrite the static data... - */ - strncpy(remote_host_name, host, sizeof(remote_host_name)-1); - remote_host_name[sizeof(remote_host_name)-1] = 0; - host = remote_host_name; + if (hp == NULL && registerd_host_only) { + fatal(net, "Couldn't resolve your address into a host name.\r\n\ +Please contact your net administrator"); + } else if (hp) { + host = hp->h_name; + } else { + host = inet_ntoa(who->sin_addr); + } + /* + * We must make a copy because Kerberos is probably going + * to also do a gethost* and overwrite the static data... + */ + strncpy(remote_host_name, host, sizeof(remote_host_name)-1); + remote_host_name[sizeof(remote_host_name)-1] = 0; + host = remote_host_name; - k_gethostname(host_name, sizeof (host_name)); - hostname = host_name; + k_gethostname(host_name, sizeof (host_name)); + hostname = host_name; #ifndef abs #define abs(x) ((x < 0) ? (-x) : x) #endif - /* Only trim if too long (and possible) */ - if (strlen(remote_host_name) > abs(utmp_len)) { - char *domain = strchr(host_name, '.'); - char *p = strchr(remote_host_name, '.'); - if (domain && p && (strcmp(p, domain) == 0)) - *p = 0; /* remove domain part */ - } + /* Only trim if too long (and possible) */ + if (strlen(remote_host_name) > abs(utmp_len)) { + char *domain = strchr(host_name, '.'); + char *p = strchr(remote_host_name, '.'); + if (domain && p && (strcmp(p, domain) == 0)) + *p = 0; /* remove domain part */ + } - /* - * If hostname still doesn't fit utmp, use ipaddr. - */ - if (strlen(remote_host_name) > abs(utmp_len)) - strncpy(remote_host_name, - inet_ntoa(who->sin_addr), - sizeof(remote_host_name)-1); + /* + * If hostname still doesn't fit utmp, use ipaddr. + */ + if (strlen(remote_host_name) > abs(utmp_len)) + strncpy(remote_host_name, + inet_ntoa(who->sin_addr), + sizeof(remote_host_name)-1); -#if defined(AUTHENTICATION) || defined(ENCRYPTION) - auth_encrypt_init(hostname, host, "TELNETD", 1); +#ifdef AUTHENTICATION + auth_encrypt_init(hostname, host, "TELNETD", 1); #endif - init_env(); - /* - * get terminal type. - */ - *user_name = 0; - level = getterminaltype(user_name); - setenv("TERM", terminaltype ? terminaltype : "network", 1); + init_env(); + /* + * get terminal type. + */ + *user_name = 0; + level = getterminaltype(user_name); + setenv("TERM", terminaltype ? terminaltype : "network", 1); - /* - * Start up the login process on the slave side of the terminal - */ - startslave(host, level, user_name); + /* + * Start up the login process on the slave side of the terminal + */ + startslave(host, level, user_name); -#if defined(_SC_CRAY_SECURE_SYS) - if (secflag) { - if (setulvl(dv.dv_actlvl) < 0) - fatal(net,"cannot setulvl()"); - if (setucmp(dv.dv_actcmp) < 0) - fatal(net, "cannot setucmp()"); - } +#ifdef _SC_CRAY_SECURE_SYS + if (secflag) { + if (setulvl(dv.dv_actlvl) < 0) + fatal(net,"cannot setulvl()"); + if (setucmp(dv.dv_actcmp) < 0) + fatal(net, "cannot setucmp()"); + } #endif /* _SC_CRAY_SECURE_SYS */ - telnet(net, ourpty); /* begin server processing */ - /*NOTREACHED*/ + telnet(net, ourpty); /* begin server processing */ + /*NOTREACHED*/ } /* end of doit */ /* * Main loop. Select from pty and network, and * hand data to telnet receiver finite state machine. */ - void -telnet(f, p) - int f, p; +void +telnet(int f, int p) { - int on = 1; + int on = 1; #define TABBUFSIZ 512 - char defent[TABBUFSIZ]; - char defstrs[TABBUFSIZ]; + char defent[TABBUFSIZ]; + char defstrs[TABBUFSIZ]; #undef TABBUFSIZ - char *HE; - char *HN; - char *IM; - void netflush(); - int nfd; + char *HE; + char *HN; + char *IM; + void netflush(); + int nfd; - /* - * Initialize the slc mapping table. - */ - get_slc_defaults(); + /* + * Initialize the slc mapping table. + */ + get_slc_defaults(); - /* - * Do some tests where it is desireable to wait for a response. - * Rather than doing them slowly, one at a time, do them all - * at once. - */ - if (my_state_is_wont(TELOPT_SGA)) - send_will(TELOPT_SGA, 1); - /* - * Is the client side a 4.2 (NOT 4.3) system? We need to know this - * because 4.2 clients are unable to deal with TCP urgent data. - * - * To find out, we send out a "DO ECHO". If the remote system - * answers "WILL ECHO" it is probably a 4.2 client, and we note - * that fact ("WILL ECHO" ==> that the client will echo what - * WE, the server, sends it; it does NOT mean that the client will - * echo the terminal input). - */ - send_do(TELOPT_ECHO, 1); + /* + * Do some tests where it is desireable to wait for a response. + * Rather than doing them slowly, one at a time, do them all + * at once. + */ + if (my_state_is_wont(TELOPT_SGA)) + send_will(TELOPT_SGA, 1); + /* + * Is the client side a 4.2 (NOT 4.3) system? We need to know this + * because 4.2 clients are unable to deal with TCP urgent data. + * + * To find out, we send out a "DO ECHO". If the remote system + * answers "WILL ECHO" it is probably a 4.2 client, and we note + * that fact ("WILL ECHO" ==> that the client will echo what + * WE, the server, sends it; it does NOT mean that the client will + * echo the terminal input). + */ + send_do(TELOPT_ECHO, 1); -#ifdef LINEMODE - if (his_state_is_wont(TELOPT_LINEMODE)) { - /* Query the peer for linemode support by trying to negotiate - * the linemode option. - */ - linemode = 0; - editmode = 0; - send_do(TELOPT_LINEMODE, 1); /* send do linemode */ - } -#endif /* LINEMODE */ + /* + * Send along a couple of other options that we wish to negotiate. + */ + send_do(TELOPT_NAWS, 1); + send_will(TELOPT_STATUS, 1); + flowmode = 1; /* default flow control state */ + restartany = -1; /* uninitialized... */ + send_do(TELOPT_LFLOW, 1); - /* - * Send along a couple of other options that we wish to negotiate. - */ - send_do(TELOPT_NAWS, 1); - send_will(TELOPT_STATUS, 1); - flowmode = 1; /* default flow control state */ - restartany = -1; /* uninitialized... */ - send_do(TELOPT_LFLOW, 1); + /* + * Spin, waiting for a response from the DO ECHO. However, + * some REALLY DUMB telnets out there might not respond + * to the DO ECHO. So, we spin looking for NAWS, (most dumb + * telnets so far seem to respond with WONT for a DO that + * they don't understand...) because by the time we get the + * response, it will already have processed the DO ECHO. + * Kludge upon kludge. + */ + while (his_will_wont_is_changing(TELOPT_NAWS)) + ttloop(); - /* - * Spin, waiting for a response from the DO ECHO. However, - * some REALLY DUMB telnets out there might not respond - * to the DO ECHO. So, we spin looking for NAWS, (most dumb - * telnets so far seem to respond with WONT for a DO that - * they don't understand...) because by the time we get the - * response, it will already have processed the DO ECHO. - * Kludge upon kludge. - */ - while (his_will_wont_is_changing(TELOPT_NAWS)) - ttloop(); + /* + * But... + * The client might have sent a WILL NAWS as part of its + * startup code; if so, we'll be here before we get the + * response to the DO ECHO. We'll make the assumption + * that any implementation that understands about NAWS + * is a modern enough implementation that it will respond + * to our DO ECHO request; hence we'll do another spin + * waiting for the ECHO option to settle down, which is + * what we wanted to do in the first place... + */ + if (his_want_state_is_will(TELOPT_ECHO) && + his_state_is_will(TELOPT_NAWS)) { + while (his_will_wont_is_changing(TELOPT_ECHO)) + ttloop(); + } + /* + * On the off chance that the telnet client is broken and does not + * respond to the DO ECHO we sent, (after all, we did send the + * DO NAWS negotiation after the DO ECHO, and we won't get here + * until a response to the DO NAWS comes back) simulate the + * receipt of a will echo. This will also send a WONT ECHO + * to the client, since we assume that the client failed to + * respond because it believes that it is already in DO ECHO + * mode, which we do not want. + */ + if (his_want_state_is_will(TELOPT_ECHO)) { + DIAG(TD_OPTIONS, + {output_data("td: simulating recv\r\n"); + }); + willoption(TELOPT_ECHO); + } - /* - * But... - * The client might have sent a WILL NAWS as part of its - * startup code; if so, we'll be here before we get the - * response to the DO ECHO. We'll make the assumption - * that any implementation that understands about NAWS - * is a modern enough implementation that it will respond - * to our DO ECHO request; hence we'll do another spin - * waiting for the ECHO option to settle down, which is - * what we wanted to do in the first place... - */ - if (his_want_state_is_will(TELOPT_ECHO) && - his_state_is_will(TELOPT_NAWS)) { - while (his_will_wont_is_changing(TELOPT_ECHO)) - ttloop(); - } - /* - * On the off chance that the telnet client is broken and does not - * respond to the DO ECHO we sent, (after all, we did send the - * DO NAWS negotiation after the DO ECHO, and we won't get here - * until a response to the DO NAWS comes back) simulate the - * receipt of a will echo. This will also send a WONT ECHO - * to the client, since we assume that the client failed to - * respond because it believes that it is already in DO ECHO - * mode, which we do not want. - */ - if (his_want_state_is_will(TELOPT_ECHO)) { - DIAG(TD_OPTIONS, - {snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - "td: simulating recv\r\n"); - nfrontp += strlen(nfrontp);}); - willoption(TELOPT_ECHO); - } + /* + * Finally, to clean things up, we turn on our echo. This + * will break stupid 4.2 telnets out of local terminal echo. + */ - /* - * Finally, to clean things up, we turn on our echo. This - * will break stupid 4.2 telnets out of local terminal echo. - */ - - if (my_state_is_wont(TELOPT_ECHO)) - send_will(TELOPT_ECHO, 1); + if (my_state_is_wont(TELOPT_ECHO)) + send_will(TELOPT_ECHO, 1); #ifdef TIOCPKT #ifdef STREAMSPTY - if (!really_stream) + if (!really_stream) #endif - /* - * Turn on packet mode - */ - ioctl(p, TIOCPKT, (char *)&on); + /* + * Turn on packet mode + */ + ioctl(p, TIOCPKT, (char *)&on); #endif -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * Continuing line mode support. If client does not support - * real linemode, attempt to negotiate kludge linemode by sending - * the do timing mark sequence. - */ - if (lmodetype < REAL_LINEMODE) - send_do(TELOPT_TM, 1); -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - /* - * Call telrcv() once to pick up anything received during - * terminal type negotiation, 4.2/4.3 determination, and - * linemode negotiation. - */ - telrcv(); + /* + * Call telrcv() once to pick up anything received during + * terminal type negotiation, 4.2/4.3 determination, and + * linemode negotiation. + */ + telrcv(); - ioctl(f, FIONBIO, (char *)&on); - ioctl(p, FIONBIO, (char *)&on); + ioctl(f, FIONBIO, (char *)&on); + ioctl(p, FIONBIO, (char *)&on); #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) - setsockopt(net, SOL_SOCKET, SO_OOBINLINE, - (void *)&on, sizeof on); + setsockopt(net, SOL_SOCKET, SO_OOBINLINE, + (void *)&on, sizeof on); #endif /* defined(SO_OOBINLINE) */ #ifdef SIGTSTP - signal(SIGTSTP, SIG_IGN); + signal(SIGTSTP, SIG_IGN); #endif #ifdef SIGTTOU - /* - * Ignoring SIGTTOU keeps the kernel from blocking us - * in ttioct() in /sys/tty.c. - */ - signal(SIGTTOU, SIG_IGN); + /* + * Ignoring SIGTTOU keeps the kernel from blocking us + * in ttioct() in /sys/tty.c. + */ + signal(SIGTTOU, SIG_IGN); #endif - signal(SIGCHLD, cleanup); + signal(SIGCHLD, cleanup); #ifdef TIOCNOTTY - { - int t; - t = open(_PATH_TTY, O_RDWR); - if (t >= 0) { - ioctl(t, TIOCNOTTY, (char *)0); - close(t); - } + { + int t; + t = open(_PATH_TTY, O_RDWR); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + close(t); } + } #endif + /* + * Show banner that getty never gave. + * + * We put the banner in the pty input buffer. This way, it + * gets carriage return null processing, etc., just like all + * other pty --> client data. + */ + + if (getenv("USER")) + hostinfo = 0; + + IM = DEFAULT_IM; + HE = 0; + edithost(HE, host_name); + if (hostinfo && *IM) + putf(IM, ptyibuf2); + + if (pcc) + strncat(ptyibuf2, ptyip, pcc+1); + ptyip = ptyibuf2; + pcc = strlen(ptyip); + + DIAG(TD_REPORT, { + output_data("td: Entering processing loop\r\n"); + }); + + + nfd = ((f > p) ? f : p) + 1; + for (;;) { + fd_set ibits, obits, xbits; + int c; + + if (ncc < 0 && pcc < 0) + break; + + FD_ZERO(&ibits); + FD_ZERO(&obits); + FD_ZERO(&xbits); /* - * Show banner that getty never gave. - * - * We put the banner in the pty input buffer. This way, it - * gets carriage return null processing, etc., just like all - * other pty --> client data. + * Never look for input if there's still + * stuff in the corresponding output buffer */ - - if (getenv("USER")) - hostinfo = 0; - - if (getent(defent, "default") == 1) { - char *getstr(); - char *cp=defstrs; - - HE = getstr("he", &cp); - HN = getstr("hn", &cp); - IM = getstr("im", &cp); - if (HN && *HN) - strcpy(host_name, HN); - if (IM == 0) - IM = ""; + if (nfrontp - nbackp || pcc > 0) { + FD_SET(f, &obits); } else { - IM = DEFAULT_IM; - HE = 0; + FD_SET(p, &ibits); + } + if (pfrontp - pbackp || ncc > 0) { + FD_SET(p, &obits); + } else { + FD_SET(f, &ibits); + } + if (!SYNCHing) { + FD_SET(f, &xbits); + } + if ((c = select(nfd, &ibits, &obits, &xbits, + (struct timeval *)0)) < 1) { + if (c == -1) { + if (errno == EINTR) { + continue; + } + } + sleep(5); + continue; } - edithost(HE, host_name); - if (hostinfo && *IM) - putf(IM, ptyibuf2); - if (pcc) - strncat(ptyibuf2, ptyip, pcc+1); - ptyip = ptyibuf2; - pcc = strlen(ptyip); -#ifdef LINEMODE /* - * Last check to make sure all our states are correct. + * Any urgent data? */ - init_termbuf(); - localstat(); -#endif /* LINEMODE */ - - DIAG(TD_REPORT, - {snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - "td: Entering processing loop\r\n"); - nfrontp += strlen(nfrontp);}); - - - nfd = ((f > p) ? f : p) + 1; - for (;;) { - fd_set ibits, obits, xbits; - int c; - - if (ncc < 0 && pcc < 0) - break; - - FD_ZERO(&ibits); - FD_ZERO(&obits); - FD_ZERO(&xbits); - /* - * Never look for input if there's still - * stuff in the corresponding output buffer - */ - if (nfrontp - nbackp || pcc > 0) { - FD_SET(f, &obits); - } else { - FD_SET(p, &ibits); - } - if (pfrontp - pbackp || ncc > 0) { - FD_SET(p, &obits); - } else { - FD_SET(f, &ibits); - } - if (!SYNCHing) { - FD_SET(f, &xbits); - } - if ((c = select(nfd, &ibits, &obits, &xbits, - (struct timeval *)0)) < 1) { - if (c == -1) { - if (errno == EINTR) { - continue; - } - } - sleep(5); - continue; - } - - /* - * Any urgent data? - */ - if (FD_ISSET(net, &xbits)) { - SYNCHing = 1; - } - - /* - * Something to read from the network... - */ - if (FD_ISSET(net, &ibits)) { -#if !defined(SO_OOBINLINE) - /* - * In 4.2 (and 4.3 beta) 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; - - ioctl(net, SIOCATMARK, (char *)&atmark); - if (atmark) { - ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); - if ((ncc == -1) && (errno == EINVAL)) { - ncc = read(net, netibuf, sizeof (netibuf)); - if (sequenceIs(didnetreceive, gotDM)) { - SYNCHing = stilloob(net); - } - } - } else { - ncc = read(net, netibuf, sizeof (netibuf)); - } - } else { - ncc = read(net, netibuf, sizeof (netibuf)); - } - settimer(didnetreceive); -#else /* !defined(SO_OOBINLINE)) */ - ncc = read(net, netibuf, sizeof (netibuf)); -#endif /* !defined(SO_OOBINLINE)) */ - if (ncc < 0 && errno == EWOULDBLOCK) - ncc = 0; - else { - if (ncc <= 0) { - break; - } - netip = netibuf; - } - DIAG((TD_REPORT | TD_NETDATA), - {snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - "td: netread %d chars\r\n", ncc); - nfrontp += strlen(nfrontp);}); - DIAG(TD_NETDATA, printdata("nd", netip, ncc)); - } - - /* - * Something to read from the pty... - */ - if (FD_ISSET(p, &ibits)) { -#ifdef STREAMSPTY - if (really_stream) - pcc = readstream(p, ptyibuf, BUFSIZ); - else -#endif - pcc = read(p, ptyibuf, BUFSIZ); - - /* - * On some systems, if we try to read something - * off the master side before the slave side is - * opened, we get EIO. - */ - if (pcc < 0 && (errno == EWOULDBLOCK || -#ifdef EAGAIN - errno == EAGAIN || -#endif - errno == EIO)) { - pcc = 0; - } else { - if (pcc <= 0) - break; -#ifdef LINEMODE - /* - * If ioctl from pty, pass it through net - */ - if (ptyibuf[0] & TIOCPKT_IOCTL) { - copy_termbuf(ptyibuf+1, pcc-1); - localstat(); - pcc = 1; - } -#endif /* LINEMODE */ - if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { - netclear(); /* clear buffer back */ -#ifndef NO_URGENT - /* - * There are client telnets on some - * operating systems get screwed up - * royally if we send them urgent - * mode data. - */ - *nfrontp++ = IAC; - *nfrontp++ = DM; - neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - -#endif - } - if (his_state_is_will(TELOPT_LFLOW) && - (ptyibuf[0] & - (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { - int newflow = - ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; - if (newflow != flowmode) { - flowmode = newflow; - snprintf(nfrontp, - BUFSIZ - - (nfrontp - netobuf), - "%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - flowmode ? LFLOW_ON - : LFLOW_OFF, - IAC, SE); - nfrontp += 6; - DIAG(TD_OPTIONS, printsub('>', - (unsigned char *)nfrontp-4, - 4);); - } - } - pcc--; - ptyip = ptyibuf+1; - } - } - - while (pcc > 0) { - if ((&netobuf[BUFSIZ] - nfrontp) < 2) - break; - c = *ptyip++ & 0377, pcc--; - if (c == IAC) - *nfrontp++ = c; - *nfrontp++ = c; - if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { - if (pcc > 0 && ((*ptyip & 0377) == '\n')) { - *nfrontp++ = *ptyip++ & 0377; - pcc--; - } else - *nfrontp++ = '\0'; - } - } - - if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) - netflush(); - if (ncc > 0) - telrcv(); - if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) - ptyflush(); + if (FD_ISSET(net, &xbits)) { + SYNCHing = 1; } - cleanup(0); -} /* end of telnet */ + + /* + * Something to read from the network... + */ + if (FD_ISSET(net, &ibits)) { +#ifndef SO_OOBINLINE + /* + * In 4.2 (and 4.3 beta) 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; + + ioctl(net, SIOCATMARK, (char *)&atmark); + if (atmark) { + ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); + if ((ncc == -1) && (errno == EINVAL)) { + ncc = read(net, netibuf, sizeof (netibuf)); + if (sequenceIs(didnetreceive, gotDM)) { + SYNCHing = stilloob(net); + } + } + } else { + ncc = read(net, netibuf, sizeof (netibuf)); + } + } else { + ncc = read(net, netibuf, sizeof (netibuf)); + } + settimer(didnetreceive); +#else /* !defined(SO_OOBINLINE)) */ + ncc = read(net, netibuf, sizeof (netibuf)); +#endif /* !defined(SO_OOBINLINE)) */ + if (ncc < 0 && errno == EWOULDBLOCK) + ncc = 0; + else { + if (ncc <= 0) { + break; + } + netip = netibuf; + } + DIAG((TD_REPORT | TD_NETDATA), { + output_data("td: netread %d chars\r\n", ncc); + }); + DIAG(TD_NETDATA, printdata("nd", netip, ncc)); + } + + /* + * Something to read from the pty... + */ + if (FD_ISSET(p, &ibits)) { +#ifdef STREAMSPTY + if (really_stream) + pcc = readstream(p, ptyibuf, BUFSIZ); + else +#endif + pcc = read(p, ptyibuf, BUFSIZ); + + /* + * On some systems, if we try to read something + * off the master side before the slave side is + * opened, we get EIO. + */ + if (pcc < 0 && (errno == EWOULDBLOCK || +#ifdef EAGAIN + errno == EAGAIN || +#endif + errno == EIO)) { + pcc = 0; + } else { + if (pcc <= 0) + break; + if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { + netclear(); /* clear buffer back */ +#ifndef NO_URGENT + /* + * There are client telnets on some + * operating systems get screwed up + * royally if we send them urgent + * mode data. + */ + output_data ("%c%c", IAC, DM); + + neturg = nfrontp-1; /* off by one XXX */ + DIAG(TD_OPTIONS, + printoption("td: send IAC", DM)); + +#endif + } + if (his_state_is_will(TELOPT_LFLOW) && + (ptyibuf[0] & + (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { + int newflow = + ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; + if (newflow != flowmode) { + flowmode = newflow; + output_data("%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + flowmode ? LFLOW_ON + : LFLOW_OFF, + IAC, SE); + DIAG(TD_OPTIONS, printsub('>', + (unsigned char *)nfrontp-4, + 4);); + } + } + pcc--; + ptyip = ptyibuf+1; + } + } + + while (pcc > 0) { + if ((&netobuf[BUFSIZ] - nfrontp) < 3) + break; + c = *ptyip++ & 0377, pcc--; + if (c == IAC) + *nfrontp++ = c; + *nfrontp++ = c; + if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { + if (pcc > 0 && ((*ptyip & 0377) == '\n')) { + *nfrontp++ = *ptyip++ & 0377; + pcc--; + } else + *nfrontp++ = '\0'; + } + } + + if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) + netflush(); + if (ncc > 0) + telrcv(); + if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) + ptyflush(); + } + cleanup(0); +} #ifndef TCSIG # ifdef TIOCSIG @@ -1291,94 +1188,95 @@ telnet(f, p) #ifdef STREAMSPTY -int flowison = -1; /* current state of flow: -1 is unknown */ + int flowison = -1; /* current state of flow: -1 is unknown */ -int readstream(int p, char *ibuf, int bufsize) +int +readstream(int p, char *ibuf, int bufsize) { - int flags = 0; - int ret = 0; - struct termios *tsp; + int flags = 0; + int ret = 0; + struct termios *tsp; #if 0 - struct termio *tp; + struct termio *tp; #endif - struct iocblk *ip; - char vstop, vstart; - int ixon; - int newflow; + struct iocblk *ip; + char vstop, vstart; + int ixon; + int newflow; - strbufc.maxlen = BUFSIZ; - strbufc.buf = (char *)ctlbuf; - strbufd.maxlen = bufsize-1; - strbufd.len = 0; - strbufd.buf = ibuf+1; - ibuf[0] = 0; + strbufc.maxlen = BUFSIZ; + strbufc.buf = (char *)ctlbuf; + strbufd.maxlen = bufsize-1; + strbufd.len = 0; + strbufd.buf = ibuf+1; + ibuf[0] = 0; - ret = getmsg(p, &strbufc, &strbufd, &flags); - if (ret < 0) /* error of some sort -- probably EAGAIN */ - return(-1); - - if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { - /* data message */ - if (strbufd.len > 0) { /* real data */ - return(strbufd.len + 1); /* count header char */ - } else { - /* nothing there */ - errno = EAGAIN; - return(-1); - } - } - - /* - * It's a control message. Return 1, to look at the flag we set - */ - - switch (ctlbuf[0]) { - case M_FLUSH: - if (ibuf[1] & FLUSHW) - ibuf[0] = TIOCPKT_FLUSHWRITE; - return(1); - - case M_IOCTL: - ip = (struct iocblk *) (ibuf+1); - - switch (ip->ioc_cmd) { -#ifdef TCSETS - case TCSETS: - case TCSETSW: - case TCSETSF: - tsp = (struct termios *) - (ibuf+1 + sizeof(struct iocblk)); - vstop = tsp->c_cc[VSTOP]; - vstart = tsp->c_cc[VSTART]; - ixon = tsp->c_iflag & IXON; - break; -#endif -#if 0 - case TCSETA: - case TCSETAW: - case TCSETAF: - tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); - vstop = tp->c_cc[VSTOP]; - vstart = tp->c_cc[VSTART]; - ixon = tp->c_iflag & IXON; - break; -#endif - default: - errno = EAGAIN; - return(-1); - } - - newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; - if (newflow != flowison) { /* it's a change */ - flowison = newflow; - ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; - return(1); - } - } - - /* nothing worth doing anything about */ - errno = EAGAIN; + ret = getmsg(p, &strbufc, &strbufd, &flags); + if (ret < 0) /* error of some sort -- probably EAGAIN */ return(-1); + + if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { + /* data message */ + if (strbufd.len > 0) { /* real data */ + return(strbufd.len + 1); /* count header char */ + } else { + /* nothing there */ + errno = EAGAIN; + return(-1); + } + } + + /* + * It's a control message. Return 1, to look at the flag we set + */ + + switch (ctlbuf[0]) { + case M_FLUSH: + if (ibuf[1] & FLUSHW) + ibuf[0] = TIOCPKT_FLUSHWRITE; + return(1); + + case M_IOCTL: + ip = (struct iocblk *) (ibuf+1); + + switch (ip->ioc_cmd) { +#ifdef TCSETS + case TCSETS: + case TCSETSW: + case TCSETSF: + tsp = (struct termios *) + (ibuf+1 + sizeof(struct iocblk)); + vstop = tsp->c_cc[VSTOP]; + vstart = tsp->c_cc[VSTART]; + ixon = tsp->c_iflag & IXON; + break; +#endif +#if 0 + case TCSETA: + case TCSETAW: + case TCSETAF: + tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); + vstop = tp->c_cc[VSTOP]; + vstart = tp->c_cc[VSTART]; + ixon = tp->c_iflag & IXON; + break; +#endif + default: + errno = EAGAIN; + return(-1); + } + + newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; + if (newflow != flowison) { /* it's a change */ + flowison = newflow; + ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; + return(1); + } + } + + /* nothing worth doing anything about */ + errno = EAGAIN; + return(-1); } #endif /* STREAMSPTY */ @@ -1387,26 +1285,26 @@ int readstream(int p, char *ibuf, int bufsize) * If it is in raw mode, just write NULL; * otherwise, write intr char. */ - void +void interrupt() { - ptyflush(); /* half-hearted */ + ptyflush(); /* half-hearted */ #if defined(STREAMSPTY) && defined(TIOCSIGNAL) - /* Streams PTY style ioctl to post a signal */ - if (really_stream) + /* Streams PTY style ioctl to post a signal */ + if (really_stream) { - int sig = SIGINT; - ioctl(ourpty, TIOCSIGNAL, &sig); - ioctl(ourpty, I_FLUSH, FLUSHR); + int sig = SIGINT; + ioctl(ourpty, TIOCSIGNAL, &sig); + ioctl(ourpty, I_FLUSH, FLUSHR); } #else #ifdef TCSIG - ioctl(ourpty, TCSIG, (char *)SIGINT); + ioctl(ourpty, TCSIG, (char *)SIGINT); #else /* TCSIG */ - init_termbuf(); - *pfrontp++ = slctab[SLC_IP].sptr ? - (unsigned char)*slctab[SLC_IP].sptr : '\177'; + init_termbuf(); + *pfrontp++ = slctab[SLC_IP].sptr ? + (unsigned char)*slctab[SLC_IP].sptr : '\177'; #endif /* TCSIG */ #endif } @@ -1416,29 +1314,29 @@ interrupt() * If it is in raw mode, just write NULL; * otherwise, write quit char. */ - void +void sendbrk() { - ptyflush(); /* half-hearted */ + ptyflush(); /* half-hearted */ #ifdef TCSIG - ioctl(ourpty, TCSIG, (char *)SIGQUIT); + ioctl(ourpty, TCSIG, (char *)SIGQUIT); #else /* TCSIG */ - init_termbuf(); - *pfrontp++ = slctab[SLC_ABORT].sptr ? - (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; + init_termbuf(); + *pfrontp++ = slctab[SLC_ABORT].sptr ? + (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; #endif /* TCSIG */ } - void +void sendsusp() { #ifdef SIGTSTP - ptyflush(); /* half-hearted */ + ptyflush(); /* half-hearted */ # ifdef TCSIG - ioctl(ourpty, TCSIG, (char *)SIGTSTP); + ioctl(ourpty, TCSIG, (char *)SIGTSTP); # else /* TCSIG */ - *pfrontp++ = slctab[SLC_SUSP].sptr ? - (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; + *pfrontp++ = slctab[SLC_SUSP].sptr ? + (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; # endif /* TCSIG */ #endif /* SIGTSTP */ } @@ -1447,31 +1345,23 @@ sendsusp() * When we get an AYT, if ^T is enabled, use that. Otherwise, * just send back "[Yes]". */ - void +void recv_ayt() { #if defined(SIGINFO) && defined(TCSIG) - if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { - ioctl(ourpty, TCSIG, (char *)SIGINFO); - return; - } + if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { + ioctl(ourpty, TCSIG, (char *)SIGINFO); + return; + } #endif - strcpy(nfrontp, "\r\n[Yes]\r\n"); - nfrontp += 9; + output_data("\r\n[Yes]\r\n"); } - void +void doeof() { - init_termbuf(); + init_termbuf(); -#if defined(LINEMODE) && (VEOF == VMIN) - if (!tty_isediting()) { - extern char oldeofc; - *pfrontp++ = oldeofc; - return; - } -#endif - *pfrontp++ = slctab[SLC_EOF].sptr ? - (unsigned char)*slctab[SLC_EOF].sptr : '\004'; + *pfrontp++ = slctab[SLC_EOF].sptr ? + (unsigned char)*slctab[SLC_EOF].sptr : '\004'; } diff --git a/appl/telnet/telnetd/telnetd.h b/appl/telnet/telnetd/telnetd.h index 23c0ec4f1..80fb2b3aa 100644 --- a/appl/telnet/telnetd/telnetd.h +++ b/appl/telnet/telnetd/telnetd.h @@ -34,9 +34,119 @@ */ +#include + +#include +#include +#include +#include + +#include +#include + +#include +#ifdef TIME_WITH_SYS_TIME +#include +#include +#elif defined(HAVE_SYS_TIME_H) +#include +#else +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif /* HAVE_SYS_RESOURCE_H */ +#ifndef _CRAY +#include +#endif /* CRAY */ +#include +#include +#include + +/* including both and in SunOS 4 generates a + lot of warnings */ + +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4 +#include +#endif +#ifdef HAVE_SYS_FILIO_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#ifndef LOG_DAEMON +#define LOG_DAEMON 0 +#endif +#ifndef LOG_ODELAY +#define LOG_ODELAY 0 +#endif +#include + +#ifdef HAVE_CURSES_H +#include +#endif +#include +#include + #include "defs.h" + +#include + +#ifndef _POSIX_VDISABLE +# ifdef VDISABLE +# define _POSIX_VDISABLE VDISABLE +# else +# define _POSIX_VDISABLE ((unsigned char)'\377') +# endif +#endif + + +#ifdef _CRAY +# ifdef CRAY1 +# include +# ifndef FD_ZERO +# include +# endif /* FD_ZERO */ +# endif /* CRAY1 */ + +#include +#endif /* _CRAY */ + +#ifdef __hpux +#include +#endif + +#ifdef HAVE_UNAME +#include +#endif + #include "ext.h" +#include "pathnames.h" #include + +#ifdef SOCKS +#include +#endif + +#ifdef KRB4 +#include +#include +#endif + +#ifdef AUTHENTICATION +#include +#include +#ifdef ENCRYPTION +#include +#endif +#endif + #include #ifdef DIAGNOSTICS @@ -49,3 +159,11 @@ extern char **environ; extern int errno; +/* prototypes */ + +/* appends data to nfrontp and advances */ +int output_data (const char *format, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; diff --git a/appl/telnet/telnetd/termstat.c b/appl/telnet/telnetd/termstat.c index a067b883b..69981fd83 100644 --- a/appl/telnet/telnetd/termstat.c +++ b/appl/telnet/telnetd/termstat.c @@ -31,15 +31,10 @@ * SUCH DAMAGE. */ -#include -#ifdef SOCKS -#include -#endif +#include "telnetd.h" RCSID("$Id$"); -#include "telnetd.h" - /* * local variables */ @@ -47,335 +42,32 @@ int def_tspeed = -1, def_rspeed = -1; #ifdef TIOCSWINSZ int def_row = 0, def_col = 0; #endif -#ifdef LINEMODE -static int _terminit = 0; -#endif /* LINEMODE */ - -#ifdef LINEMODE -/* - * localstat - * - * This function handles all management of linemode. - * - * Linemode allows the client to do the local editing of data - * and send only complete lines to the server. Linemode state is - * based on the state of the pty driver. If the pty is set for - * external processing, then we can use linemode. Further, if we - * can use real linemode, then we can look at the edit control bits - * in the pty to determine what editing the client should do. - * - * Linemode support uses the following state flags to keep track of - * current and desired linemode state. - * alwayslinemode : true if -l was specified on the telnetd - * command line. It means to have linemode on as much as - * possible. - * - * lmodetype: signifies whether the client can - * handle real linemode, or if use of kludgeomatic linemode - * is preferred. It will be set to one of the following: - * REAL_LINEMODE : use linemode option - * NO_KLUDGE : don't initiate kludge linemode. - * KLUDGE_LINEMODE : use kludge linemode - * NO_LINEMODE : client is ignorant of linemode - * - * linemode, uselinemode : linemode is true if linemode - * is currently on, uselinemode is the state that we wish - * to be in. If another function wishes to turn linemode - * on or off, it sets or clears uselinemode. - * - * editmode, useeditmode : like linemode/uselinemode, but - * these contain the edit mode states (edit and trapsig). - * - * The state variables correspond to some of the state information - * in the pty. - * linemode: - * In real linemode, this corresponds to whether the pty - * expects external processing of incoming data. - * In kludge linemode, this more closely corresponds to the - * whether normal processing is on or not. (ICANON in - * system V, or COOKED mode in BSD.) - * If the -l option was specified (alwayslinemode), then - * an attempt is made to force external processing on at - * all times. - * - * The following heuristics are applied to determine linemode - * handling within the server. - * 1) Early on in starting up the server, an attempt is made - * to negotiate the linemode option. If this succeeds - * then lmodetype is set to REAL_LINEMODE and all linemode - * processing occurs in the context of the linemode option. - * 2) If the attempt to negotiate the linemode option failed, - * and the "-k" (don't initiate kludge linemode) isn't set, - * then we try to use kludge linemode. We test for this - * capability by sending "do Timing Mark". If a positive - * response comes back, then we assume that the client - * understands kludge linemode (ech!) and the - * lmodetype flag is set to KLUDGE_LINEMODE. - * 3) Otherwise, linemode is not supported at all and - * lmodetype remains set to NO_LINEMODE (which happens - * to be 0 for convenience). - * 4) At any time a command arrives that implies a higher - * state of linemode support in the client, we move to that - * linemode support. - * - * A short explanation of kludge linemode is in order here. - * 1) The heuristic to determine support for kludge linemode - * is to send a do timing mark. We assume that a client - * that supports timing marks also supports kludge linemode. - * A risky proposition at best. - * 2) Further negotiation of linemode is done by changing the - * the server's state regarding SGA. If server will SGA, - * then linemode is off, if server won't SGA, then linemode - * is on. - */ - void -localstat() -{ - void netflush(); - int need_will_echo = 0; - - /* - * Check for state of BINARY options. - */ - if (tty_isbinaryin()) { - if (his_want_state_is_wont(TELOPT_BINARY)) - send_do(TELOPT_BINARY, 1); - } else { - if (his_want_state_is_will(TELOPT_BINARY)) - send_dont(TELOPT_BINARY, 1); - } - - if (tty_isbinaryout()) { - if (my_want_state_is_wont(TELOPT_BINARY)) - send_will(TELOPT_BINARY, 1); - } else { - if (my_want_state_is_will(TELOPT_BINARY)) - send_wont(TELOPT_BINARY, 1); - } - - /* - * Check for changes to flow control if client supports it. - */ - flowstat(); - - /* - * Check linemode on/off state - */ - uselinemode = tty_linemode(); - - /* - * If alwayslinemode is on, and pty is changing to turn it off, then - * force linemode back on. - */ - if (alwayslinemode && linemode && !uselinemode) { - uselinemode = 1; - tty_setlinemode(uselinemode); - } - -#if defined(ENCRYPTION) - /* - * If the terminal is not echoing, but editing is enabled, - * something like password input is going to happen, so - * if we the other side is not currently sending encrypted - * data, ask the other side to start encrypting. - */ - if (his_state_is_will(TELOPT_ENCRYPT)) { - static int enc_passwd = 0; - if (uselinemode && !tty_isecho() && tty_isediting() - && (enc_passwd == 0) && !decrypt_input) { - encrypt_send_request_start(); - enc_passwd = 1; - } else if (enc_passwd) { - encrypt_send_request_end(); - enc_passwd = 0; - } - } -#endif - - /* - * Do echo mode handling as soon as we know what the - * linemode is going to be. - * If the pty has echo turned off, then tell the client that - * the server will echo. If echo is on, then the server - * will echo if in character mode, but in linemode the - * client should do local echoing. The state machine will - * not send anything if it is unnecessary, so don't worry - * about that here. - * - * If we need to send the WILL ECHO (because echo is off), - * then delay that until after we have changed the MODE. - * This way, when the user is turning off both editing - * and echo, the client will get editing turned off first. - * This keeps the client from going into encryption mode - * and then right back out if it is doing auto-encryption - * when passwords are being typed. - */ - if (uselinemode) { - if (tty_isecho()) - send_wont(TELOPT_ECHO, 1); - else - need_will_echo = 1; -#ifdef KLUDGELINEMODE - if (lmodetype == KLUDGE_OK) - lmodetype = KLUDGE_LINEMODE; -#endif - } - - /* - * If linemode is being turned off, send appropriate - * command and then we're all done. - */ - if (!uselinemode && linemode) { -# ifdef KLUDGELINEMODE - if (lmodetype == REAL_LINEMODE) { -# endif /* KLUDGELINEMODE */ - send_dont(TELOPT_LINEMODE, 1); -# ifdef KLUDGELINEMODE - } else if (lmodetype == KLUDGE_LINEMODE) - send_will(TELOPT_SGA, 1); -# endif /* KLUDGELINEMODE */ - send_will(TELOPT_ECHO, 1); - linemode = uselinemode; - goto done; - } - -# ifdef KLUDGELINEMODE - /* - * If using real linemode check edit modes for possible later use. - * If we are in kludge linemode, do the SGA negotiation. - */ - if (lmodetype == REAL_LINEMODE) { -# endif /* KLUDGELINEMODE */ - useeditmode = 0; - if (tty_isediting()) - useeditmode |= MODE_EDIT; - if (tty_istrapsig()) - useeditmode |= MODE_TRAPSIG; - if (tty_issofttab()) - useeditmode |= MODE_SOFT_TAB; - if (tty_islitecho()) - useeditmode |= MODE_LIT_ECHO; -# ifdef KLUDGELINEMODE - } else if (lmodetype == KLUDGE_LINEMODE) { - if (tty_isediting() && uselinemode) - send_wont(TELOPT_SGA, 1); - else - send_will(TELOPT_SGA, 1); - } -# endif /* KLUDGELINEMODE */ - - /* - * Negotiate linemode on if pty state has changed to turn it on. - * Send appropriate command and send along edit mode, then all done. - */ - if (uselinemode && !linemode) { -# ifdef KLUDGELINEMODE - if (lmodetype == KLUDGE_LINEMODE) { - send_wont(TELOPT_SGA, 1); - } else if (lmodetype == REAL_LINEMODE) { -# endif /* KLUDGELINEMODE */ - send_do(TELOPT_LINEMODE, 1); - /* send along edit modes */ - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%c%c%c%c%c%c%c", IAC, SB, - TELOPT_LINEMODE, LM_MODE, useeditmode, - IAC, SE); - nfrontp += 7; - editmode = useeditmode; -# ifdef KLUDGELINEMODE - } -# endif /* KLUDGELINEMODE */ - linemode = uselinemode; - goto done; - } - -# ifdef KLUDGELINEMODE - /* - * None of what follows is of any value if not using - * real linemode. - */ - if (lmodetype < REAL_LINEMODE) - goto done; -# endif /* KLUDGELINEMODE */ - - if (linemode && his_state_is_will(TELOPT_LINEMODE)) { - /* - * If edit mode changed, send edit mode. - */ - if (useeditmode != editmode) { - /* - * Send along appropriate edit mode mask. - */ - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%c%c%c%c%c%c%c", IAC, SB, - TELOPT_LINEMODE, LM_MODE, useeditmode, - IAC, SE); - nfrontp += 7; - editmode = useeditmode; - } - - - /* - * Check for changes to special characters in use. - */ - start_slc(0); - check_slc(); - end_slc(0); - } - -done: - if (need_will_echo) - send_will(TELOPT_ECHO, 1); - /* - * Some things should be deferred until after the pty state has - * been set by the local process. Do those things that have been - * deferred now. This only happens once. - */ - if (_terminit == 0) { - _terminit = 1; - defer_terminit(); - } - - netflush(); - set_termbuf(); - return; - -} /* end of localstat */ -#endif /* LINEMODE */ /* * flowstat * * Check for changes to flow control */ - void +void flowstat() { - if (his_state_is_will(TELOPT_LFLOW)) { - if (tty_flowmode() != flowmode) { - flowmode = tty_flowmode(); - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - flowmode ? LFLOW_ON : LFLOW_OFF, - IAC, SE); - nfrontp += 6; - } - if (tty_restartany() != restartany) { - restartany = tty_restartany(); - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - restartany ? LFLOW_RESTART_ANY - : LFLOW_RESTART_XON, - IAC, SE); - nfrontp += 6; - } + if (his_state_is_will(TELOPT_LFLOW)) { + if (tty_flowmode() != flowmode) { + flowmode = tty_flowmode(); + output_data("%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + flowmode ? LFLOW_ON : LFLOW_OFF, + IAC, SE); } + if (tty_restartany() != restartany) { + restartany = tty_restartany(); + output_data("%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + restartany ? LFLOW_RESTART_ANY + : LFLOW_RESTART_XON, + IAC, SE); + } + } } /* @@ -386,254 +78,63 @@ flowstat() * at a time, and if using kludge linemode, then only linemode may be * affected. */ - void -clientstat(code, parm1, parm2) - int code, parm1, parm2; +void +clientstat(int code, int parm1, int parm2) { - void netflush(); + void netflush(); - /* - * Get a copy of terminal characteristics. - */ - init_termbuf(); + /* + * Get a copy of terminal characteristics. + */ + init_termbuf(); - /* - * Process request from client. code tells what it is. - */ - switch (code) { -#ifdef LINEMODE - case TELOPT_LINEMODE: - /* - * Don't do anything unless client is asking us to change - * modes. - */ - uselinemode = (parm1 == WILL); - if (uselinemode != linemode) { -# ifdef KLUDGELINEMODE - /* - * If using kludge linemode, make sure that - * we can do what the client asks. - * We can not turn off linemode if alwayslinemode - * and the ICANON bit is set. - */ - if (lmodetype == KLUDGE_LINEMODE) { - if (alwayslinemode && tty_isediting()) { - uselinemode = 1; - } - } - - /* - * Quit now if we can't do it. - */ - if (uselinemode == linemode) - return; - - /* - * If using real linemode and linemode is being - * turned on, send along the edit mode mask. - */ - if (lmodetype == REAL_LINEMODE && uselinemode) -# else /* KLUDGELINEMODE */ - if (uselinemode) -# endif /* KLUDGELINEMODE */ - { - useeditmode = 0; - if (tty_isediting()) - useeditmode |= MODE_EDIT; - if (tty_istrapsig) - useeditmode |= MODE_TRAPSIG; - if (tty_issofttab()) - useeditmode |= MODE_SOFT_TAB; - if (tty_islitecho()) - useeditmode |= MODE_LIT_ECHO; - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%c%c%c%c%c%c%c", IAC, - SB, TELOPT_LINEMODE, LM_MODE, - useeditmode, IAC, SE); - nfrontp += 7; - editmode = useeditmode; - } - - - tty_setlinemode(uselinemode); - - linemode = uselinemode; - - if (!linemode) - send_will(TELOPT_ECHO, 1); - } - break; - - case LM_MODE: - { - int ack, changed; - - /* - * Client has sent along a mode mask. If it agrees with - * what we are currently doing, ignore it; if not, it could - * be viewed as a request to change. Note that the server - * will change to the modes in an ack if it is different from - * what we currently have, but we will not ack the ack. - */ - useeditmode &= MODE_MASK; - ack = (useeditmode & MODE_ACK); - useeditmode &= ~MODE_ACK; - - if (changed = (useeditmode ^ editmode)) { - /* - * This check is for a timing problem. If the - * state of the tty has changed (due to the user - * application) we need to process that info - * before we write in the state contained in the - * ack!!! This gets out the new MODE request, - * and when the ack to that command comes back - * we'll set it and be in the right mode. - */ - if (ack) - localstat(); - if (changed & MODE_EDIT) - tty_setedit(useeditmode & MODE_EDIT); - - if (changed & MODE_TRAPSIG) - tty_setsig(useeditmode & MODE_TRAPSIG); - - if (changed & MODE_SOFT_TAB) - tty_setsofttab(useeditmode & MODE_SOFT_TAB); - - if (changed & MODE_LIT_ECHO) - tty_setlitecho(useeditmode & MODE_LIT_ECHO); - - set_termbuf(); - - if (!ack) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%c%c%c%c%c%c%c", IAC, - SB, TELOPT_LINEMODE, LM_MODE, - useeditmode|MODE_ACK, - IAC, SE); - nfrontp += 7; - } - - editmode = useeditmode; - } - - break; - - } /* end of case LM_MODE */ -#endif /* LINEMODE */ - - case TELOPT_NAWS: + /* + * Process request from client. code tells what it is. + */ + switch (code) { + case TELOPT_NAWS: #ifdef TIOCSWINSZ - { - struct winsize ws; + { + struct winsize ws; - def_col = parm1; - def_row = parm2; -#ifdef LINEMODE - /* - * Defer changing window size until after terminal is - * initialized. - */ - if (terminit() == 0) - return; -#endif /* LINEMODE */ + def_col = parm1; + def_row = parm2; - /* - * Change window size as requested by client. - */ + /* + * Change window size as requested by client. + */ - ws.ws_col = parm1; - ws.ws_row = parm2; - ioctl(ourpty, TIOCSWINSZ, (char *)&ws); - } + ws.ws_col = parm1; + ws.ws_row = parm2; + ioctl(ourpty, TIOCSWINSZ, (char *)&ws); + } #endif /* TIOCSWINSZ */ - break; + break; - case TELOPT_TSPEED: - { - def_tspeed = parm1; - def_rspeed = parm2; -#ifdef LINEMODE - /* - * Defer changing the terminal speed. - */ - if (terminit() == 0) - return; -#endif /* LINEMODE */ - /* - * Change terminal speed as requested by client. - * We set the receive speed first, so that if we can't - * store seperate receive and transmit speeds, the transmit - * speed will take precedence. - */ - tty_rspeed(parm2); - tty_tspeed(parm1); - set_termbuf(); + case TELOPT_TSPEED: + { + def_tspeed = parm1; + def_rspeed = parm2; + /* + * Change terminal speed as requested by client. + * We set the receive speed first, so that if we can't + * store seperate receive and transmit speeds, the transmit + * speed will take precedence. + */ + tty_rspeed(parm2); + tty_tspeed(parm1); + set_termbuf(); - break; + break; - } /* end of case TELOPT_TSPEED */ + } /* end of case TELOPT_TSPEED */ - default: - /* What? */ - break; - } /* end of switch */ + default: + /* What? */ + break; + } /* end of switch */ - netflush(); + netflush(); -} /* end of clientstat */ - -#ifdef LINEMODE -/* - * defer_terminit - * - * Some things should not be done until after the login process has started - * and all the pty modes are set to what they are supposed to be. This - * function is called when the pty state has been processed for the first time. - * It calls other functions that do things that were deferred in each module. - */ - void -defer_terminit() -{ - - /* - * local stuff that got deferred. - */ - if (def_tspeed != -1) { - clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed); - def_tspeed = def_rspeed = 0; - } - -#ifdef TIOCSWINSZ - if (def_col || def_row) { - struct winsize ws; - - memset(&ws, 0, sizeof(ws)); - ws.ws_col = def_col; - ws.ws_row = def_row; - ioctl(ourpty, TIOCSWINSZ, (char *)&ws); - } -#endif - - /* - * The only other module that currently defers anything. - */ - deferslc(); - -} /* end of defer_terminit */ - -/* - * terminit - * - * Returns true if the pty state has been processed yet. - */ - int -terminit() -{ - return(_terminit); - -} /* end of terminit */ -#endif /* LINEMODE */ +} diff --git a/appl/telnet/telnetd/utility.c b/appl/telnet/telnetd/utility.c index 700e1a49c..b95d7f2f8 100644 --- a/appl/telnet/telnetd/utility.c +++ b/appl/telnet/telnetd/utility.c @@ -31,19 +31,10 @@ * SUCH DAMAGE. */ -#include -#ifdef SOCKS -#include -#endif - -RCSID("$Id$"); - #define PRINTOPTIONS #include "telnetd.h" -#ifdef HAVE_UNAME -#include -#endif +RCSID("$Id$"); /* * utility functions performing io related tasks @@ -52,23 +43,22 @@ RCSID("$Id$"); /* * ttloop * - * A small subroutine to flush the network output buffer, get some data - * from the network, and pass it through the telnet state machine. We - * also flush the pty input buffer (by dropping its data) if it becomes - * too full. + * A small subroutine to flush the network output buffer, get some + * data from the network, and pass it through the telnet state + * machine. We also flush the pty input buffer (by dropping its data) + * if it becomes too full. */ - void +void ttloop(void) { void netflush(void); - - DIAG(TD_REPORT, {snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - "td: ttloop\r\n"); - nfrontp += strlen(nfrontp);}); - if (nfrontp-nbackp) { + + DIAG(TD_REPORT, { + output_data("td: ttloop\r\n"); + }); + if (nfrontp-nbackp) netflush(); - } ncc = read(net, netibuf, sizeof netibuf); if (ncc < 0) { syslog(LOG_INFO, "ttloop: read: %m\n"); @@ -77,9 +67,9 @@ ttloop(void) syslog(LOG_INFO, "ttloop: peer died: %m\n"); exit(1); } - DIAG(TD_REPORT, {snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - "td: ttloop read %d chars\r\n", ncc); - nfrontp += strlen(nfrontp);}); + DIAG(TD_REPORT, { + output_data("td: ttloop read %d chars\r\n", ncc); + }); netip = netibuf; telrcv(); /* state machine */ if (ncc > 0) { @@ -91,9 +81,8 @@ ttloop(void) /* * Check a descriptor to see if out of band data exists on it. */ - int +int stilloob(int s) - /* socket number */ { static struct timeval timeout = { 0 }; fd_set excepts; @@ -115,28 +104,26 @@ stilloob(int s) } } - void +void ptyflush(void) { - int n; + int n; - if ((n = pfrontp - pbackp) > 0) { - DIAG((TD_REPORT | TD_PTYDATA), - { snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "td: ptyflush %d chars\r\n", n); - nfrontp += strlen(nfrontp); }); - DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); - n = write(ourpty, pbackp, n); - } - if (n < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return; - cleanup(0); - } - pbackp += n; - if (pbackp == pfrontp) - pbackp = pfrontp = ptyobuf; + if ((n = pfrontp - pbackp) > 0) { + DIAG((TD_REPORT | TD_PTYDATA), { + output_data("td: ptyflush %d chars\r\n", n); + }); + DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); + n = write(ourpty, pbackp, n); + } + if (n < 0) { + if (errno == EWOULDBLOCK || errno == EINTR) + return; + cleanup(0); + } + pbackp += n; + if (pbackp == pfrontp) + pbackp = pfrontp = ptyobuf; } /* @@ -149,7 +136,7 @@ ptyflush(void) * if the current address is a TELNET IAC ("I Am a Command") * character. */ - char * +char * nextitem(char *current) { if ((*current&0xff) != IAC) { @@ -161,22 +148,22 @@ nextitem(char *current) case WILL: case WONT: return current+3; - case SB: /* loop forever looking for the SE */ - { - char *look = current+2; + case SB:{ + /* loop forever looking for the SE */ + char *look = current+2; - for (;;) { - if ((*look++&0xff) == IAC) { - if ((*look++&0xff) == SE) { - return look; - } + for (;;) { + if ((*look++&0xff) == IAC) { + if ((*look++&0xff) == SE) { + return look; } } } + } default: return current+2; } -} /* end of nextitem */ +} /* @@ -195,52 +182,52 @@ nextitem(char *current) * caller should be setting the urgent data pointer AFTER calling * us in any case. */ - void +void netclear(void) { char *thisitem, *next; char *good; #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ - ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) + ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) -#if defined(ENCRYPTION) - thisitem = nclearto > netobuf ? nclearto : netobuf; +#ifdef ENCRYPTION + thisitem = nclearto > netobuf ? nclearto : netobuf; #else - thisitem = netobuf; + thisitem = netobuf; #endif - while ((next = nextitem(thisitem)) <= nbackp) { - thisitem = next; - } - - /* Now, thisitem is first before/at boundary. */ - -#if defined(ENCRYPTION) - good = nclearto > netobuf ? nclearto : netobuf; -#else - good = netobuf; /* where the good bytes go */ -#endif - - while (nfrontp > thisitem) { - if (wewant(thisitem)) { - int length; - - next = thisitem; - do { - next = nextitem(next); - } while (wewant(next) && (nfrontp > next)); - length = next-thisitem; - memmove(good, thisitem, length); - good += length; + while ((next = nextitem(thisitem)) <= nbackp) { thisitem = next; - } else { - thisitem = nextitem(thisitem); } - } - nbackp = netobuf; - nfrontp = good; /* next byte to be sent */ - neturg = 0; + /* Now, thisitem is first before/at boundary. */ + +#ifdef ENCRYPTION + good = nclearto > netobuf ? nclearto : netobuf; +#else + good = netobuf; /* where the good bytes go */ +#endif + + while (nfrontp > thisitem) { + if (wewant(thisitem)) { + int length; + + next = thisitem; + do { + next = nextitem(next); + } while (wewant(next) && (nfrontp > next)); + length = next-thisitem; + memmove(good, thisitem, length); + good += length; + thisitem = next; + } else { + thisitem = nextitem(thisitem); + } + } + + nbackp = netobuf; + nfrontp = good; /* next byte to be sent */ + neturg = 0; } /* end of netclear */ /* @@ -248,7 +235,7 @@ netclear(void) * Send as much data as possible to the network, * handling requests for urgent data. */ - void +void netflush(void) { int n; @@ -256,18 +243,15 @@ netflush(void) if ((n = nfrontp - nbackp) > 0) { DIAG(TD_REPORT, - { snprintf(nfrontp, BUFSIZ - (nfrontp - netobuf), - "td: netflush %d chars\r\n", n); - n += strlen(nfrontp); /* get count first */ - nfrontp += strlen(nfrontp); /* then move pointer */ - }); -#if defined(ENCRYPTION) + { n += output_data("td: netflush %d chars\r\n", n); + }); +#ifdef ENCRYPTION if (encrypt_output) { - char *s = nclearto ? nclearto : nbackp; - if (nfrontp - s > 0) { - (*encrypt_output)((unsigned char *)s, nfrontp-s); - nclearto = nfrontp; - } + char *s = nclearto ? nclearto : nbackp; + if (nfrontp - s > 0) { + (*encrypt_output)((unsigned char *)s, nfrontp-s); + nclearto = nfrontp; + } } #endif /* @@ -296,11 +280,11 @@ netflush(void) } if (n < 0) { if (errno == EWOULDBLOCK || errno == EINTR) - return; + return; cleanup(0); } nbackp += n; -#if defined(ENCRYPTION) +#ifdef ENCRYPTION if (nbackp > nclearto) nclearto = 0; #endif @@ -309,12 +293,12 @@ netflush(void) } if (nbackp == nfrontp) { nbackp = nfrontp = netobuf; -#if defined(ENCRYPTION) +#ifdef ENCRYPTION nclearto = 0; #endif } return; -} /* end of netflush */ +} /* @@ -327,19 +311,18 @@ netflush(void) * ptr - A pointer to a character string to write * len - How many bytes to write */ - void +void writenet(unsigned char *ptr, int len) { - /* flush buffer if no room for new data) */ - if ((&netobuf[BUFSIZ] - nfrontp) < len) { - /* if this fails, don't worry, buffer is a little big */ - netflush(); - } + /* flush buffer if no room for new data) */ + while ((&netobuf[BUFSIZ] - nfrontp) < len) { + /* if this fails, don't worry, buffer is a little big */ + netflush(); + } - memmove(nfrontp, ptr, len); - nfrontp += len; - -} /* end of writenet */ + memmove(nfrontp, ptr, len); + nfrontp += len; +} /* @@ -349,204 +332,196 @@ writenet(unsigned char *ptr, int len) void fatal(int f, char *msg) { - char buf[BUFSIZ]; + char buf[BUFSIZ]; - snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg); -#if defined(ENCRYPTION) - if (encrypt_output) { - /* - * Better turn off encryption first.... - * Hope it flushes... - */ - encrypt_send_end(); - netflush(); - } + snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg); +#ifdef ENCRYPTION + if (encrypt_output) { + /* + * Better turn off encryption first.... + * Hope it flushes... + */ + encrypt_send_end(); + netflush(); + } #endif - write(f, buf, (int)strlen(buf)); - sleep(1); /*XXX*/ - exit(1); + write(f, buf, (int)strlen(buf)); + sleep(1); /*XXX*/ + exit(1); } - void +void fatalperror(int f, char *msg) { - char buf[BUFSIZ]; - - snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno)); - fatal(f, buf); + char buf[BUFSIZ]; + + snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno)); + fatal(f, buf); } char editedhost[32]; void edithost(char *pat, char *host) { - char *res = editedhost; + char *res = editedhost; - if (!pat) - pat = ""; - while (*pat) { - switch (*pat) { + if (!pat) + pat = ""; + while (*pat) { + switch (*pat) { - case '#': - if (*host) - host++; - break; + case '#': + if (*host) + host++; + break; - case '@': - if (*host) - *res++ = *host++; - break; + case '@': + if (*host) + *res++ = *host++; + break; - default: - *res++ = *pat; - break; - } - if (res == &editedhost[sizeof editedhost - 1]) { - *res = '\0'; - return; - } - pat++; + default: + *res++ = *pat; + break; } - if (*host) - strncpy(res, host, - sizeof editedhost - (res - editedhost) -1); - else - *res = '\0'; - editedhost[sizeof editedhost - 1] = '\0'; + if (res == &editedhost[sizeof editedhost - 1]) { + *res = '\0'; + return; + } + pat++; + } + if (*host) + strncpy(res, host, + sizeof editedhost - (res - editedhost) -1); + else + *res = '\0'; + editedhost[sizeof editedhost - 1] = '\0'; } static char *putlocation; - void +void putstr(char *s) { - while (*s) - putchr(*s++); + while (*s) + putchr(*s++); } - void +void putchr(int cc) { - *putlocation++ = cc; + *putlocation++ = cc; } /* * This is split on two lines so that SCCS will not see the M * between two % signs and expand it... */ -static char fmtstr[] = { "%l:%M\ -%P on %A, %d %B %Y" }; +static char fmtstr[] = { "%l:%M" "%P on %A, %d %B %Y" }; void putf(char *cp, char *where) { #ifdef HAVE_UNAME - struct utsname name; + struct utsname name; #endif - char *slash; - time_t t; - char db[100]; + char *slash; + time_t t; + char db[100]; -/* if we don't have uname, set these to sensible values */ - char *sysname = "Unix", - *machine = "", - *release = "", - *version = ""; + /* if we don't have uname, set these to sensible values */ + char *sysname = "Unix", + *machine = "", + *release = "", + *version = ""; #ifdef HAVE_UNAME - uname(&name); - sysname=name.sysname; - machine=name.machine; - release=name.release; - version=name.version; + uname(&name); + sysname=name.sysname; + machine=name.machine; + release=name.release; + version=name.version; #endif - putlocation = where; + putlocation = where; - while (*cp) { - if (*cp != '%') { - putchr(*cp++); - continue; - } - switch (*++cp) { - - case 't': -#ifdef STREAMSPTY - /* names are like /dev/pts/2 -- we want pts/2 */ - slash = strchr(line+1, '/'); -#else - slash = strrchr(line, '/'); -#endif - if (slash == (char *) 0) - putstr(line); - else - putstr(&slash[1]); - break; - - case 'h': - putstr(editedhost); - break; - - case 's': - putstr(sysname); - break; - - case 'm': - putstr(machine); - break; - - case 'r': - putstr(release); - break; - - case 'v': - putstr(version); - break; - - case 'd': - time(&t); - strftime(db, sizeof(db), fmtstr, localtime(&t)); - putstr(db); - break; - - case '%': - putchr('%'); - break; - } - cp++; + while (*cp) { + if (*cp != '%') { + putchr(*cp++); + continue; } + switch (*++cp) { + + case 't': +#ifdef STREAMSPTY + /* names are like /dev/pts/2 -- we want pts/2 */ + slash = strchr(line+1, '/'); +#else + slash = strrchr(line, '/'); +#endif + if (slash == (char *) 0) + putstr(line); + else + putstr(&slash[1]); + break; + + case 'h': + putstr(editedhost); + break; + + case 's': + putstr(sysname); + break; + + case 'm': + putstr(machine); + break; + + case 'r': + putstr(release); + break; + + case 'v': + putstr(version); + break; + + case 'd': + time(&t); + strftime(db, sizeof(db), fmtstr, localtime(&t)); + putstr(db); + break; + + case '%': + putchr('%'); + break; + } + cp++; + } } #ifdef DIAGNOSTICS /* * Print telnet options and commands in plain text, if possible. */ - void +void printoption(char *fmt, int option) { - if (TELOPT_OK(option)) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s %s\r\n", - fmt, - TELOPT(option)); - else if (TELCMD_OK(option)) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s %s\r\n", - fmt, - TELCMD(option)); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s %d\r\n", - fmt, - option); - nfrontp += strlen(nfrontp); - return; + if (TELOPT_OK(option)) + output_data("%s %s\r\n", + fmt, + TELOPT(option)); + else if (TELCMD_OK(option)) + output_data("%s %s\r\n", + fmt, + TELCMD(option)); + else + output_data("%s %d\r\n", + fmt, + option); + return; } - void +void printsub(int direction, unsigned char *pointer, int length) /* '<' or '>' */ /* where suboption data sits */ @@ -555,995 +530,624 @@ printsub(int direction, unsigned char *pointer, int length) int i; char buf[512]; - if (!(diagnostic & TD_OPTIONS)) - return; + if (!(diagnostic & TD_OPTIONS)) + return; - if (direction) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "td: %s suboption ", - direction == '<' ? "recv" : "send"); - nfrontp += strlen(nfrontp); - if (length >= 3) { - int j; + if (direction) { + output_data("td: %s suboption ", + direction == '<' ? "recv" : "send"); + if (length >= 3) { + int j; - i = pointer[length-2]; - j = pointer[length-1]; + i = pointer[length-2]; + j = pointer[length-1]; - if (i != IAC || j != SE) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "(terminated by "); - nfrontp += strlen(nfrontp); - if (TELOPT_OK(i)) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s ", - TELOPT(i)); - else if (TELCMD_OK(i)) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s ", - TELCMD(i)); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d ", - i); - nfrontp += strlen(nfrontp); - if (TELOPT_OK(j)) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s", - TELOPT(j)); - else if (TELCMD_OK(j)) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s", - TELCMD(j)); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d", - j); - nfrontp += strlen(nfrontp); - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - ", not IAC SE!) "); - nfrontp += strlen(nfrontp); - } - } - length -= 2; - } - if (length < 1) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "(Empty suboption??\?)"); - nfrontp += strlen(nfrontp); - return; - } - switch (pointer[0]) { - case TELOPT_TTYPE: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "TERMINAL-TYPE "); - nfrontp += strlen(nfrontp); - switch (pointer[1]) { - case TELQUAL_IS: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "IS \"%.*s\"", - length-2, - (char *)pointer+2); - break; - case TELQUAL_SEND: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "SEND"); - break; - default: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "- unknown qualifier %d (0x%x).", - pointer[1], pointer[1]); - } - nfrontp += strlen(nfrontp); - break; - case TELOPT_TSPEED: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "TERMINAL-SPEED"); - nfrontp += strlen(nfrontp); - if (length < 2) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case TELQUAL_IS: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " IS %.*s", - length-2, - (char *)pointer+2); - nfrontp += strlen(nfrontp); - break; - default: - if (pointer[1] == 1) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " SEND"); + if (i != IAC || j != SE) { + output_data("(terminated by "); + if (TELOPT_OK(i)) + output_data("%s ", + TELOPT(i)); + else if (TELCMD_OK(i)) + output_data("%s ", + TELCMD(i)); else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d (unknown)", - pointer[1]); - nfrontp += strlen(nfrontp); - for (i = 2; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[i]); - nfrontp += strlen(nfrontp); - } - break; + output_data("%d ", + i); + if (TELOPT_OK(j)) + output_data("%s", + TELOPT(j)); + else if (TELCMD_OK(j)) + output_data("%s", + TELCMD(j)); + else + output_data("%d", + j); + output_data(", not IAC SE!) "); } + } + length -= 2; + } + if (length < 1) { + output_data("(Empty suboption??\?)"); + return; + } + switch (pointer[0]) { + case TELOPT_TTYPE: + output_data("TERMINAL-TYPE "); + switch (pointer[1]) { + case TELQUAL_IS: + output_data("IS \"%.*s\"", + length-2, + (char *)pointer+2); break; - - case TELOPT_LFLOW: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "TOGGLE-FLOW-CONTROL"); - nfrontp += strlen(nfrontp); - if (length < 2) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case LFLOW_OFF: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " OFF"); - break; - case LFLOW_ON: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ON"); - break; - case LFLOW_RESTART_ANY: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " RESTART-ANY"); - break; - case LFLOW_RESTART_XON: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " RESTART-XON"); - break; - default: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d (unknown)", - pointer[1]); - } - nfrontp += strlen(nfrontp); + case TELQUAL_SEND: + output_data("SEND"); + break; + default: + output_data("- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + case TELOPT_TSPEED: + output_data("TERMINAL-SPEED"); + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case TELQUAL_IS: + output_data(" IS %.*s", length-2, (char *)pointer+2); + break; + default: + if (pointer[1] == 1) + output_data(" SEND"); + else + output_data(" %d (unknown)", pointer[1]); for (i = 2; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[i]); - nfrontp += strlen(nfrontp); + output_data(" ?%d?", pointer[i]); } break; + } + break; - case TELOPT_NAWS: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "NAWS"); - nfrontp += strlen(nfrontp); - if (length < 2) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - if (length == 2) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[1]); - nfrontp += strlen(nfrontp); - break; - } - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d %d (%d)", - pointer[1], - pointer[2], - (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); - nfrontp += strlen(nfrontp); - if (length == 4) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[3]); - nfrontp += strlen(nfrontp); - break; - } - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d %d (%d)", - pointer[3], pointer[4], - (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); - nfrontp += strlen(nfrontp); - for (i = 5; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[i]); - nfrontp += strlen(nfrontp); - } + case TELOPT_LFLOW: + output_data("TOGGLE-FLOW-CONTROL"); + if (length < 2) { + output_data(" (empty suboption??\?)"); break; + } + switch (pointer[1]) { + case LFLOW_OFF: + output_data(" OFF"); + break; + case LFLOW_ON: + output_data(" ON"); + break; + case LFLOW_RESTART_ANY: + output_data(" RESTART-ANY"); + break; + case LFLOW_RESTART_XON: + output_data(" RESTART-XON"); + break; + default: + output_data(" %d (unknown)", + pointer[1]); + } + for (i = 2; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; - case TELOPT_LINEMODE: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "LINEMODE "); - nfrontp += strlen(nfrontp); - if (length < 2) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); + case TELOPT_NAWS: + output_data("NAWS"); + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + if (length == 2) { + output_data(" ?%d?", + pointer[1]); + break; + } + output_data(" %u %u(%u)", + pointer[1], + pointer[2], + (((unsigned int)pointer[1])<<8) + pointer[2]); + if (length == 4) { + output_data(" ?%d?", + pointer[3]); + break; + } + output_data(" %u %u(%u)", + pointer[3], + pointer[4], + (((unsigned int)pointer[3])<<8) + pointer[4]); + for (i = 5; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + + case TELOPT_LINEMODE: + output_data("LINEMODE "); + if (length < 2) { + output_data(" (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case WILL: + output_data("WILL "); + goto common; + case WONT: + output_data("WONT "); + goto common; + case DO: + output_data("DO "); + goto common; + case DONT: + output_data("DONT "); + common: + if (length < 3) { + output_data("(no option??\?)"); break; } - switch (pointer[1]) { - case WILL: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "WILL "); - goto common; - case WONT: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "WONT "); - goto common; - case DO: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "DO "); - goto common; - case DONT: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "DONT "); - common: - nfrontp += strlen(nfrontp); - if (length < 3) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "(no option??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[2]) { - case LM_FORWARDMASK: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "Forward Mask"); - nfrontp += strlen(nfrontp); - for (i = 3; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %x", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - default: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d (unknown)", - pointer[2]); - nfrontp += strlen(nfrontp); - for (i = 3; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d", - pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - } - break; - - case LM_SLC: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "SLC"); - nfrontp += strlen(nfrontp); - for (i = 2; i < length - 2; i += 3) { - if (SLC_NAME_OK(pointer[i+SLC_FUNC])) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %s", - SLC_NAME(pointer[i+SLC_FUNC])); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d", - pointer[i+SLC_FUNC]); - nfrontp += strlen(nfrontp); - switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { - case SLC_NOSUPPORT: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " NOSUPPORT"); break; - case SLC_CANTCHANGE: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " CANTCHANGE"); break; - case SLC_VARIABLE: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " VARIABLE"); - break; - case SLC_DEFAULT: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " DEFAULT"); - break; - } - nfrontp += strlen(nfrontp); - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s%s%s", - pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", - pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", - pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); - nfrontp += strlen(nfrontp); - if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| - SLC_FLUSHOUT| SLC_LEVELBITS)) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "(0x%x)", - pointer[i+SLC_FLAGS]); - nfrontp += strlen(nfrontp); - } - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d;", - pointer[i+SLC_VALUE]); - nfrontp += strlen(nfrontp); - if ((pointer[i+SLC_VALUE] == IAC) && - (pointer[i+SLC_VALUE+1] == IAC)) - i++; - } - for (; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - - case LM_MODE: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "MODE "); - nfrontp += strlen(nfrontp); - if (length < 3) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "(no mode??\?)"); - nfrontp += strlen(nfrontp); - break; - } - { - char tbuf[32]; - 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" : "", - pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", - pointer[2]&MODE_ACK ? "|ACK" : ""); - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s", - tbuf[1] ? &tbuf[1] : "0"); - nfrontp += strlen(nfrontp); - } - if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (0x%x)", - pointer[2]); - nfrontp += strlen(nfrontp); - } + switch (pointer[2]) { + case LM_FORWARDMASK: + output_data("Forward Mask"); for (i = 3; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?0x%x?", - pointer[i]); - nfrontp += strlen(nfrontp); + output_data(" %x", pointer[i]); } break; default: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d (unknown)", - pointer[1]); - nfrontp += strlen(nfrontp); - for (i = 2; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d", pointer[i]); - nfrontp += strlen(nfrontp); + output_data("%d (unknown)", + pointer[2]); + for (i = 3; i < length; i++) { + output_data(" %d", + pointer[i]); } + break; } break; - case TELOPT_STATUS: { - char *cp; - int j, k; - - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "STATUS"); - nfrontp += strlen(nfrontp); - - switch (pointer[1]) { - default: - if (pointer[1] == TELQUAL_SEND) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " SEND"); + case LM_SLC: + output_data("SLC"); + for (i = 2; i < length - 2; i += 3) { + if (SLC_NAME_OK(pointer[i+SLC_FUNC])) + output_data(" %s", + SLC_NAME(pointer[i+SLC_FUNC])); else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d (unknown)", - pointer[1]); - nfrontp += strlen(nfrontp); - for (i = 2; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[i]); - nfrontp += strlen(nfrontp); + output_data(" %d", + pointer[i+SLC_FUNC]); + switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { + case SLC_NOSUPPORT: + output_data(" NOSUPPORT"); + break; + case SLC_CANTCHANGE: + output_data(" CANTCHANGE"); + break; + case SLC_VARIABLE: + output_data(" VARIABLE"); + break; + case SLC_DEFAULT: + output_data(" DEFAULT"); + break; } + output_data("%s%s%s", + pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); + if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| + SLC_FLUSHOUT| SLC_LEVELBITS)) { + output_data("(0x%x)", + pointer[i+SLC_FLAGS]); + } + output_data(" %d;", + pointer[i+SLC_VALUE]); + if ((pointer[i+SLC_VALUE] == IAC) && + (pointer[i+SLC_VALUE+1] == IAC)) + i++; + } + for (; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + + case LM_MODE: + output_data("MODE "); + if (length < 3) { + output_data("(no mode??\?)"); break; - case TELQUAL_IS: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " IS\r\n"); - nfrontp += strlen(nfrontp); + } + { + char tbuf[32]; + 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" : "", + pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", + pointer[2]&MODE_ACK ? "|ACK" : ""); + output_data("%s", + tbuf[1] ? &tbuf[1] : "0"); + } + if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { + output_data(" (0x%x)", + pointer[2]); + } + for (i = 3; i < length; i++) { + output_data(" ?0x%x?", + pointer[i]); + } + break; + default: + output_data("%d (unknown)", + pointer[1]); + for (i = 2; i < length; i++) { + output_data(" %d", pointer[i]); + } + } + break; - for (i = 2; i < length; i++) { - switch(pointer[i]) { - case DO: cp = "DO"; goto common2; - case DONT: cp = "DONT"; goto common2; - case WILL: cp = "WILL"; goto common2; - case WONT: cp = "WONT"; goto common2; - common2: - i++; - if (TELOPT_OK(pointer[i])) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %s %s", - cp, - TELOPT(pointer[i])); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %s %d", - cp, - pointer[i]); - nfrontp += strlen(nfrontp); + case TELOPT_STATUS: { + char *cp; + int j, k; - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\r\n"); - nfrontp += strlen(nfrontp); + output_data("STATUS"); + + switch (pointer[1]) { + default: + if (pointer[1] == TELQUAL_SEND) + output_data(" SEND"); + else + output_data(" %d (unknown)", + pointer[1]); + for (i = 2; i < length; i++) { + output_data(" ?%d?", + pointer[i]); + } + break; + case TELQUAL_IS: + output_data(" IS\r\n"); + + for (i = 2; i < length; i++) { + switch(pointer[i]) { + case DO: cp = "DO"; goto common2; + case DONT: cp = "DONT"; goto common2; + case WILL: cp = "WILL"; goto common2; + case WONT: cp = "WONT"; goto common2; + common2: + i++; + if (TELOPT_OK(pointer[i])) + output_data(" %s %s", + cp, + TELOPT(pointer[i])); + else + output_data(" %s %d", + cp, + pointer[i]); + + output_data("\r\n"); + break; + + case SB: + output_data(" SB "); + i++; + j = k = i; + while (j < length) { + if (pointer[j] == SE) { + if (j+1 == length) + break; + if (pointer[j+1] == SE) + j++; + else + break; + } + pointer[k++] = pointer[j++]; + } + printsub(0, &pointer[i], k - i); + if (i < length) { + output_data(" SE"); + i = j; + } else + i = j - 1; + + output_data("\r\n"); + + break; + + default: + output_data(" %d", + pointer[i]); + break; + } + } + break; + } + break; + } + + case TELOPT_XDISPLOC: + output_data("X-DISPLAY-LOCATION "); + switch (pointer[1]) { + case TELQUAL_IS: + output_data("IS \"%.*s\"", + length-2, + (char *)pointer+2); + break; + case TELQUAL_SEND: + output_data("SEND"); + break; + default: + output_data("- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + + case TELOPT_NEW_ENVIRON: + output_data("NEW-ENVIRON "); + goto env_common1; + case TELOPT_OLD_ENVIRON: + output_data("OLD-ENVIRON"); + env_common1: + switch (pointer[1]) { + case TELQUAL_IS: + output_data("IS "); + goto env_common; + case TELQUAL_SEND: + output_data("SEND "); + goto env_common; + case TELQUAL_INFO: + output_data("INFO "); + env_common: + { + int noquote = 2; + for (i = 2; i < length; i++ ) { + switch (pointer[i]) { + case NEW_ENV_VAR: + output_data("\" VAR " + noquote); + noquote = 2; break; - case SB: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " SB "); - nfrontp += strlen(nfrontp); - i++; - j = k = i; - while (j < length) { - if (pointer[j] == SE) { - if (j+1 == length) - break; - if (pointer[j+1] == SE) - j++; - else - break; - } - pointer[k++] = pointer[j++]; - } - printsub(0, &pointer[i], k - i); - if (i < length) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " SE"); - nfrontp += strlen(nfrontp); - i = j; - } else - i = j - 1; + case NEW_ENV_VALUE: + output_data("\" VALUE " + noquote); + noquote = 2; + break; - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\r\n"); - nfrontp += strlen(nfrontp); + case ENV_ESC: + output_data("\" ESC " + noquote); + noquote = 2; + break; + case ENV_USERVAR: + output_data("\" USERVAR " + noquote); + noquote = 2; break; default: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d", - pointer[i]); - nfrontp += strlen(nfrontp); - break; - } - } - break; - } - break; - } - - case TELOPT_XDISPLOC: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "X-DISPLAY-LOCATION "); - nfrontp += strlen(nfrontp); - switch (pointer[1]) { - case TELQUAL_IS: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "IS \"%.*s\"", - length-2, - (char *)pointer+2); - break; - case TELQUAL_SEND: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "SEND"); - break; - default: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "- unknown qualifier %d (0x%x).", - pointer[1], pointer[1]); - } - nfrontp += strlen(nfrontp); - break; - - case TELOPT_NEW_ENVIRON: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "NEW-ENVIRON "); - goto env_common1; - case TELOPT_OLD_ENVIRON: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "OLD-ENVIRON"); - env_common1: - nfrontp += strlen(nfrontp); - switch (pointer[1]) { - case TELQUAL_IS: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "IS "); - goto env_common; - case TELQUAL_SEND: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "SEND "); - goto env_common; - case TELQUAL_INFO: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "INFO "); - env_common: - nfrontp += strlen(nfrontp); - { - int noquote = 2; - for (i = 2; i < length; i++ ) { - switch (pointer[i]) { - case NEW_ENV_VAR: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\" VAR " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - case NEW_ENV_VALUE: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\" VALUE " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - case ENV_ESC: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\" ESC " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - case ENV_USERVAR: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\" USERVAR " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - default: - if (isprint(pointer[i]) && pointer[i] != '"') { - if (noquote) { - *nfrontp++ = '"'; - noquote = 0; - } - *nfrontp++ = pointer[i]; - } else { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\" %03o " + noquote, - pointer[i]); - nfrontp += strlen(nfrontp); - noquote = 2; + if (isprint(pointer[i]) && pointer[i] != '"') { + if (noquote) { + output_data ("\""); + noquote = 0; } - break; + output_data ("%c", pointer[i]); + } else { + output_data("\" %03o " + noquote, + pointer[i]); + noquote = 2; } - } - if (!noquote) - *nfrontp++ = '"'; - break; - } - } - break; - -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "AUTHENTICATION"); - nfrontp += strlen(nfrontp); - - if (length < 2) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case TELQUAL_REPLY: - case TELQUAL_IS: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %s ", - (pointer[1] == TELQUAL_IS) ? - "IS" : "REPLY"); - nfrontp += strlen(nfrontp); - if (AUTHTYPE_NAME_OK(pointer[2])) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s ", - AUTHTYPE_NAME(pointer[2])); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d ", - pointer[2]); - nfrontp += strlen(nfrontp); - if (length < 3) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "(partial suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s|%s", - ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - nfrontp += strlen(nfrontp); - - auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s", - buf); - nfrontp += strlen(nfrontp); - break; - - case TELQUAL_SEND: - i = 2; - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " SEND "); - nfrontp += strlen(nfrontp); - while (i < length) { - if (AUTHTYPE_NAME_OK(pointer[i])) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s ", - AUTHTYPE_NAME(pointer[i])); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d ", - pointer[i]); - nfrontp += strlen(nfrontp); - if (++i >= length) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "(partial suboption??\?)"); - nfrontp += strlen(nfrontp); break; } - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s|%s ", - ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - nfrontp += strlen(nfrontp); - ++i; } + if (!noquote) + output_data ("\""); break; - - case TELQUAL_NAME: - i = 2; - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " NAME \""); - nfrontp += strlen(nfrontp); - while (i < length) - *nfrontp++ = pointer[i++]; - *nfrontp++ = '"'; - break; - - default: - for (i = 2; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ?%d?", - pointer[i]); - nfrontp += strlen(nfrontp); - } - break; } + } + break; + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + output_data("AUTHENTICATION"); + + if (length < 2) { + output_data(" (empty suboption??\?)"); break; -#endif - -#if defined(ENCRYPTION) - case TELOPT_ENCRYPT: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "ENCRYPT"); - nfrontp += strlen(nfrontp); - if (length < 2) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (empty suboption?)"); - nfrontp += strlen(nfrontp); + } + switch (pointer[1]) { + case TELQUAL_REPLY: + case TELQUAL_IS: + output_data(" %s ", + (pointer[1] == TELQUAL_IS) ? + "IS" : "REPLY"); + if (AUTHTYPE_NAME_OK(pointer[2])) + output_data("%s ", + AUTHTYPE_NAME(pointer[2])); + else + output_data("%d ", + pointer[2]); + if (length < 3) { + output_data("(partial suboption??\?)"); break; } - switch (pointer[1]) { - case ENCRYPT_START: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " START"); - nfrontp += strlen(nfrontp); - break; + output_data("%s|%s", + ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); - case ENCRYPT_END: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " END"); - nfrontp += strlen(nfrontp); - break; + auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + output_data("%s", + buf); + break; - case ENCRYPT_REQSTART: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " REQUEST-START"); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_REQEND: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " REQUEST-END"); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_IS: - case ENCRYPT_REPLY: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %s ", - (pointer[1] == ENCRYPT_IS) ? - "IS" : "REPLY"); - nfrontp += strlen(nfrontp); - if (length < 3) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " (partial suboption?)"); - nfrontp += strlen(nfrontp); - break; - } - if (ENCTYPE_NAME_OK(pointer[2])) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s ", - ENCTYPE_NAME(pointer[2])); + case TELQUAL_SEND: + i = 2; + output_data(" SEND "); + while (i < length) { + if (AUTHTYPE_NAME_OK(pointer[i])) + output_data("%s ", + AUTHTYPE_NAME(pointer[i])); else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d (unknown)", - pointer[2]); - nfrontp += strlen(nfrontp); - - encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s", - buf); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_SUPPORT: - i = 2; - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " SUPPORT "); - nfrontp += strlen(nfrontp); - while (i < length) { - if (ENCTYPE_NAME_OK(pointer[i])) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s ", - ENCTYPE_NAME(pointer[i])); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d ", - pointer[i]); - nfrontp += strlen(nfrontp); - i++; + output_data("%d ", + pointer[i]); + if (++i >= length) { + output_data("(partial suboption??\?)"); + break; } - break; - - case ENCRYPT_ENC_KEYID: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " ENC_KEYID %d", - pointer[1]); - nfrontp += strlen(nfrontp); - goto encommon; - - case ENCRYPT_DEC_KEYID: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " DEC_KEYID %d", - pointer[1]); - nfrontp += strlen(nfrontp); - goto encommon; - - default: - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d (unknown)", - pointer[1]); - nfrontp += strlen(nfrontp); - encommon: - for (i = 2; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d", - pointer[i]); - nfrontp += strlen(nfrontp); - } - break; + output_data("%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; -#endif + + case TELQUAL_NAME: + i = 2; + output_data(" NAME \"%.*s\"", + length - 2, + pointer); + break; default: - if (TELOPT_OK(pointer[0])) - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s (unknown)", - TELOPT(pointer[0])); - else - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%d (unknown)", - pointer[i]); - nfrontp += strlen(nfrontp); - for (i = 1; i < length; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %d", - pointer[i]); - nfrontp += strlen(nfrontp); + for (i = 2; i < length; i++) { + output_data(" ?%d?", + pointer[i]); } break; } - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "\r\n"); - nfrontp += strlen(nfrontp); + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + output_data("ENCRYPT"); + if (length < 2) { + output_data(" (empty suboption?)"); + break; + } + switch (pointer[1]) { + case ENCRYPT_START: + output_data(" START"); + break; + + case ENCRYPT_END: + output_data(" END"); + break; + + case ENCRYPT_REQSTART: + output_data(" REQUEST-START"); + break; + + case ENCRYPT_REQEND: + output_data(" REQUEST-END"); + break; + + case ENCRYPT_IS: + case ENCRYPT_REPLY: + output_data(" %s ", + (pointer[1] == ENCRYPT_IS) ? + "IS" : "REPLY"); + if (length < 3) { + output_data(" (partial suboption?)"); + break; + } + if (ENCTYPE_NAME_OK(pointer[2])) + output_data("%s ", + ENCTYPE_NAME(pointer[2])); + else + output_data(" %d (unknown)", + pointer[2]); + + encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + output_data("%s", + buf); + break; + + case ENCRYPT_SUPPORT: + i = 2; + output_data(" SUPPORT "); + while (i < length) { + if (ENCTYPE_NAME_OK(pointer[i])) + output_data("%s ", + ENCTYPE_NAME(pointer[i])); + else + output_data("%d ", + pointer[i]); + i++; + } + break; + + case ENCRYPT_ENC_KEYID: + output_data(" ENC_KEYID %d", pointer[1]); + goto encommon; + + case ENCRYPT_DEC_KEYID: + output_data(" DEC_KEYID %d", pointer[1]); + goto encommon; + + default: + output_data(" %d (unknown)", pointer[1]); + encommon: + for (i = 2; i < length; i++) { + output_data(" %d", pointer[i]); + } + break; + } + break; +#endif + + default: + if (TELOPT_OK(pointer[0])) + output_data("%s (unknown)", + TELOPT(pointer[0])); + else + output_data("%d (unknown)", + pointer[i]); + for (i = 1; i < length; i++) { + output_data(" %d", pointer[i]); + } + break; + } + output_data("\r\n"); } /* * Dump a data buffer in hex and ascii to the output data stream. */ - void +void printdata(char *tag, char *ptr, int cnt) { - int i; - char xbuf[30]; + int i; + char xbuf[30]; - while (cnt) { - /* flush net output buffer if no room for new data) */ - if ((&netobuf[BUFSIZ] - nfrontp) < 80) { - netflush(); - } - - /* add a line of output */ - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%s: ", - tag); - nfrontp += strlen(nfrontp); - for (i = 0; i < 20 && cnt; i++) { - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - "%02x", - *ptr); - nfrontp += strlen(nfrontp); - if (isprint(*ptr)) { - xbuf[i] = *ptr; - } else { - xbuf[i] = '.'; - } - if (i % 2) { - *nfrontp = ' '; - nfrontp++; - } - cnt--; - ptr++; - } - xbuf[i] = '\0'; - snprintf(nfrontp, - BUFSIZ - (nfrontp - netobuf), - " %s\r\n", - xbuf); - nfrontp += strlen(nfrontp); + while (cnt) { + /* flush net output buffer if no room for new data) */ + if ((&netobuf[BUFSIZ] - nfrontp) < 80) { + netflush(); } + + /* add a line of output */ + output_data("%s: ", tag); + for (i = 0; i < 20 && cnt; i++) { + output_data("%02x", *ptr); + if (isprint(*ptr)) { + xbuf[i] = *ptr; + } else { + xbuf[i] = '.'; + } + if (i % 2) { + output_data(" "); + } + cnt--; + ptr++; + } + xbuf[i] = '\0'; + output_data(" %s\r\n", xbuf); + } } #endif /* DIAGNOSTICS */