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

📄 utility.c

📁 经典的unix下telnetd代码
💻 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. 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. */#define PRINTOPTIONS#include "telnetd.h"/* RCSID("$KTH: utility.c,v 1.25 2001/05/17 00:34:42 assar Exp $"); *//* * 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. * * return 0 if OK or 1 if interrupted by a signal. */intttloop(void){    void netflush(void);        DIAG(TD_REPORT, {	output_data("td: ttloop\r\n");    });    if (nfrontp-nbackp)	netflush();    ncc = read(net, netibuf, sizeof netibuf);    if (ncc < 0) {	if (errno == EINTR)	    return 1;	syslog(LOG_INFO, "ttloop:  read: %m");	exit(1);    } else if (ncc == 0) {	syslog(LOG_INFO, "ttloop:  peer died");	exit(1);    }    DIAG(TD_REPORT, {	output_data("td: ttloop read %d chars\r\n", ncc);    });    netip = netibuf;    telrcv();			/* state machine */    if (ncc > 0) {	pfrontp = pbackp = ptyobuf;	telrcv();    }    return 0;}  /* end of ttloop *//* * Check a descriptor to see if out of band data exists on it. */intstilloob(int s){    static struct timeval timeout = { 0 };    fd_set	excepts;    int value;    if (s >= FD_SETSIZE)	fatal(ourpty, "fd too large");    do {	FD_ZERO(&excepts);	FD_SET(s, &excepts);	value = select(s+1, 0, 0, &excepts, &timeout);    } while ((value == -1) && (errno == EINTR));    if (value < 0) {	fatalperror(ourpty, "select");    }    if (FD_ISSET(s, &excepts)) {	return 1;    } else {	return 0;    }}voidptyflush(void){    int n;    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;}/* * 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(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 */	char *look = current+2;	for (;;) {	    if ((*look++&0xff) == IAC) {		if ((*look++&0xff) == SE) {		    return look;		}	    }	}    }    default:	return current+2;    }}/* * 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(void){    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	thisitem = netobuf;#endif	while ((next = nextitem(thisitem)) <= nbackp) {	    thisitem = next;	}	/* 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 *//* *  netflush *		Send as much data as possible to the network, *	handling requests for urgent data. */voidnetflush(void){    int n;    extern int not42;    if ((n = nfrontp - nbackp) > 0) {	DIAG(TD_REPORT,	     { 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;	    }	}#endif	/*	 * 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 1 /* remove this to make it work between solaris 2.6 and linux */	if ((neturg == 0) || (not42 == 0)) {#endif	    n = write(net, nbackp, n);	/* normal write */#if 1 /* remove this to make it work between solaris 2.6 and linux */	} 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 */	    }	}#endif    }    if (n < 0) {	if (errno == EWOULDBLOCK || errno == EINTR)	    return;	cleanup(0);    }    nbackp += n;#ifdef ENCRYPTION    if (nbackp > nclearto)	nclearto = 0;#endif    if (nbackp >= neturg) {	neturg = 0;    }    if (nbackp == nfrontp) {	nbackp = nfrontp = netobuf;#ifdef ENCRYPTION	nclearto = 0;#endif    }    return;}/* * 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(unsigned char *ptr, int len){    /* 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;}/* * miscellaneous functions doing a variety of little jobs follow ... */void fatal(int f, char *msg){    char buf[BUFSIZ];    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);}voidfatalperror_errno(int f, const char *msg, int error){    char buf[BUFSIZ];        snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(error));    fatal(f, buf);}voidfatalperror(int f, const char *msg){    fatalperror_errno(f, msg, errno);}char editedhost[32];void edithost(char *pat, char *host){    char *res = editedhost;    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)	strlcpy (res, host,			 sizeof editedhost - (res - editedhost));    else	*res = '\0';    editedhost[sizeof editedhost - 1] = '\0';}static char *putlocation;voidputstr(char *s){    while (*s)	putchr(*s++);}voidputchr(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" };void putf(char *cp, char *where){#ifdef HAVE_UNAME    struct utsname name;#endif    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 = ""; #ifdef HAVE_UNAME    uname(&name);    sysname=name.sysname;    machine=name.machine;    release=name.release;    version=name.version;#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 = 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. */voidprintoption(char *fmt, int option){    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;}voidprintsub(int direction, unsigned char *pointer, int length)        		          	/* '<' or '>' */                 	         	/* where suboption data sits */       			       		/* length of suboption data */{    int i = 0;#ifdef AUTHENTICATION    unsigned char buf[512];#endif    if (!(diagnostic & TD_OPTIONS))	return;    if (direction) {	output_data("td: %s suboption ",		    direction == '<' ? "recv" : "send");	if (length >= 3) {	    int j;	    i = pointer[length-2];	    j = pointer[length-1];	    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		    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;    }

⌨️ 快捷键说明

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