/* * Common support routines for sockets * * James L. Peterson * * Copyright (C) 1987 MCC * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of MCC not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. MCC makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL MCC BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * */ /* * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ #include "scope.h" #include #include /* ********************************************** */ /* */ /* Debugging support routines */ /* */ /* ********************************************** */ void enterprocedure(const char *s) { debug(2, (stderr, "-> %s\n", s)); } void warn(const char *s) { fprintf(stderr, "####### %s\n", s); } void panic(const char *s) { fprintf(stderr, "%s\n", s); exit(1); } /* ************************************************************ */ /* */ /* Signal Handling support */ /* */ /* ************************************************************ */ #define __USE_BSD_SIGNAL #include static void SignalURG(int sig) { debug(1, (stderr, "==> SIGURG received\n")); } static void SignalPIPE(int sig) { signal(SIGPIPE, SignalPIPE); debug(1, (stderr, "==> SIGPIPE received\n")); } static void SignalINT(int sig) { signal(SIGINT, SignalINT); debug(1, (stderr, "==> SIGINT received\n")); Interrupt = 1; } static void _X_NORETURN SignalQUIT(int sig) { debug(1, (stderr, "==> SIGQUIT received\n")); exit(1); } static void _X_NORETURN SignalTERM(int sig) { debug(1, (stderr, "==> SIGTERM received\n")); exit(1); } static void SignalTSTP(int sig) { debug(1, (stderr, "==> SIGTSTP received\n")); } static void SignalCONT(int sig) { debug(1, (stderr, "==> SIGCONT received\n")); } static void SignalUSR1(int sig) { debug(1, (stderr, "==> SIGUSR1 received\n")); ScopeEnabled = !ScopeEnabled; } void SetSignalHandling(void) { enterprocedure("SetSignalHandling"); (void) signal(SIGURG, SignalURG); (void) signal(SIGPIPE, SignalPIPE); (void) signal(SIGINT, SignalINT); (void) signal(SIGQUIT, SignalQUIT); (void) signal(SIGTERM, SignalTERM); (void) signal(SIGTSTP, SignalTSTP); (void) signal(SIGCONT, SignalCONT); if (HandleSIGUSR1) (void) signal(SIGUSR1, SignalUSR1); } /* ************************************************************ */ /* */ /* Create a socket for a service to listen for clients */ /* */ /* ************************************************************ */ #ifdef USE_XTRANS #define TRANS_CLIENT #define TRANS_SERVER #define X11_t #include static XtransConnInfo *ListenTransConns = NULL; static int *ListenTransFds = NULL; static int ListenTransCount; #else #include /* needed by sys/socket.h and netinet/in.h */ #include /* for struct iovec, used by socket.h */ #include /* for AF_INET, SOCK_STREAM, ... */ #include /* for FIONCLEX, FIONBIO, ... */ #include /* for FIONCLEX, FIONBIO, ... */ #if !defined(FIOCLEX) && defined(HAVE_SYS_FILIO_H) #include #endif #include /* struct sockaddr_in */ #include /* struct servent * and struct hostent * */ #define BACKLOG 5 #endif void SetUpConnectionSocket(int iport, void (*connectionFunc) (int)) { #ifdef USE_XTRANS char port[20]; int partial; int i; #else FD ConnectionSocket; struct sockaddr_in sin; short port; int one = 1; int ON = 1; /* used in ioctl */ #ifndef SO_DONTLINGER struct linger linger; #endif /* SO_DONTLINGER */ #endif char MyHostName[256]; enterprocedure("SetUpConnectionSocket"); (void) gethostname(MyHostName, sizeof(MyHostName)); ScopeHost = strdup(MyHostName); if (ScopeHost == NULL) panic("Can't allocate memory for hostname"); #ifdef USE_XTRANS ScopePort = iport - ServerBasePort; snprintf(port, sizeof(port), "%d", ScopePort); if ((_X11TransMakeAllCOTSServerListeners(port, &partial, &ListenTransCount, &ListenTransConns) >= 0) && (ListenTransCount >= 1)) { if (partial) { debug(4, (stderr, "Warning: Failed to establish listening connections on some transports\n")); } ListenTransFds = malloc(ListenTransCount * sizeof(int)); if (ListenTransFds == NULL) panic("Can't allocate memory for ListenTransFds"); for (i = 0; i < ListenTransCount; i++) { int fd = _X11TransGetConnectionNumber(ListenTransConns[i]); ListenTransFds[i] = fd; debug(4, (stderr, "Listening on FD %d\n", fd)); UsingFD(fd, NewConnection, NULL, ListenTransConns[i]); } } else { panic("Could not open any listening connections"); } #else /* create the connection socket and set its parameters of use */ ConnectionSocket = socket(AF_INET, SOCK_STREAM, 0); if (ConnectionSocket < 0) { perror("socket"); exit(-1); } (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)); #ifdef SO_USELOOPBACK (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_USELOOPBACK, (char *) NULL, 0); #endif #ifdef SO_DONTLINGER (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0); #else /* SO_DONTLINGER */ linger.l_onoff = 0; linger.l_linger = 0; (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof linger); #endif /* SO_DONTLINGER */ /* define the name and port to be used with the connection socket */ bzero((char *) &sin, sizeof(sin)); sin.sin_family = AF_INET; /* the address of the socket is composed of two parts: the host machine and the port number. We need the host machine address for the current host */ { /* define the host part of the address */ struct hostent *hp = gethostbyname(MyHostName); if (hp == NULL) panic("No address for our host"); memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); } /* new code -- INADDR_ANY should be better than using the name of the host machine. The host machine may have several different network addresses. INADDR_ANY should work with all of them at once. */ sin.sin_addr.s_addr = INADDR_ANY; port = iport; sin.sin_port = htons(port); ScopePort = port; /* bind the name and port number to the connection socket */ if (bind(ConnectionSocket, (struct sockaddr *) &sin, sizeof(sin)) < 0) { perror("bind"); exit(-1); } debug(4, (stderr, "Socket is FD %d for %s,%d\n", ConnectionSocket, ScopeHost, ScopePort)); /* now activate the named connection socket to get messages */ if (listen(ConnectionSocket, BACKLOG) < 0) { perror("listen"); exit(-1); }; /* a few more parameter settings */ #ifdef FD_CLOEXEC (void) fcntl(ConnectionSocket, F_SETFD, FD_CLOEXEC); #else (void) ioctl(ConnectionSocket, FIOCLEX, 0); #endif /* ultrix reads hang on Unix sockets, hpux reads fail */ #if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux)) (void) fcntl(ConnectionSocket, F_SETFL, O_NONBLOCK); #else #ifdef FIOSNBIO (void) ioctl(ConnectionSocket, FIOSNBIO, &ON); #else (void) fcntl(ConnectionSocket, F_SETFL, FNDELAY); #endif #endif debug(4, (stderr, "Listening on FD %d\n", ConnectionSocket)); UsingFD(ConnectionSocket, connectionFunc, NULL, NULL); #endif }