/* ************************************************************ *\ * * * 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 2002 Sun Microsystems, Inc. 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, and/or sell copies of the Software, and to permit persons * to whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * 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 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. * * Except as contained in this notice, the name of a copyright holder * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * of the copyright holder. * * \* *********************************************************** */ #include "scope.h" #include #ifdef SYSV #define bzero(s,l) memset(s, 0, l) #define bcopy(s,d,l) memmove(d,s,l) #endif #include /* ********************************************** */ /* */ /* Debugging support routines */ /* */ /* ********************************************** */ void enterprocedure (char *s) { debug(2,(stderr, "-> %s\n", s)); } void warn (char *s) { fprintf(stderr, "####### %s\n", s); } void panic (char *s) { fprintf(stderr, "%s\n", s); exit(1); } /* ********************************************** */ /* */ /* Debugging forms of memory management */ /* */ /* ********************************************** */ void * Malloc (long n) { void *p; p = malloc(n); debug(64,(stderr, "%x = malloc(%d)\n", p, n)); if (p == NULL) panic("no more malloc space"); return(p); } void Free(void *p) { debug(64,(stderr, "%x = free\n", p)); free(p); } /* ************************************************************ */ /* */ /* 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 SignalQUIT(int sig) { debug(1,(stderr, "==> SIGQUIT received\n")); exit(1); } static void 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, "==> SIGCONT 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, ... */ #ifdef SVR4 #include #endif #include /* struct sockaddr_in */ #include /* struct servent * and struct hostent * */ static int ON = 1 /* used in ioctl */ ; #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; #ifndef SO_DONTLINGER struct linger linger; #endif /* SO_DONTLINGER */ #endif enterprocedure("SetUpConnectionSocket"); #ifdef USE_XTRANS ScopePort = iport - ServerBasePort; sprintf (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 = (int *) malloc (ListenTransCount * sizeof (int)); 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 */ char MyHostName[256]; struct hostent *hp; (void) gethostname(MyHostName, sizeof(MyHostName)); ScopeHost = (char *) Malloc((long)(1+strlen(MyHostName))); strcpy(ScopeHost, MyHostName); hp = gethostbyname(MyHostName); if (hp == NULL) panic("No address for our host"); bcopy((char *)hp->h_addr, (char*)&sin.sin_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 }