diff options
author | Alan Coopersmith <alan.coopersmith@sun.com> | 2009-05-06 17:10:31 -0700 |
---|---|---|
committer | Alan Coopersmith <alan.coopersmith@sun.com> | 2009-05-06 17:10:31 -0700 |
commit | 0aab8135dae526b090dcb1ffab801023ac4084aa (patch) | |
tree | 3aa615a5196bddc76ff23a5e4b3ae6ab04a40588 /fd.c | |
parent | eb05316a471da962eefe82c9b9a16a7590653ba7 (diff) | |
parent | def948f052a758850cadc022943517742b299441 (diff) | |
download | xscope-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.c | 275 |
1 files changed, 249 insertions, 26 deletions
@@ -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; |