1 /*
2 * Common support routines for sockets
3 *
4 * James L. Peterson
5 *
6 * Copyright (C) 1987 MCC
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of MCC not be used in
13 * advertising or publicity pertaining to distribution of the software without
14 * specific, written prior permission. MCC makes no
15 * representations about the suitability of this software for any purpose. It
16 * is provided "as is" without express or implied warranty.
17 *
18 * MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 * EVENT SHALL MCC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24 * PERFORMANCE OF THIS SOFTWARE.
25 *
26 */
27 /*
28 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
29 *
30 * Permission is hereby granted, free of charge, to any person obtaining a
31 * copy of this software and associated documentation files (the "Software"),
32 * to deal in the Software without restriction, including without limitation
33 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 * and/or sell copies of the Software, and to permit persons to whom the
35 * Software is furnished to do so, subject to the following conditions:
36 *
37 * The above copyright notice and this permission notice (including the next
38 * paragraph) shall be included in all copies or substantial portions of the
39 * Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47 * DEALINGS IN THE SOFTWARE.
48 *
49 */
50
51 #include "scope.h"
52 #include <fcntl.h>
53 #include <unistd.h>
54
55 /* ********************************************** */
56 /* */
57 /* Debugging support routines */
58 /* */
59 /* ********************************************** */
60
61 void
enterprocedure(const char * s)62 enterprocedure(const char *s)
63 {
64 debug(2, (stderr, "-> %s\n", s));
65 }
66
67 void
warn(const char * s)68 warn(const char *s)
69 {
70 fprintf(stderr, "####### %s\n", s);
71 }
72
73 void
panic(const char * s)74 panic(const char *s)
75 {
76 fprintf(stderr, "%s\n", s);
77 exit(1);
78 }
79
80 /* ************************************************************ */
81 /* */
82 /* Signal Handling support */
83 /* */
84 /* ************************************************************ */
85
86 #define __USE_BSD_SIGNAL
87 #include <signal.h>
88
89 static void
SignalURG(int sig)90 SignalURG(int sig)
91 {
92 debug(1, (stderr, "==> SIGURG received\n"));
93 }
94
95 static void
SignalPIPE(int sig)96 SignalPIPE(int sig)
97 {
98 signal(SIGPIPE, SignalPIPE);
99 debug(1, (stderr, "==> SIGPIPE received\n"));
100 }
101
102 static void
SignalINT(int sig)103 SignalINT(int sig)
104 {
105 signal(SIGINT, SignalINT);
106 debug(1, (stderr, "==> SIGINT received\n"));
107 Interrupt = 1;
108 }
109
110 static void _X_NORETURN
SignalQUIT(int sig)111 SignalQUIT(int sig)
112 {
113 debug(1, (stderr, "==> SIGQUIT received\n"));
114 exit(1);
115 }
116
117 static void _X_NORETURN
SignalTERM(int sig)118 SignalTERM(int sig)
119 {
120 debug(1, (stderr, "==> SIGTERM received\n"));
121 exit(1);
122 }
123
124 static void
SignalTSTP(int sig)125 SignalTSTP(int sig)
126 {
127 debug(1, (stderr, "==> SIGTSTP received\n"));
128 }
129
130 static void
SignalCONT(int sig)131 SignalCONT(int sig)
132 {
133 debug(1, (stderr, "==> SIGCONT received\n"));
134 }
135
136 static void
SignalUSR1(int sig)137 SignalUSR1(int sig)
138 {
139 debug(1, (stderr, "==> SIGUSR1 received\n"));
140 ScopeEnabled = !ScopeEnabled;
141 }
142
143 void
SetSignalHandling(void)144 SetSignalHandling(void)
145 {
146 enterprocedure("SetSignalHandling");
147 (void) signal(SIGURG, SignalURG);
148 (void) signal(SIGPIPE, SignalPIPE);
149 (void) signal(SIGINT, SignalINT);
150 (void) signal(SIGQUIT, SignalQUIT);
151 (void) signal(SIGTERM, SignalTERM);
152 (void) signal(SIGTSTP, SignalTSTP);
153 (void) signal(SIGCONT, SignalCONT);
154 if (HandleSIGUSR1)
155 (void) signal(SIGUSR1, SignalUSR1);
156 }
157
158
159
160 /* ************************************************************ */
161 /* */
162 /* Create a socket for a service to listen for clients */
163 /* */
164 /* ************************************************************ */
165
166 #ifdef USE_XTRANS
167
168 #define TRANS_CLIENT
169 #define TRANS_SERVER
170 #define X11_t
171 #include <X11/Xtrans/Xtrans.h>
172 static XtransConnInfo *ListenTransConns = NULL;
173 static int *ListenTransFds = NULL;
174 static int ListenTransCount;
175
176 #else
177
178 #include <sys/types.h> /* needed by sys/socket.h and netinet/in.h */
179 #include <sys/uio.h> /* for struct iovec, used by socket.h */
180 #include <sys/socket.h> /* for AF_INET, SOCK_STREAM, ... */
181 #include <sys/ioctl.h> /* for FIONCLEX, FIONBIO, ... */
182 #include <sys/fcntl.h> /* for FIONCLEX, FIONBIO, ... */
183 #if !defined(FIOCLEX) && defined(HAVE_SYS_FILIO_H)
184 #include <sys/filio.h>
185 #endif
186
187 #include <netinet/in.h> /* struct sockaddr_in */
188 #include <netdb.h> /* struct servent * and struct hostent * */
189
190 #define BACKLOG 5
191 #endif
192
193 void
SetUpConnectionSocket(int iport,void (* connectionFunc)(int))194 SetUpConnectionSocket(int iport, void (*connectionFunc) (int))
195 {
196 #ifdef USE_XTRANS
197 char port[20];
198 int partial;
199 int i;
200 #else
201 FD ConnectionSocket;
202 struct sockaddr_in sin;
203 short port;
204 int one = 1;
205 int ON = 1; /* used in ioctl */
206 #ifndef SO_DONTLINGER
207 struct linger linger;
208 #endif /* SO_DONTLINGER */
209 #endif
210 char MyHostName[256];
211
212 enterprocedure("SetUpConnectionSocket");
213
214 (void) gethostname(MyHostName, sizeof(MyHostName));
215 ScopeHost = strdup(MyHostName);
216 if (ScopeHost == NULL)
217 panic("Can't allocate memory for hostname");
218
219 #ifdef USE_XTRANS
220 ScopePort = iport - ServerBasePort;
221 snprintf(port, sizeof(port), "%d", ScopePort);
222 if ((_X11TransMakeAllCOTSServerListeners(port, &partial, &ListenTransCount,
223 &ListenTransConns) >= 0) &&
224 (ListenTransCount >= 1)) {
225 if (partial) {
226 debug(4, (stderr,
227 "Warning: Failed to establish listening connections on some transports\n"));
228 }
229 ListenTransFds = malloc(ListenTransCount * sizeof(int));
230 if (ListenTransFds == NULL)
231 panic("Can't allocate memory for ListenTransFds");
232
233 for (i = 0; i < ListenTransCount; i++) {
234 int fd = _X11TransGetConnectionNumber(ListenTransConns[i]);
235
236 ListenTransFds[i] = fd;
237 debug(4, (stderr, "Listening on FD %d\n", fd));
238 UsingFD(fd, NewConnection, NULL, ListenTransConns[i]);
239 }
240 }
241 else {
242 panic("Could not open any listening connections");
243 }
244 #else
245
246 /* create the connection socket and set its parameters of use */
247 ConnectionSocket = socket(AF_INET, SOCK_STREAM, 0);
248 if (ConnectionSocket < 0) {
249 perror("socket");
250 exit(-1);
251 }
252 (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
253 sizeof(int));
254 #ifdef SO_USELOOPBACK
255 (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_USELOOPBACK,
256 (char *) NULL, 0);
257 #endif
258 #ifdef SO_DONTLINGER
259 (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_DONTLINGER,
260 (char *) NULL, 0);
261 #else /* SO_DONTLINGER */
262 linger.l_onoff = 0;
263 linger.l_linger = 0;
264 (void) setsockopt(ConnectionSocket, SOL_SOCKET, SO_LINGER, (char *) &linger,
265 sizeof linger);
266 #endif /* SO_DONTLINGER */
267
268 /* define the name and port to be used with the connection socket */
269 bzero((char *) &sin, sizeof(sin));
270 sin.sin_family = AF_INET;
271
272 /* the address of the socket is composed of two parts: the host machine and
273 the port number. We need the host machine address for the current host
274 */
275 {
276 /* define the host part of the address */
277 struct hostent *hp = gethostbyname(MyHostName);
278
279 if (hp == NULL)
280 panic("No address for our host");
281 memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
282 }
283 /* new code -- INADDR_ANY should be better than using the name of the
284 host machine. The host machine may have several different network
285 addresses. INADDR_ANY should work with all of them at once. */
286 sin.sin_addr.s_addr = INADDR_ANY;
287
288 port = iport;
289 sin.sin_port = htons(port);
290 ScopePort = port;
291
292 /* bind the name and port number to the connection socket */
293 if (bind(ConnectionSocket, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
294 perror("bind");
295 exit(-1);
296 }
297
298 debug(4, (stderr, "Socket is FD %d for %s,%d\n",
299 ConnectionSocket, ScopeHost, ScopePort));
300
301 /* now activate the named connection socket to get messages */
302 if (listen(ConnectionSocket, BACKLOG) < 0) {
303 perror("listen");
304 exit(-1);
305 };
306
307 /* a few more parameter settings */
308 #ifdef FD_CLOEXEC
309 (void) fcntl(ConnectionSocket, F_SETFD, FD_CLOEXEC);
310 #else
311 (void) ioctl(ConnectionSocket, FIOCLEX, 0);
312 #endif
313 /* ultrix reads hang on Unix sockets, hpux reads fail */
314 #if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux))
315 (void) fcntl(ConnectionSocket, F_SETFL, O_NONBLOCK);
316 #else
317 #ifdef FIOSNBIO
318 (void) ioctl(ConnectionSocket, FIOSNBIO, &ON);
319 #else
320 (void) fcntl(ConnectionSocket, F_SETFL, FNDELAY);
321 #endif
322 #endif
323
324 debug(4, (stderr, "Listening on FD %d\n", ConnectionSocket));
325 UsingFD(ConnectionSocket, connectionFunc, NULL, NULL);
326 #endif
327 }
328