summaryrefslogtreecommitdiff
path: root/fd.c
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@sun.com>2009-05-06 17:10:31 -0700
committerAlan Coopersmith <alan.coopersmith@sun.com>2009-05-06 17:10:31 -0700
commit0aab8135dae526b090dcb1ffab801023ac4084aa (patch)
tree3aa615a5196bddc76ff23a5e4b3ae6ab04a40588 /fd.c
parenteb05316a471da962eefe82c9b9a16a7590653ba7 (diff)
parentdef948f052a758850cadc022943517742b299441 (diff)
downloadxscope-0aab8135dae526b090dcb1ffab801023ac4084aa.tar.gz
Merge branch 'keithp'
Conflicts: common.c decode11.c fd.c fd.h print11.c prtype.c scope.c scope.h server.c table11.c x11.h xscope.man
Diffstat (limited to 'fd.c')
-rw-r--r--fd.c275
1 files changed, 249 insertions, 26 deletions
diff --git a/fd.c b/fd.c
index 616dc9c..af6c79b 100644
--- a/fd.c
+++ b/fd.c
@@ -62,6 +62,21 @@
#define bcopy(s,d,l) memmove(d,s,l)
#endif
+#include <sys/uio.h> /* for struct iovec, used by socket.h */
+#include <sys/socket.h> /* for AF_INET, SOCK_STREAM, ... */
+#include <sys/ioctl.h> /* for FIONCLEX, FIONBIO, ... */
+#ifdef SVR4
+#include <sys/filio.h>
+#endif
+#include <fcntl.h>
+#include <netinet/in.h> /* struct sockaddr_in */
+#include <sys/un.h> /* struct sockaddr_un */
+#include <netinet/tcp.h>
+#include <netdb.h> /* struct servent * and struct hostent * */
+#include <errno.h> /* for EINTR, EADDRINUSE, ... */
+extern int errno;
+
+
/*
All of this code is to support the handling of file descriptors (FD).
The idea is to keep a table of the FDs that are in use and why.
@@ -83,10 +98,19 @@ InitializeFD()
enterprocedure("InitializeFD");
/* get the number of file descriptors the system will let us use */
+#if defined(hpux) || defined(SVR4)
+ MaxFD = _NFILE - 1;
+#else
MaxFD = getdtablesize();
if (MaxFD > FD_SETSIZE) {
MaxFD = FD_SETSIZE;
}
+#endif
+ if (MaxFD > StaticMaxFD)
+ {
+ fprintf(stderr, "Recompile with larger StaticMaxFD value %d\n", MaxFD);
+ MaxFD = StaticMaxFD;
+ }
/* allocate space for a File Descriptor (FD) Table */
FDD = (struct FDDescriptor *)
@@ -110,20 +134,21 @@ InitializeFD()
MaxFD -= 4;
nFDsInUse = 0 /* stdin, stdout, stderr */ ;
- FD_ZERO(&ReadDescriptors);
+ ReadDescriptors = 0;
HighestFD = 0;
- UsingFD(fileno(stdin), (void (*)(int))NULL, NULL);
- UsingFD(fileno(stdout), (void (*)(int))NULL, NULL);
- UsingFD(fileno(stderr), (void (*)(int))NULL, NULL);
+ UsingFD(fileno(stdin), NULL, NULL, NULL);
+ UsingFD(fileno(stdout), NULL, NULL, NULL);
+ UsingFD(fileno(stderr), NULL, NULL, NULL);
}
/* ************************************************************ */
void
-UsingFD(fd, Handler, trans_conn)
+UsingFD(fd, Handler, FlushHandler, trans_conn)
FD fd;
void (*Handler)(int);
+ void (*FlushHandler)(int);
XtransConnInfo trans_conn;
{
if (FDD[fd].Busy)
@@ -132,13 +157,14 @@ UsingFD(fd, Handler, trans_conn)
FDD[fd].Busy = true;
FDD[fd].InputHandler = Handler;
+ FDD[fd].FlushHandler = FlushHandler;
#ifdef USE_XTRANS
FDD[fd].trans_conn = trans_conn;
#endif
if (Handler == NULL)
- FD_CLR(fd,&ReadDescriptors) /* clear fd bit */ ;
+ ReadDescriptors &= ~(1 << fd) /* clear fd bit */ ;
else
- FD_SET(fd,&ReadDescriptors) /* set fd bit */ ;
+ ReadDescriptors |= 1 << fd /* set fd bit */ ;
if (fd > HighestFD)
HighestFD = fd;
@@ -161,7 +187,7 @@ NotUsingFD(fd)
nFDsInUse -= 1;
FDD[fd].Busy = false;
- FD_CLR(fd,&ReadDescriptors) /* clear fd bit */ ;
+ ReadDescriptors &= ~(1 << fd) /* clear fd bit */ ;
while (!FDD[HighestFD].Busy && HighestFD > 0)
HighestFD -= 1;
@@ -195,7 +221,183 @@ EOFonFD(fd)
NotUsingFD(fd);
}
+FD
+AcceptConnection (ConnectionSocket)
+ FD ConnectionSocket;
+{
+ FD ClientFD;
+ struct sockaddr_in from;
+ int len = sizeof (from);
+ int tmp = 1;
+
+ enterprocedure("ConnectToClient");
+
+ ClientFD = accept(ConnectionSocket, (struct sockaddr *)&from, &len);
+ debug(4,(stderr, "Connect To Client: FD %d\n", ClientFD));
+ if (ClientFD < 0 && errno == EWOULDBLOCK)
+ {
+ debug(4,(stderr, "Almost blocked accepting FD %d\n", ClientFD));
+ panic("Can't connect to Client");
+ }
+ if (ClientFD < 0)
+ {
+ debug(4,(stderr, "NewConnection: error %d\n", errno));
+ panic("Can't connect to Client");
+ }
+
+#ifdef FD_CLOEXEC
+ (void)fcntl(ClientFD, F_SETFD, FD_CLOEXEC);
+#else
+ (void)ioctl(ClientFD, FIOCLEX, 0);
+#endif
+ /* ultrix reads hang on Unix sockets, hpux reads fail */
+#if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux))
+ (void) fcntl (ClientFD, F_SETFL, O_NONBLOCK);
+#else
+#ifdef FIOSNBIO
+ ioctl (ClientFD, FIOSNBIO, &ON);
+#else
+ (void) fcntl (ClientFD, F_SETFL, FNDELAY);
+#endif
+#endif
+ (void) setsockopt(ClientFD, IPPROTO_TCP, TCP_NODELAY, (char *) &tmp, sizeof (int));
+ return(ClientFD);
+}
+
+FD
+MakeConnection(server, port, report, trans_conn)
+ char *server;
+ short port;
+ int report;
+ XtransConnInfo *trans_conn; /* transport connection object */
+{
+ FD ServerFD;
+#ifdef USE_XTRANS
+ char address[256];
+ int connect_stat;
+ extern long ServerBasePort;
+
+ snprintf (address, sizeof(address), "%s:%d", server, port - ServerBasePort);
+ if ( (*trans_conn = _X11TransOpenCOTSClient(address)) == NULL ) {
+ debug(1,(stderr, "OpenCOTSClient failed\n"));
+ panic("Can't open connection to Server");
+ }
+ if ((connect_stat = _X11TransConnect(*trans_conn,address)) < 0 ) {
+ _X11TransClose(*trans_conn);
+ *trans_conn = NULL;
+ debug(1,(stderr, "TransConnect failed\n"));
+ panic("Can't open connection to Server");
+ }
+
+ ServerFD = _X11TransGetConnectionNumber(*trans_conn);
+#else /* !USE_XTRANS */
+ char HostName[512];
+ struct sockaddr_in sin;
+ struct sockaddr_un sun;
+ struct sockaddr *saddr;
+ int salen;
+ struct hostent *hp;
+ int tmp = 1;
+#ifndef SO_DONTLINGER
+ struct linger linger;
+#endif /* SO_DONTLINGER */
+
+ enterprocedure("ConnectToServer");
+
+ /* establish a socket to the name server for this host */
+ /* determine the host machine for this process */
+ if (*server == '\0')
+ {
+ sun.sun_family = AF_UNIX;
+ sprintf (sun.sun_path, "/tmp/.X11-unix/X%d", port - 6000);
+ salen = sizeof (sun.sun_family) + strlen (sun.sun_path) + 1;
+ saddr = (struct sockaddr *) &sun;
+ }
+ else
+ {
+ debug(4,(stderr, "try to connect on %s\n", server));
+
+ bzero((char *)&sin, sizeof(sin));
+ sin.sin_addr.s_addr = inet_addr (server);
+ if ((long) sin.sin_addr.s_addr == -1)
+ {
+ hp = gethostbyname(server);
+ if (hp == 0)
+ {
+ perror("gethostbyname failed");
+ debug(1,(stderr, "gethostbyname failed for %s\n", server));
+ panic("Can't open connection to Server");
+ }
+ bcopy((char *)hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
+ }
+
+ sin.sin_family = AF_INET;
+
+ if (port == ScopePort
+ && strcmp(server, ScopeHost) == 0)
+ {
+ char error_message[100];
+ (void)sprintf(error_message, "Trying to attach to myself: %s,%d\n",
+ server, sin.sin_port);
+ panic(error_message);
+ }
+
+ sin.sin_port = htons (port);
+ salen = sizeof (sin);
+ saddr = (struct sockaddr *) &sin;
+ }
+
+ ServerFD = socket(saddr->sa_family, SOCK_STREAM, 0);
+ if (ServerFD < 0)
+ {
+ perror("socket() to Server failed");
+ debug(1,(stderr, "socket failed\n"));
+ panic("Can't open connection to Server");
+ }
+ (void) setsockopt(ServerFD, SOL_SOCKET, SO_REUSEADDR, (char *) NULL, 0);
+#ifdef SO_USELOOPBACK
+ (void) setsockopt(ServerFD, SOL_SOCKET, SO_USELOOPBACK,(char *) NULL, 0);
+#endif
+ (void) setsockopt(ServerFD, IPPROTO_TCP, TCP_NODELAY, (char *) &tmp, sizeof (int));
+#ifdef SO_DONTLINGER
+ (void) setsockopt(ServerFD, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
+#else /* SO_DONTLINGER */
+ linger.l_onoff = 0;
+ linger.l_linger = 0;
+ (void) setsockopt(ServerFD, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof linger);
+#endif /* SO_DONTLINGER */
+
+ /* ******************************************************** */
+ /* try to connect to Server */
+
+ if (connect(ServerFD, saddr, salen) < 0)
+ {
+ debug(4,(stderr, "connect returns errno of %d\n", errno));
+ if (errno != 0)
+ if (report)
+ perror("connect");
+ switch (errno)
+ {
+ case ECONNREFUSED:
+ /* experience says this is because there is no Server
+ to connect to */
+ (void)close(ServerFD);
+ debug(1,(stderr, "No Server\n"));
+ if (report)
+ warn("Can't open connection to Server");
+ return(-1);
+
+ default:
+ (void)close(ServerFD);
+ panic("Can't open connection to Server");
+ }
+ }
+#endif /* USE_XTRANS */
+ debug(4,(stderr, "Connect To Server: FD %d\n", ServerFD));
+ return(ServerFD);
+}
+
/* ************************************************************ */
/* */
/* Main Loop -- wait for input from any source and Process */
@@ -212,19 +414,25 @@ MainLoop(void)
while (true)
{
- fd_set rfds, xfds;
+ int rfds, wfds, xfds;
short nfds;
short fd;
/* wait for something */
- rfds = ReadDescriptors;
+ rfds = ReadDescriptors & ~BlockedReadDescriptors;
+ wfds = ReadDescriptors & WriteDescriptors;
xfds = rfds;
debug(128,(stderr, "select %d, rfds = 0%o\n", HighestFD + 1, rfds));
- nfds = select(HighestFD + 1, (struct fd_set *) &rfds,
- (struct fd_set *) NULL, (struct fd_set *) &xfds, NULL);
- debug(128,(stderr, "select nfds = 0%o, rfds = 0%o, xfds 0%o\n",
- nfds, rfds, xfds));
+ if (Interrupt || (rfds == 0 && wfds == 0))
+ {
+ ReadCommands ();
+ Interrupt = 0;
+ continue;
+ }
+ nfds = select(HighestFD + 1, &rfds, &wfds, &xfds, (struct timeval *)NULL);
+ debug(128,(stderr, "select nfds = 0%o, rfds = 0%o, 0%o, xfds 0%o\n",
+ nfds, rfds, wfds, xfds));
if (nfds < 0)
{
@@ -239,7 +447,15 @@ MainLoop(void)
continue;
}
- panic("Select returns error");
+ if (Interrupt)
+ {
+ ReadCommands ();
+ Interrupt = 0;
+ }
+ else
+ {
+ panic("Select returns error");
+ }
continue /* to end of while loop */ ;
}
@@ -250,25 +466,32 @@ MainLoop(void)
}
/* check each fd to see if it has input */
- for (fd = 0; 0 < nfds && fd <= HighestFD; fd++)
+ for (fd = 0; fd <= HighestFD; fd++)
{
/*
check all returned fd's; this prevents
starvation of later clients by earlier clients
*/
- if (FD_ISSET(fd,&rfds) == 0)
- continue;
-
- nfds -= 1;
-
- if (FDD[fd].InputHandler == NULL)
+ if (rfds & (1 << fd))
+ {
+ if (FDD[fd].InputHandler == NULL)
+ {
+ panic("FD selected with no handler");
+ debug(1,(stderr, "FD %d has NULL handler\n", fd));
+ }
+ else
+ (FDD[fd].InputHandler)(fd);
+ }
+ if (wfds & (1 << fd))
+ {
+ if (FDD[fd].FlushHandler == NULL)
{
- panic("FD selected with no handler");
- debug(1,(stderr, "FD %d has NULL handler\n", fd));
+ panic("FD selected with no flush handler");
}
- else
- (FDD[fd].InputHandler)(fd);
+ else
+ (FDD[fd].FlushHandler)(fd);
+ }
}
}
return 0;