📄 remote.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 + -