⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utility.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)utility.c	8.2 (Berkeley) 12/15/93";#endif /* not lint */#define PRINTOPTIONS#include "telnetd.h"/* * utility functions performing io related tasks *//* * 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. */    voidttloop(){    void netflush();    DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n");		     nfrontp += strlen(nfrontp);});    if (nfrontp-nbackp) {	netflush();    }    ncc = read(net, netibuf, sizeof netibuf);    if (ncc < 0) {	syslog(LOG_INFO, "ttloop:  read: %m\n");	exit(1);    } else if (ncc == 0) {	syslog(LOG_INFO, "ttloop:  peer died: %m\n");	exit(1);    }    DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc);		     nfrontp += strlen(nfrontp);});    netip = netibuf;    telrcv();			/* state machine */    if (ncc > 0) {	pfrontp = pbackp = ptyobuf;	telrcv();    }}  /* end of ttloop *//* * Check a descriptor to see if out of band data exists on it. */    intstilloob(s)    int	s;		/* socket number */{    static struct timeval timeout = { 0 };    fd_set	excepts;    int value;    do {	FD_ZERO(&excepts);	FD_SET(s, &excepts);	value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);    } while ((value == -1) && (errno == EINTR));    if (value < 0) {	fatalperror(pty, "select");    }    if (FD_ISSET(s, &excepts)) {	return 1;    } else {	return 0;    }}	voidptyflush(){	int n;	if ((n = pfrontp - pbackp) > 0) {		DIAG((TD_REPORT | TD_PTYDATA),			{ sprintf(nfrontp, "td: ptyflush %d chars\r\n", n);			  nfrontp += strlen(nfrontp); });		DIAG(TD_PTYDATA, printdata("pd", pbackp, n));		n = write(pty, pbackp, n);	}	if (n < 0) {		if (errno == EWOULDBLOCK || errno == EINTR)			return;		cleanup(0);	}	pbackp += n;	if (pbackp == pfrontp)		pbackp = pfrontp = ptyobuf;}/* * nextitem() * *	Return the address of the next "item" in the TELNET data * stream.  This will be the address of the next character if * the current address is a user data character, or it will * be the address of the character following the TELNET command * if the current address is a TELNET IAC ("I Am a Command") * character. */    char *nextitem(current)    char	*current;{    if ((*current&0xff) != IAC) {	return current+1;    }    switch (*(current+1)&0xff) {    case DO:    case DONT:    case WILL:    case WONT:	return current+3;    case SB:		/* loop forever looking for the SE */	{	    register char *look = current+2;	    for (;;) {		if ((*look++&0xff) == IAC) {		    if ((*look++&0xff) == SE) {			return look;		    }		}	    }	}    default:	return current+2;    }}  /* end of nextitem *//* * netclear() * *	We are about to do a TELNET SYNCH operation.  Clear * the path to the network. * *	Things are a bit tricky since we may have sent the first * byte or so of a previous TELNET command into the network. * So, we have to scan the network buffer from the beginning * until we are up to where we want to be. * *	A side effect of what we do, just to keep things * simple, is to clear the urgent data pointer.  The principal * caller should be setting the urgent data pointer AFTER calling * us in any case. */    voidnetclear(){    register char *thisitem, *next;    char *good;#define	wewant(p)	((nfrontp > p) && ((*p&0xff) == IAC) && \				((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))#ifdef	ENCRYPTION    thisitem = nclearto > netobuf ? nclearto : netobuf;#else	/* ENCRYPTION */    thisitem = netobuf;#endif	/* ENCRYPTION */    while ((next = nextitem(thisitem)) <= nbackp) {	thisitem = next;    }    /* Now, thisitem is first before/at boundary. */#ifdef	ENCRYPTION    good = nclearto > netobuf ? nclearto : netobuf;#else	/* ENCRYPTION */    good = netobuf;	/* where the good bytes go */#endif	/* ENCRYPTION */    while (nfrontp > thisitem) {	if (wewant(thisitem)) {	    int length;	    next = thisitem;	    do {		next = nextitem(next);	    } while (wewant(next) && (nfrontp > next));	    length = next-thisitem;	    bcopy(thisitem, good, length);	    good += length;	    thisitem = next;	} else {	    thisitem = nextitem(thisitem);	}    }    nbackp = netobuf;    nfrontp = good;		/* next byte to be sent */    neturg = 0;}  /* end of netclear *//* *  netflush *		Send as much data as possible to the network, *	handling requests for urgent data. */    voidnetflush(){    int n;    extern int not42;    if ((n = nfrontp - nbackp) > 0) {	DIAG(TD_REPORT,	    { sprintf(nfrontp, "td: netflush %d chars\r\n", n);	      n += strlen(nfrontp);  /* get count first */	      nfrontp += strlen(nfrontp);  /* then move pointer */	    });#ifdef	ENCRYPTION	if (encrypt_output) {		char *s = nclearto ? nclearto : nbackp;		if (nfrontp - s > 0) {			(*encrypt_output)((unsigned char *)s, nfrontp-s);			nclearto = nfrontp;		}	}#endif	/* ENCRYPTION */	/*	 * if no urgent data, or if the other side appears to be an	 * old 4.2 client (and thus unable to survive TCP urgent data),	 * write the entire buffer in non-OOB mode.	 */	if ((neturg == 0) || (not42 == 0)) {	    n = write(net, nbackp, n);	/* normal write */	} else {	    n = neturg - nbackp;	    /*	     * In 4.2 (and 4.3) systems, there is some question about	     * what byte in a sendOOB operation is the "OOB" data.	     * To make ourselves compatible, we only send ONE byte	     * out of band, the one WE THINK should be OOB (though	     * we really have more the TCP philosophy of urgent data	     * rather than the Unix philosophy of OOB data).	     */	    if (n > 1) {		n = send(net, nbackp, n-1, 0);	/* send URGENT all by itself */	    } else {		n = send(net, nbackp, n, MSG_OOB);	/* URGENT data */	    }	}    }    if (n < 0) {	if (errno == EWOULDBLOCK || errno == EINTR)		return;	cleanup(0);    }    nbackp += n;#ifdef	ENCRYPTION    if (nbackp > nclearto)	nclearto = 0;#endif	/* ENCRYPTION */    if (nbackp >= neturg) {	neturg = 0;    }    if (nbackp == nfrontp) {	nbackp = nfrontp = netobuf;#ifdef	ENCRYPTION	nclearto = 0;#endif	/* ENCRYPTION */    }    return;}  /* end of netflush *//* * writenet * * Just a handy little function to write a bit of raw data to the net. * It will force a transmit of the buffer if necessary * * arguments *    ptr - A pointer to a character string to write *    len - How many bytes to write */	voidwritenet(ptr, len)	register unsigned char *ptr;	register 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();	}	bcopy(ptr, nfrontp, len);	nfrontp += len;}  /* end of writenet *//* * miscellaneous functions doing a variety of little jobs follow ... */	voidfatal(f, msg)	int f;	char *msg;{	char buf[BUFSIZ];	(void) sprintf(buf, "telnetd: %s.\r\n", msg);#ifdef	ENCRYPTION	if (encrypt_output) {		/*		 * Better turn off encryption first....		 * Hope it flushes...		 */		encrypt_send_end();		netflush();	}#endif	/* ENCRYPTION */	(void) write(f, buf, (int)strlen(buf));	sleep(1);	/*XXX*/	exit(1);}	voidfatalperror(f, msg)	int f;	char *msg;{	char buf[BUFSIZ], *strerror();	(void) sprintf(buf, "%s: %s\r\n", msg, strerror(errno));	fatal(f, buf);}char editedhost[32];	voidedithost(pat, host)	register char *pat;	register char *host;{	register char *res = editedhost;	char *strncpy();	if (!pat)		pat = "";	while (*pat) {		switch (*pat) {		case '#':			if (*host)				host++;			break;		case '@':			if (*host)				*res++ = *host++;			break;		default:			*res++ = *pat;			break;		}		if (res == &editedhost[sizeof editedhost - 1]) {			*res = '\0';			return;		}		pat++;	}	if (*host)		(void) strncpy(res, host,				sizeof editedhost - (res - editedhost) -1);	else		*res = '\0';	editedhost[sizeof editedhost - 1] = '\0';}static char *putlocation;	voidputstr(s)	register char *s;{	while (*s)		putchr(*s++);}	voidputchr(cc)	int 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" };	voidputf(cp, where)	register char *cp;	char *where;{	char *slash;	time_t t;	char db[100];#ifdef	STREAMSPTY	extern char *index();#else	extern char *rindex();#endif	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 = index(line+1, '/');#else			slash = rindex(line, '/');#endif			if (slash == (char *) 0)				putstr(line);			else				putstr(&slash[1]);			break;		case 'h':			putstr(editedhost);			break;		case 'd':			(void)time(&t);			(void)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. */	voidprintoption(fmt, option)	register char *fmt;	register int option;{	if (TELOPT_OK(option))		sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option));	else if (TELCMD_OK(option))		sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option));	else		sprintf(nfrontp, "%s %d\r\n", fmt, option);	nfrontp += strlen(nfrontp);	return;}    voidprintsub(direction, pointer, length)    char		direction;	/* '<' or '>' */    unsigned char	*pointer;	/* where suboption data sits */    int			length;		/* length of suboption data */{    register int i;    char buf[512];        if (!(diagnostic & TD_OPTIONS))		return;	if (direction) {	    sprintf(nfrontp, "td: %s suboption ",					direction == '<' ? "recv" : "send");	    nfrontp += strlen(nfrontp);	    if (length >= 3) {		register int j;		i = pointer[length-2];		j = pointer[length-1];		if (i != IAC || j != SE) {		    sprintf(nfrontp, "(terminated by ");		    nfrontp += strlen(nfrontp);		    if (TELOPT_OK(i))			sprintf(nfrontp, "%s ", TELOPT(i));		    else if (TELCMD_OK(i))			sprintf(nfrontp, "%s ", TELCMD(i));		    else			sprintf(nfrontp, "%d ", i);		    nfrontp += strlen(nfrontp);		    if (TELOPT_OK(j))			sprintf(nfrontp, "%s", TELOPT(j));		    else if (TELCMD_OK(j))			sprintf(nfrontp, "%s", TELCMD(j));		    else			sprintf(nfrontp, "%d", j);		    nfrontp += strlen(nfrontp);		    sprintf(nfrontp, ", not IAC SE!) ");		    nfrontp += strlen(nfrontp);		}	    }	    length -= 2;	}	if (length < 1) {	    sprintf(nfrontp, "(Empty suboption??\?)");	    nfrontp += strlen(nfrontp);	    return;	}	switch (pointer[0]) {	case TELOPT_TTYPE:	    sprintf(nfrontp, "TERMINAL-TYPE ");	    nfrontp += strlen(nfrontp);	    switch (pointer[1]) {	    case TELQUAL_IS:		sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2);		break;	    case TELQUAL_SEND:		sprintf(nfrontp, "SEND");		break;	    default:		sprintf(nfrontp,				"- unknown qualifier %d (0x%x).",				pointer[1], pointer[1]);	    }	    nfrontp += strlen(nfrontp);	    break;	case TELOPT_TSPEED:	    sprintf(nfrontp, "TERMINAL-SPEED");	    nfrontp += strlen(nfrontp);	    if (length < 2) {		sprintf(nfrontp, " (empty suboption??\?)");		nfrontp += strlen(nfrontp);		break;	    }	    switch (pointer[1]) {	    case TELQUAL_IS:		sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2);		nfrontp += strlen(nfrontp);		break;	    default:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -