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

📄 telnetd.c

📁 经典的unix下telnetd代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    close(t);	}    }#endif    show_issue();    /*     * 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;    if (cgetent(&buf, gettytab, gettyent) >= 0) {	char *HN;	if (cgetstr(buf, "he", &he) <= 0)	    he = NULL;	if (cgetstr(buf, "im", &IM) <= 0)	    IM = "";	if (cgetstr(buf, "hn", &HN) > 0) {	    strlcpy(host_name, HN, sizeof host_name);	    free(HN);	}	cgetclose();    } else {	IM = DEFAULT_IM;	he = NULL;    }    edithost(he, host_name);    if (he)	free(he);    if (hostinfo && *IM)	putf(IM, ptyibuf2);    if (IM != DEFAULT_IM && *IM)	free(IM);    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;    setsize = howmany(nfd, NFDBITS) * sizeof(fd_mask);    ibits = malloc(setsize);    obits = malloc(setsize);    xbits = malloc(setsize);    if (ibits == NULL || obits == NULL || xbits == NULL) {	syslog(LOG_ERR, "Out of memory");	exit(1);    }    timeout = time(NULL) + 5;    for (;;) {	int c;	/* wait for encryption to be turned on, but don't wait           indefinitely */	if(!startslave_called && (!encrypt_delay() || timeout > time(NULL))){	    startslave_called = 1;	    startslave(host, utmp_host, level, autoname);	}	if (ncc < 0 && pcc < 0)	    break;	memset(obits, 0, setsize);	memset(ibits, 0, setsize);	memset(xbits, 0, setsize);	/*	 * 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(f, xbits)) {	    SYNCHing = 1;	}	/*	 * Something to read from the network...	 */	if (FD_ISSET(f, 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(f, SIOCATMARK, (char *)&atmark);		if (atmark) {		    ncc = recv(f, netibuf, sizeof (netibuf), MSG_OOB);		    if ((ncc == -1) && (errno == EINVAL)) {			ncc = read(f, netibuf, sizeof (netibuf));			if (sequenceIs(didnetreceive, gotDM)) {			    SYNCHing = stilloob(f);			}		    }		} else {		    ncc = read(f, netibuf, sizeof (netibuf));		}	    } else {		ncc = read(f, 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#  define TCSIG TIOCSIG# endif#endif#ifdef	STREAMSPTY    int flowison = -1;  /* current state of flow: -1 is unknown */intreadstream(int p, char *ibuf, int bufsize){    int flags = 0;    int ret = 0;    struct termios *tsp;#if 0    struct termio *tp;#endif    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;    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 *//* * Send interrupt to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write intr char. */voidinterrupt(){    ptyflush();	/* half-hearted */#if defined(STREAMSPTY) && defined(TIOCSIGNAL)    /* Streams PTY style ioctl to post a signal */    if (really_stream)	{	    int sig = SIGINT;	    ioctl(ourpty, TIOCSIGNAL, &sig);	    ioctl(ourpty, I_FLUSH, FLUSHR);	}#else#ifdef	TCSIG    ioctl(ourpty, TCSIG, (char *)SIGINT);#else	/* TCSIG */    init_termbuf();    *pfrontp++ = slctab[SLC_IP].sptr ?	(unsigned char)*slctab[SLC_IP].sptr : '\177';#endif	/* TCSIG */#endif}/* * Send quit to process on other side of pty. * If it is in raw mode, just write NULL; * otherwise, write quit char. */voidsendbrk(){    ptyflush();	/* half-hearted */#ifdef	TCSIG    ioctl(ourpty, TCSIG, (char *)SIGQUIT);#else	/* TCSIG */    init_termbuf();    *pfrontp++ = slctab[SLC_ABORT].sptr ?	(unsigned char)*slctab[SLC_ABORT].sptr : '\034';#endif	/* TCSIG */}voidsendsusp(){#ifdef	SIGTSTP    ptyflush();	/* half-hearted */# ifdef	TCSIG    ioctl(ourpty, TCSIG, (char *)SIGTSTP);# else	/* TCSIG */    *pfrontp++ = slctab[SLC_SUSP].sptr ?	(unsigned char)*slctab[SLC_SUSP].sptr : '\032';# endif	/* TCSIG */#endif	/* SIGTSTP */}/* * When we get an AYT, if ^T is enabled, use that.  Otherwise, * just send back "[Yes]". */voidrecv_ayt(){#if	defined(SIGINFO) && defined(TCSIG)    if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {	ioctl(ourpty, TCSIG, (char *)SIGINFO);	return;    }#endif    output_data("\r\n[Yes]\r\n");}voiddoeof(){    init_termbuf();    *pfrontp++ = slctab[SLC_EOF].sptr ?	(unsigned char)*slctab[SLC_EOF].sptr : '\004';}

⌨️ 快捷键说明

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