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

📄 remote.c

📁 使用BorlandC++4.5编译的一个MUD客户端程序
💻 C
字号:
head	2.1;access;symbols;locks; strict;comment	@ * @;2.1date	95.10.24.15.46.14;	author tsurace;	state Release;branches;next	1.2;1.2date	95.10.18.22.08.21;	author tsurace;	state Beta;branches;next	1.1;1.1date	95.10.12.20.51.58;	author tsurace;	state Exp;branches;next	;desc@Remote connection management.@2.1log@Roll.@text@/* remote.c: Handle I/O to remote */

/*
 * $Id: remote.c 1.2 1995/10/18 22:08:21 tsurace Beta tsurace $
 * $Log: remote.c $ * Revision 1.2  1995/10/18  22:08:21  tsurace * Removed potentially dangerous errno=WSAGetLastError() hack. * (Maybe sys_errlist[errno] invalid?) *
 * Revision 1.1  1995/10/12  20:51:58  tsurace
 * Initial revision
 *
 */

#include "vt.h"
#include <errno.h>
#include <fcntl.h>

#ifdef __WIN32__ /* windows sockets */
/*
 * Win32 notes:
 *
 * I (tekHedd) would like to thank, compliment, bless, worship,
 * and otherwise suck up to the programmer who encapsulated
 * socket code in remote.c, window code in window.c, etc.  I could
 * kiss you!  (But I won't.)  
 *
 * read(), write(), and close() may not be used on sockets, you must
 * use send(), recv(), and closesocket(), and also ioctlsocket().
 */
# include <dos.h> /* sleep() */
# include <winsock.h>
# include "win32/replace.h"
  typedef const struct sockaddr FAR * CONNECT_SOCKET_T;
# define EWOULDBLOCK WSAEWOULDBLOCK      /* not the same as errno.h */
# define errno WSAGetLastError() /* Tricky, dangerous */
#else /* Berkeley (real) sockets */
# include <sys/uio.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
  extern unsigned long inet_addr();
  extern int errno;
# define closesocket(an_fd) close(an_fd)
#endif /* __WIN32__ */

#ifdef PROTOTYPES
static int get_in_addr(char *, struct in_addr *);
static void receive_input(Unode *rmt);
#else
static void receive_input();
#endif

#ifndef FD_ZERO
typedef struct fd_set_tag {
	long masks[9];
} DESCR_MASK;
#define FD_SET(n, p)   ((p)->masks[(n) / 32] |=	 (1 << ((n) % 32)))
#define FD_CLR(n, p)   ((p)->masks[(n) / 32] &= ~(1 << ((n) % 32)))
#define FD_ISSET(n, p) ((p)->masks[(n) / 32] &	 (1 << ((n) % 32)))
#define FD_ZERO(p)     bzero((p), sizeof(*(p)))
#else
typedef fd_set DESCR_MASK;
#endif

#define INBUF_SIZE 1024
extern int sys_nerr;
Unode rmt_ring;				/* Dummy node for remotes ring */
Unode *cur_rmt = NULL;			/* Remote being processed      */
String kin;

void init_rmt()
{
	rmt_ring.next = rmt_ring.prev = &rmt_ring;
	rmt_ring.dummy = 1;
}

void cleanup_rmt(void)
{
    ;
}

static int get_in_addr(name, addr)
	char *name;
	struct in_addr *addr;
{
	struct hostent *hostent;

	if (isdigit(*name)) {
		addr->s_addr = inet_addr(name);
		return addr->s_addr != (unsigned long) -1L;
	}
	hostent = gethostbyname(name);
	if (!hostent)
		return 0;
	bcopy(hostent->h_addr, (char *) addr, sizeof(struct in_addr));
	return 1;
}

Unode *new_rmt(addr, port)
	char *addr;
	int port;
{
	struct sockaddr_in saddr;
	struct in_addr hostaddr;
	int fd;
	Unode *rmt;
 
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(port);
	if (!get_in_addr(addr, &hostaddr)) {
		vtc_errmsg = "Couldn't find host";
		return NULL;
	}
	vtc_errmsg = NULL;
	bcopy(&hostaddr, &saddr.sin_addr, sizeof(struct in_addr));
	fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0)
		return NULL;
	if (connect(fd,
                    (CONNECT_SOCKET_T)&saddr,
                    sizeof(struct sockaddr_in)) < 0) {
		closesocket(fd);
		return NULL;
	}
#ifdef FNDELAY
	fcntl(fd, F_SETFL, FNDELAY);
#endif
#ifdef __WIN32__
        /* Inform windows of the new socket.  :/ */
        if (NULL != NewSocket (fd, FD_READ | FD_CLOSE))
        {
            vtc_errmsg = "WSAAsyncSelect failed";
            closesocket(fd); 
            return NULL;
        }
#endif
	rmt = unalloc();
	rmt->Raddr = vtstrdup(addr);
	rmt->Rport = port;
	rmt->Rfd = fd;
	rmt->Rbuf = New(String);
	*rmt->Rbuf = empty_string;
	rmt->Rtelnetbuf = New(String);
	*rmt->Rtelnetbuf = empty_string;
	rmt->Rwin = NULL;
	rmt->Rnetread = NULL;
	rmt->Rpromptread = NULL;
	rmt->Rrstack = NULL;
	rmt->Robj = NULL;
	rmt->Rback = rmt->Rbusy = rmt->Rraw = 0;
	rmt->Riac = rmt->Rintent = 0;
	rmt->Recho = 1;
	rmt->Rdisconnected = 0;
	rmt->prev = rmt_ring.prev;
	rmt->next = &rmt_ring;
	rmt_ring.prev = rmt_ring.prev->next = rmt;
	return rmt;
}

void disconnect(rmt)
	Unode *rmt;
{
	Func *func;
	Unode *old_rmt;
	int ormt_id;

	if (rmt->Rdisconnected)
		return;
	rmt->Rdisconnected = 1;
	func = find_func("disconnect_hook");
	if (func && func->cmd) {
		old_rmt = cur_rmt;
		if (cur_rmt)
			ormt_id = cur_rmt->id;
		cur_rmt = rmt;
		run_prog(func->cmd);
		cur_rmt = old_rmt && ormt_id == old_rmt->id ? old_rmt : NULL;
	}
	if (rmt->Rwin) {
		rmt->Rwin->Wrmt = NULL;
		update_echo_mode();
	}
	closesocket(rmt->Rfd);
	s_free(rmt->Rbuf);
	Discard(rmt->Rbuf, String);
	rmt->prev->next = rmt->next;
	rmt->next->prev = rmt->prev;
	if (cur_rmt == rmt)
		cur_rmt = NULL;
	destroy_pointers(rmt->frefs);
	break_pipe(rmt->Rrstack);
	discard_unode(rmt);
}

static void receive_input(rmt)
	Unode *rmt;
{
    int count;
    char block[INBUF_SIZE + 1];

    /* Get some data.  If we're interrupted or would block, don't worry! */
    count = recv(rmt->Rfd, block, INBUF_SIZE, 0);
    if (count > 0)       /* got some data */
    {
        block[count] = '\0';
        s_acat(rmt->Rbuf, block);
        rmt->Rinbuf = 1;
    }
    else if (-1 == count && errno != EINTR && errno != EWOULDBLOCK)
    {
        vtc_errflag = 1;
        vtc_errmsg = "Connection closed by foreign host";
        disconnect(rmt);
    }
    else /* 0 == count, disconnect on some versions of UNIX? */
    {
        vtc_errflag = 1;
        vtc_errmsg = NULL;
        disconnect(rmt);
    };
}

/*
 * In the unix version, this function processes all keyboard input.
 * 
 * In the MS-Windoze version, this is polled when the os tells us there
 * might be input on a socket, but keyboard input comes from events.
 */
int io_check(sec, usec)
	long sec, usec;
{
	struct timeval tv, *tvp;
 	DESCR_MASK readers; 
        DESCR_MASK exc;
	int count, nfd, fd;
	Unode *rp, *next;
	char block[INBUF_SIZE + 1];

	FD_ZERO(&readers);
	FD_ZERO(&exc);
	if (sec == -1) { 
		tvp = NULL; /* wait forever for input */
	} else {
		tv.tv_sec = sec;
		tv.tv_usec = usec;
		tvp = &tv;
	}
#ifdef __WIN32__ /* Can't use select() on stdin with Winsock */
    nfd = 0;
#else
 	FD_SET(0, &readers);  
	nfd = 1;
#endif /* __WIN32__ */
	for (rp = rmt_ring.next; !rp->dummy; rp = rp->next) {
		if ((rp->Rwin || rp->Rback) && !rp->Rbusy) {
			fd = rp->Rfd;
			FD_SET(fd, &readers);
			if (nfd <= fd)
				nfd = fd + 1;
		}
	}
	count = select(nfd, &readers, (DESCR_MASK *) NULL, &exc, tvp);
	if (count == 0 || count == -1 && errno == EINTR)
		return 0;
	if (count == -1)
		operror("select", NULL);
	for (rp = rmt_ring.next; !rp->dummy; rp = next) {
		next = rp->next;
		if ((rp->Rwin || rp->Rback) && !rp->Rbusy) {
			if (FD_ISSET(rp->Rfd, &readers))
				receive_input(rp);
		}
	};
#ifndef __WIN32__ /* Ignore stdin? */
	/* Check for keyboard input */
	if (FD_ISSET(0, &readers)) {
		do
			count = read(0, block, INBUF_SIZE);
		while (count == -1 && errno == EINTR);
		s_cat(&kin, cstr_sl(block, count));
	};
#endif
	return 1;
}


int transmit(rmt, cstr)
	Unode *rmt;
	Cstr cstr;
{
	int written;

	if (rmt->Rdisconnected)
		return -1;
	while (cstr.l > 0) {
		written = send(rmt->Rfd, cstr.s, cstr.l, 0);
		if (written == -1) {
			if (errno == EWOULDBLOCK) {
				sleep(1);
				continue;
			}
			vtc_errflag = 1;
			vtc_errmsg = NULL;
			disconnect(rmt);
			return -1;
		}
		cstr.s += written;
		cstr.l -= written;
		if (cstr.l)
			sleep(1);
	}
	return 0;
}

int input_waiting(fd)
	int fd;
{
	struct timeval tv;
	DESCR_MASK readers;

	tv.tv_sec = tv.tv_usec = 0;
	FD_ZERO(&readers);
	FD_SET(fd, &readers);
	return select(fd + 1, &readers, (DESCR_MASK *) NULL,
		      (DESCR_MASK *) NULL, &tv);
}

int process_remote_text(rmt)
	Unode *rmt;
{
	int rid = rmt->id;
	char *s;

	for (s = rmt->Rbuf->c.s; *s; s++) {
		if (!(rmt->Rwin || rmt->Rback) || rmt->Rbusy) {
			s_cpy(rmt->Rbuf, cstr_sl(s, rmt->Rbuf->c.l -
				(s - rmt->Rbuf->c.s)));
			telnet_state_machine(rmt, 0);
			return 1;
		}
		rmt->Rinbuf = (s[1] != 0);
		telnet_state_machine(rmt, (unsigned char) *s);
		if (rmt->id != rid)
			return 0;
	}
	telnet_state_machine(rmt, 0);
	s_term(rmt->Rbuf, 0);
	rmt->Rinbuf = (rmt->Rbuf->c.l != 0);
	return 1;
}

void give_remote(rmt, is, isgoahead)
	Unode *rmt;
	Istr *is;
	int isgoahead;
{
	Func *func;

	is->refs++;
	if (rmt->Rrstack && !isgoahead) {
		resume_istr(&rmt->Rrstack, is);
	} else {
		func = (isgoahead) ? rmt->Rpromptread : rmt->Rnetread;
		if (func) {
			run_prog_istr(func->cmd, is, NULL, rmt);
		} else {
			output(rmt->Rwin, is->rs->str.c.s);
			if (!isgoahead)
				output(rmt->Rwin, "\n");
		}
	}
	dec_ref_istr(is);
}

@1.2log@Removed potentially dangerous errno=WSAGetLastError() hack.(Maybe sys_errlist[errno] invalid?)@text@d4 6a9 2 * $Id: remote.c 1.1 1995/10/12 20:51:58 tsurace Exp tsurace $ * $Log: remote.c $@1.1log@Initial revision@text@d4 5a8 2 * $Id$ * $Log$d32 1a32 1# define errno (errno=WSAGetLastError()) /* Tricky, dangerous */@

⌨️ 快捷键说明

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