1bbe1b32bSmrg/*
2bbe1b32bSmrg * handles connections
3bbe1b32bSmrg */
4bbe1b32bSmrg/*
5bbe1b32bSmrg
6bbe1b32bSmrgCopyright 1990, 1991, 1998  The Open Group
7bbe1b32bSmrg
8bbe1b32bSmrgPermission to use, copy, modify, distribute, and sell this software and its
9bbe1b32bSmrgdocumentation for any purpose is hereby granted without fee, provided that
10bbe1b32bSmrgthe above copyright notice appear in all copies and that both that
11bbe1b32bSmrgcopyright notice and this permission notice appear in supporting
12bbe1b32bSmrgdocumentation.
13bbe1b32bSmrg
14bbe1b32bSmrgThe above copyright notice and this permission notice shall be included in
15bbe1b32bSmrgall copies or substantial portions of the Software.
16bbe1b32bSmrg
17bbe1b32bSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18bbe1b32bSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19bbe1b32bSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20bbe1b32bSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21bbe1b32bSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22bbe1b32bSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23bbe1b32bSmrg
24bbe1b32bSmrgExcept as contained in this notice, the name of The Open Group shall not be
25bbe1b32bSmrgused in advertising or otherwise to promote the sale, use or other dealings
26bbe1b32bSmrgin this Software without prior written authorization from The Open Group.
27bbe1b32bSmrg
28bbe1b32bSmrg * Copyright 1990, 1991 Network Computing Devices;
29bbe1b32bSmrg * Portions Copyright 1987 by Digital Equipment Corporation
30bbe1b32bSmrg *
31bbe1b32bSmrg * Permission to use, copy, modify, distribute, and sell this software and
32bbe1b32bSmrg * its documentation for any purpose is hereby granted without fee, provided
33bbe1b32bSmrg * that the above copyright notice appear in all copies and that both that
34bbe1b32bSmrg * copyright notice and this permission notice appear in supporting
35bbe1b32bSmrg * documentation, and that the names of Network Computing Devices, or Digital
36bbe1b32bSmrg * not be used in advertising or publicity pertaining to distribution
37bbe1b32bSmrg * of the software without specific, written prior permission.
38bbe1b32bSmrg *
39bbe1b32bSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
40bbe1b32bSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
41bbe1b32bSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
42bbe1b32bSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
43bbe1b32bSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44bbe1b32bSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
45bbe1b32bSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46bbe1b32bSmrg * THIS SOFTWARE.
47bbe1b32bSmrg */
48bbe1b32bSmrg/*
49bbe1b32bSmrg * Copyright 1990, 1991 Network Computing Devices;
50bbe1b32bSmrg * Portions Copyright 1987 by Digital Equipment Corporation
51bbe1b32bSmrg *
52bbe1b32bSmrg * Permission to use, copy, modify, distribute, and sell this software and
53bbe1b32bSmrg * its documentation for any purpose is hereby granted without fee, provided
54bbe1b32bSmrg * that the above copyright notice appear in all copies and that both that
55bbe1b32bSmrg * copyright notice and this permission notice appear in supporting
56bbe1b32bSmrg * documentation, and that the names of Network Computing Devices, or Digital
57bbe1b32bSmrg * not be used in advertising or publicity pertaining to distribution
58bbe1b32bSmrg * of the software without specific, written prior permission.
59bbe1b32bSmrg *
60bbe1b32bSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
61bbe1b32bSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
62bbe1b32bSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
63bbe1b32bSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
64bbe1b32bSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
65bbe1b32bSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
66bbe1b32bSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
67bbe1b32bSmrg * THIS SOFTWARE.
68bbe1b32bSmrg */
69ce6676dbSmrg
7034f90d55Smrg#include	"config.h"
71bbe1b32bSmrg
7230e1ba2cSmrg/* include Xpoll.h early for possible FD_SETSIZE re-definition */
735bd42952Smrg#include	"X11/Xpoll.h"
74bbe1b32bSmrg#include	<stdlib.h>
75bbe1b32bSmrg#include	<X11/Xtrans/Xtrans.h>
76bbe1b32bSmrg#include	<stdlib.h>
77bbe1b32bSmrg#include	"misc.h"
78bbe1b32bSmrg#include	<stdio.h>
79bbe1b32bSmrg#include	<errno.h>
80bbe1b32bSmrg#include	<X11/Xos.h>
81bbe1b32bSmrg#include	<sys/param.h>
82bbe1b32bSmrg#include	<sys/socket.h>
83bbe1b32bSmrg#include	<sys/uio.h>
84bbe1b32bSmrg#include	<signal.h>
85bbe1b32bSmrg
86bbe1b32bSmrg#include	<X11/fonts/FS.h>
87bbe1b32bSmrg#include	<X11/fonts/FSproto.h>
88bbe1b32bSmrg#include	"clientstr.h"
89bbe1b32bSmrg#include	"osdep.h"
90bbe1b32bSmrg#include	"globals.h"
91bbe1b32bSmrg#include	"osstruct.h"
92bbe1b32bSmrg#include	"servermd.h"
93bbe1b32bSmrg#include	"dispatch.h"
94bbe1b32bSmrg#include	"fsevents.h"
95bbe1b32bSmrg
96bbe1b32bSmrg
97bbe1b32bSmrg
98bbe1b32bSmrgint         ListenPort = DEFAULT_FS_PORT;   /* port to listen on */
99bbe1b32bSmrgint         lastfdesc;
100bbe1b32bSmrg
101bbe1b32bSmrgfd_set      WellKnownConnections;
102bbe1b32bSmrgfd_set      AllSockets;
103bbe1b32bSmrgfd_set      AllClients;
104bbe1b32bSmrgfd_set      LastSelectMask;
105bbe1b32bSmrgfd_set      ClientsWithInput;
106bbe1b32bSmrgfd_set      ClientsWriteBlocked;
107bbe1b32bSmrgfd_set      OutputPending;
108bbe1b32bSmrglong        OutputBufferSize = BUFSIZE;
109bbe1b32bSmrg
110bbe1b32bSmrgBool        NewOutputPending;
111bbe1b32bSmrgBool        AnyClientsWriteBlocked;
112bbe1b32bSmrg
113bbe1b32bSmrgint         ConnectionTranslation[MAXSOCKS];
114bbe1b32bSmrg
115bbe1b32bSmrgXtransConnInfo 	*ListenTransConns = NULL;
116bbe1b32bSmrgint	       	*ListenTransFds = NULL;
117bbe1b32bSmrgint		ListenTransCount;
118bbe1b32bSmrg
119bbe1b32bSmrg
12030f8ce46Smrgextern int  xfd_ffs (fd_mask);
121bbe1b32bSmrgstatic void error_conn_max(XtransConnInfo trans_conn);
122bbe1b32bSmrgstatic void close_fd(OsCommPtr oc);
123bbe1b32bSmrg
124bbe1b32bSmrg
125bbe1b32bSmrgstatic XtransConnInfo
126bbe1b32bSmrglookup_trans_conn (int fd)
127bbe1b32bSmrg{
128bbe1b32bSmrg    if (ListenTransFds)
129bbe1b32bSmrg    {
130bbe1b32bSmrg	int i;
131bbe1b32bSmrg	for (i = 0; i < ListenTransCount; i++)
132bbe1b32bSmrg	    if (ListenTransFds[i] == fd)
133bbe1b32bSmrg		return ListenTransConns[i];
134bbe1b32bSmrg    }
135bbe1b32bSmrg
136bbe1b32bSmrg    return (NULL);
137bbe1b32bSmrg}
138bbe1b32bSmrg
139bbe1b32bSmrgvoid
140bbe1b32bSmrgStopListening(void)
141bbe1b32bSmrg{
142bbe1b32bSmrg    int i;
143bbe1b32bSmrg
144bbe1b32bSmrg    for (i = 0; i < ListenTransCount; i++)
145bbe1b32bSmrg    {
146bbe1b32bSmrg	FD_CLR (ListenTransFds[i], &AllSockets);
147bbe1b32bSmrg	_FontTransCloseForCloning (ListenTransConns[i]);
148bbe1b32bSmrg    }
149bbe1b32bSmrg
150bbe1b32bSmrg    free ((char *) ListenTransFds);
151bbe1b32bSmrg    free ((char *) ListenTransConns);
152bbe1b32bSmrg
153bbe1b32bSmrg    ListenTransFds = NULL;
154bbe1b32bSmrg    ListenTransConns = NULL;
155ce6676dbSmrg    ListenTransCount = 0;
156bbe1b32bSmrg}
157bbe1b32bSmrg
158bbe1b32bSmrg/*
159bbe1b32bSmrg * creates the sockets for listening to clients
160bbe1b32bSmrg *
161bbe1b32bSmrg * only called when server first started
162bbe1b32bSmrg */
163bbe1b32bSmrgvoid
164bbe1b32bSmrgCreateSockets(int old_listen_count, OldListenRec *old_listen)
165bbe1b32bSmrg{
166bbe1b32bSmrg    int	i;
167ce6676dbSmrg    struct sigaction act;
168bbe1b32bSmrg
169bbe1b32bSmrg    FD_ZERO(&AllSockets);
170bbe1b32bSmrg    FD_ZERO(&AllClients);
171bbe1b32bSmrg    FD_ZERO(&LastSelectMask);
172bbe1b32bSmrg    FD_ZERO(&ClientsWithInput);
173bbe1b32bSmrg    FD_ZERO(&WellKnownConnections);
174bbe1b32bSmrg
175bbe1b32bSmrg    for (i = 0; i < MAXSOCKS; i++)
176bbe1b32bSmrg	ConnectionTranslation[i] = 0;
177bbe1b32bSmrg
178bbe1b32bSmrg    lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
179bbe1b32bSmrg
180ce6676dbSmrg    if ((lastfdesc < 0) || (lastfdesc > MAXSOCKS)) {
181bbe1b32bSmrg	lastfdesc = MAXSOCKS;
182bbe1b32bSmrg    }
183bbe1b32bSmrg
184bbe1b32bSmrg    if (old_listen_count > 0) {
185bbe1b32bSmrg
186bbe1b32bSmrg	/*
187bbe1b32bSmrg	 * The font server cloned itself.  Re-use previously opened
188bbe1b32bSmrg	 * transports for listening.
189bbe1b32bSmrg	 */
190bbe1b32bSmrg
191bbe1b32bSmrg	ListenTransConns = (XtransConnInfo *) malloc (
192bbe1b32bSmrg	    old_listen_count * sizeof (XtransConnInfo));
193bbe1b32bSmrg
194bbe1b32bSmrg	ListenTransFds = (int *) malloc (old_listen_count * sizeof (int));
195bbe1b32bSmrg
196bbe1b32bSmrg	ListenTransCount = 0;
197bbe1b32bSmrg
198bbe1b32bSmrg	for (i = 0; i < old_listen_count; i++)
199bbe1b32bSmrg	{
200bbe1b32bSmrg	    char portnum[10];
201bbe1b32bSmrg
202bbe1b32bSmrg	    if (old_listen[i].portnum != ListenPort)
203bbe1b32bSmrg		continue;		/* this should never happen */
204bbe1b32bSmrg	    else
2058f34cbf9Ssnj		snprintf (portnum, sizeof(portnum), "%d", old_listen[i].portnum);
206bbe1b32bSmrg
207bbe1b32bSmrg	    if ((ListenTransConns[ListenTransCount] =
208bbe1b32bSmrg		_FontTransReopenCOTSServer (old_listen[i].trans_id,
209bbe1b32bSmrg		old_listen[i].fd, portnum)) != NULL)
210bbe1b32bSmrg	    {
211bbe1b32bSmrg		ListenTransFds[ListenTransCount] = old_listen[i].fd;
212bbe1b32bSmrg		FD_SET (old_listen[i].fd, &WellKnownConnections);
213bbe1b32bSmrg
214bbe1b32bSmrg		NoticeF("reusing existing file descriptor %d\n",
215bbe1b32bSmrg		    old_listen[i].fd);
216bbe1b32bSmrg
217bbe1b32bSmrg		ListenTransCount++;
218bbe1b32bSmrg	    }
219bbe1b32bSmrg	}
220bbe1b32bSmrg    } else {
221bbe1b32bSmrg	char port[20];
222bbe1b32bSmrg	int partial;
223bbe1b32bSmrg
2248f34cbf9Ssnj	snprintf (port, sizeof(port), "%d", ListenPort);
225bbe1b32bSmrg
226bbe1b32bSmrg	if ((_FontTransMakeAllCOTSServerListeners (port, &partial,
227bbe1b32bSmrg	    &ListenTransCount, &ListenTransConns) >= 0) &&
228bbe1b32bSmrg	    (ListenTransCount >= 1))
229bbe1b32bSmrg	{
230bbe1b32bSmrg	    ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int));
231bbe1b32bSmrg
232bbe1b32bSmrg	    for (i = 0; i < ListenTransCount; i++)
233bbe1b32bSmrg	    {
234bbe1b32bSmrg		int fd = _FontTransGetConnectionNumber (ListenTransConns[i]);
235bbe1b32bSmrg
236bbe1b32bSmrg		ListenTransFds[i] = fd;
237bbe1b32bSmrg		FD_SET (fd, &WellKnownConnections);
238bbe1b32bSmrg	    }
239bbe1b32bSmrg	}
240bbe1b32bSmrg    }
241bbe1b32bSmrg
242bbe1b32bSmrg    if (! XFD_ANYSET(&WellKnownConnections))
243bbe1b32bSmrg	FatalError("cannot establish any listening sockets\n");
244bbe1b32bSmrg
245bbe1b32bSmrg    /* set up all the signal handlers */
246ce6676dbSmrg    sigemptyset(&act.sa_mask);
247ce6676dbSmrg    act.sa_flags = SA_RESTART;
248ce6676dbSmrg#define HANDLE_SIGNAL(s, h)	act.sa_handler = h; sigaction(s, &act, NULL)
249ce6676dbSmrg
250ce6676dbSmrg    HANDLE_SIGNAL(SIGPIPE, SIG_IGN);
251ce6676dbSmrg    HANDLE_SIGNAL(SIGHUP, AutoResetServer);
252ce6676dbSmrg    HANDLE_SIGNAL(SIGINT, GiveUp);
253ce6676dbSmrg    HANDLE_SIGNAL(SIGTERM, GiveUp);
254ce6676dbSmrg    HANDLE_SIGNAL(SIGUSR1, ServerReconfig);
255ce6676dbSmrg    HANDLE_SIGNAL(SIGUSR2, ServerCacheFlush);
256ce6676dbSmrg    HANDLE_SIGNAL(SIGCHLD, CleanupChild);
257bbe1b32bSmrg
258bbe1b32bSmrg    XFD_COPYSET (&WellKnownConnections, &AllSockets);
259bbe1b32bSmrg}
260bbe1b32bSmrg
261bbe1b32bSmrg/*
262bbe1b32bSmrg * called when server cycles
263bbe1b32bSmrg */
264bbe1b32bSmrgvoid
265bbe1b32bSmrgResetSockets(void)
266bbe1b32bSmrg{
267bbe1b32bSmrg}
268bbe1b32bSmrg
269bbe1b32bSmrgvoid
270bbe1b32bSmrgCloseSockets(void)
271bbe1b32bSmrg{
272bbe1b32bSmrg    int i;
273bbe1b32bSmrg
274bbe1b32bSmrg    for (i = 0; i < ListenTransCount; i++)
275bbe1b32bSmrg	_FontTransClose (ListenTransConns[i]);
276bbe1b32bSmrg}
277bbe1b32bSmrg
278bbe1b32bSmrg/*
279bbe1b32bSmrg * accepts new connections
280bbe1b32bSmrg */
281bbe1b32bSmrgvoid
282bbe1b32bSmrgMakeNewConnections(void)
283bbe1b32bSmrg{
284bbe1b32bSmrg    fd_mask     readyconnections;
285bbe1b32bSmrg    int         curconn;
286bbe1b32bSmrg    int         newconn;
287bbe1b32bSmrg    long        connect_time;
288bbe1b32bSmrg    int         i;
289bbe1b32bSmrg    ClientPtr   client;
290bbe1b32bSmrg    OsCommPtr   oc;
291bbe1b32bSmrg    fd_set	tmask;
292bbe1b32bSmrg
293bbe1b32bSmrg    XFD_ANDSET (&tmask, &LastSelectMask, &WellKnownConnections);
294bbe1b32bSmrg    readyconnections = tmask.fds_bits[0];
295bbe1b32bSmrg    if (!readyconnections)
296bbe1b32bSmrg	return;
297bbe1b32bSmrg    connect_time = GetTimeInMillis();
298bbe1b32bSmrg
299bbe1b32bSmrg    /* kill off stragglers */
300bbe1b32bSmrg    for (i = MINCLIENT; i < currentMaxClients; i++) {
301bbe1b32bSmrg	if ((client = clients[i]) != NullClient) {
302bbe1b32bSmrg	    oc = (OsCommPtr) client->osPrivate;
303bbe1b32bSmrg	    if ((oc && (oc->conn_time != 0) &&
304bbe1b32bSmrg		    (connect_time - oc->conn_time) >= TimeOutValue) ||
305bbe1b32bSmrg		     ((client->noClientException != FSSuccess) &&
306bbe1b32bSmrg		      (client->clientGone != CLIENT_GONE)))
307bbe1b32bSmrg		CloseDownClient(client);
308bbe1b32bSmrg	}
309bbe1b32bSmrg    }
310bbe1b32bSmrg
311bbe1b32bSmrg    while (readyconnections) {
312bbe1b32bSmrg	XtransConnInfo trans_conn, new_trans_conn;
313bbe1b32bSmrg	int status;
314bbe1b32bSmrg
31530f8ce46Smrg	curconn = xfd_ffs(readyconnections) - 1;
316bbe1b32bSmrg	readyconnections &= ~(1 << curconn);
317bbe1b32bSmrg
318bbe1b32bSmrg	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
319bbe1b32bSmrg	    continue;
320bbe1b32bSmrg
321bbe1b32bSmrg	if ((new_trans_conn = _FontTransAccept (trans_conn, &status)) == NULL)
322bbe1b32bSmrg	    continue;
323bbe1b32bSmrg
324bbe1b32bSmrg	newconn = _FontTransGetConnectionNumber (new_trans_conn);
325bbe1b32bSmrg
326bbe1b32bSmrg	_FontTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
327bbe1b32bSmrg
32894f982dbSmrg	oc = (OsCommPtr) FSalloc(sizeof(OsCommRec));
329bbe1b32bSmrg	if (!oc) {
33094f982dbSmrg	    FSfree(oc);
331bbe1b32bSmrg	    error_conn_max(new_trans_conn);
332bbe1b32bSmrg	    _FontTransClose(new_trans_conn);
333bbe1b32bSmrg	    continue;
334bbe1b32bSmrg	}
335bbe1b32bSmrg	FD_SET(newconn, &AllClients);
336bbe1b32bSmrg	FD_SET(newconn, &AllSockets);
337bbe1b32bSmrg	oc->fd = newconn;
338bbe1b32bSmrg	oc->trans_conn = new_trans_conn;
339bbe1b32bSmrg	oc->input = (ConnectionInputPtr) NULL;
340bbe1b32bSmrg	oc->output = (ConnectionOutputPtr) NULL;
341bbe1b32bSmrg	oc->conn_time = connect_time;
342bbe1b32bSmrg
343bbe1b32bSmrg	if ((newconn < lastfdesc) &&
344bbe1b32bSmrg		(client = NextAvailableClient((pointer) oc))) {
345bbe1b32bSmrg	    ConnectionTranslation[newconn] = client->index;
346bbe1b32bSmrg	} else {
347bbe1b32bSmrg	    error_conn_max(new_trans_conn);
348bbe1b32bSmrg	    close_fd(oc);
349bbe1b32bSmrg	}
350bbe1b32bSmrg    }
351bbe1b32bSmrg}
352bbe1b32bSmrg
353bbe1b32bSmrg#define	NOROOM	"maximum number of clients reached"
354bbe1b32bSmrg
355bbe1b32bSmrgstatic void
356bbe1b32bSmrgerror_conn_max(XtransConnInfo trans_conn)
357bbe1b32bSmrg{
358bbe1b32bSmrg    int fd = _FontTransGetConnectionNumber (trans_conn);
359bbe1b32bSmrg    fsConnSetup conn;
360bbe1b32bSmrg    char        pad[3];
361bbe1b32bSmrg    char        byteOrder = 0;
362bbe1b32bSmrg    int         whichbyte = 1;
363bbe1b32bSmrg    struct timeval waittime;
364bbe1b32bSmrg    fd_set      mask;
365bbe1b32bSmrg
366bbe1b32bSmrg
367bbe1b32bSmrg    waittime.tv_usec = BOTIMEOUT / MILLI_PER_SECOND;
368bbe1b32bSmrg    waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
369bbe1b32bSmrg	(1000000 / MILLI_PER_SECOND);
370bbe1b32bSmrg    FD_ZERO(&mask);
371bbe1b32bSmrg    FD_SET(fd, &mask);
372bbe1b32bSmrg    (void) Select(fd + 1, &mask, NULL, NULL, &waittime);
373bbe1b32bSmrg    /* try to read the byteorder of the connection */
374bbe1b32bSmrg    (void) _FontTransRead(trans_conn, &byteOrder, 1);
375bbe1b32bSmrg    if ((byteOrder == 'l') || (byteOrder == 'B')) {
376bbe1b32bSmrg	int         num_alts;
377bbe1b32bSmrg	AlternateServerPtr altservers,
378bbe1b32bSmrg	            as;
379bbe1b32bSmrg	int         i,
380bbe1b32bSmrg	            altlen = 0;
381bbe1b32bSmrg
382bbe1b32bSmrg	num_alts = ListAlternateServers(&altservers);
383bbe1b32bSmrg	conn.status = AuthDenied;
384bbe1b32bSmrg	conn.major_version = FS_PROTOCOL;
385bbe1b32bSmrg	conn.minor_version = FS_PROTOCOL_MINOR;
386bbe1b32bSmrg	conn.num_alternates = num_alts;
387bbe1b32bSmrg	for (i = 0, as = altservers; i < num_alts; i++, as++) {
388bbe1b32bSmrg	    altlen += (2 + as->namelen + 3) >> 2;
389bbe1b32bSmrg	}
390bbe1b32bSmrg	conn.alternate_len = altlen;
391bbe1b32bSmrg	/* blow off the auth info */
392bbe1b32bSmrg	conn.auth_index = 0;
393bbe1b32bSmrg	conn.auth_len = 0;
394bbe1b32bSmrg
395bbe1b32bSmrg	if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
396bbe1b32bSmrg		(!(*(char *) &whichbyte) && (byteOrder == 'l'))) {
397bbe1b32bSmrg	    conn.status = lswaps(conn.status);
398bbe1b32bSmrg	    conn.major_version = lswaps(conn.major_version);
399bbe1b32bSmrg	    conn.minor_version = lswaps(conn.minor_version);
400bbe1b32bSmrg	    conn.alternate_len = lswaps(conn.alternate_len);
401bbe1b32bSmrg	}
402bbe1b32bSmrg	(void) _FontTransWrite(trans_conn,
403bbe1b32bSmrg	    (char *) &conn, SIZEOF(fsConnSetup));
404bbe1b32bSmrg	/* dump alternates */
405bbe1b32bSmrg	for (i = 0, as = altservers; i < num_alts; i++, as++) {
406bbe1b32bSmrg	    (void) _FontTransWrite(trans_conn,
407bbe1b32bSmrg		(char *) as, 2);  /* XXX */
408bbe1b32bSmrg	    (void) _FontTransWrite(trans_conn,
409bbe1b32bSmrg		(char *) as->name, as->namelen);
410bbe1b32bSmrg	    altlen = 2 + as->namelen;
411bbe1b32bSmrg	    /* pad it */
412bbe1b32bSmrg	    if (altlen & 3)
413bbe1b32bSmrg		(void) _FontTransWrite(trans_conn,
414bbe1b32bSmrg		(char *) pad, ((4 - (altlen & 3)) & 3));
415bbe1b32bSmrg	}
416bbe1b32bSmrg    }
417bbe1b32bSmrg}
418bbe1b32bSmrg
419bbe1b32bSmrgstatic void
420bbe1b32bSmrgclose_fd(OsCommPtr oc)
421bbe1b32bSmrg{
422bbe1b32bSmrg    int         fd = oc->fd;
423bbe1b32bSmrg
424bbe1b32bSmrg    if (oc->trans_conn)
425bbe1b32bSmrg	_FontTransClose(oc->trans_conn);
426bbe1b32bSmrg    FreeOsBuffers(oc);
427bbe1b32bSmrg    FD_CLR(fd, &AllSockets);
428bbe1b32bSmrg    FD_CLR(fd, &AllClients);
429bbe1b32bSmrg    FD_CLR(fd, &ClientsWithInput);
430bbe1b32bSmrg    FD_CLR(fd, &ClientsWriteBlocked);
431bbe1b32bSmrg    if (!XFD_ANYSET(&ClientsWriteBlocked))
432bbe1b32bSmrg	AnyClientsWriteBlocked = FALSE;
433bbe1b32bSmrg    FD_CLR(fd, &OutputPending);
43494f982dbSmrg    FSfree(oc);
435bbe1b32bSmrg}
436bbe1b32bSmrg
437bbe1b32bSmrgvoid
438bbe1b32bSmrgCheckConnections(void)
439bbe1b32bSmrg{
440bbe1b32bSmrg    fd_set      mask;
441bbe1b32bSmrg    fd_set      tmask;
442bbe1b32bSmrg    int         curclient;
443bbe1b32bSmrg    int         i;
444bbe1b32bSmrg    struct timeval notime;
445bbe1b32bSmrg    int         r;
446bbe1b32bSmrg
447bbe1b32bSmrg    notime.tv_sec = 0;
448bbe1b32bSmrg    notime.tv_usec = 0;
449bbe1b32bSmrg
450bbe1b32bSmrg    XFD_COPYSET(&AllClients, &mask);
451bbe1b32bSmrg    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) {
452bbe1b32bSmrg	while (mask.fds_bits[i]) {
45330f8ce46Smrg	    curclient = xfd_ffs(mask.fds_bits[i]) - 1 + (i * (sizeof(fd_mask) * 8));
454bbe1b32bSmrg	    FD_ZERO(&tmask);
455bbe1b32bSmrg	    FD_SET(curclient, &tmask);
456bbe1b32bSmrg	    r = Select(curclient + 1, &tmask, NULL, NULL, &notime);
457bbe1b32bSmrg	    if (r < 0)
458bbe1b32bSmrg		CloseDownClient(clients[ConnectionTranslation[curclient]]);
459bbe1b32bSmrg	    FD_CLR(curclient, &mask);
460bbe1b32bSmrg	}
461bbe1b32bSmrg    }
462bbe1b32bSmrg}
463bbe1b32bSmrg
464bbe1b32bSmrgvoid
465bbe1b32bSmrgCloseDownConnection(ClientPtr client)
466bbe1b32bSmrg{
467bbe1b32bSmrg    OsCommPtr   oc = (OsCommPtr) client->osPrivate;
468bbe1b32bSmrg
469ce6676dbSmrg    if (oc == NULL)
470ce6676dbSmrg	return;
471ce6676dbSmrg
472bbe1b32bSmrg    if (oc->output && oc->output->count)
473bbe1b32bSmrg	FlushClient(client, oc, (char *) NULL, 0, 0);
474bbe1b32bSmrg    ConnectionTranslation[oc->fd] = 0;
475bbe1b32bSmrg    close_fd(oc);
476bbe1b32bSmrg    client->osPrivate = (pointer) NULL;
477bbe1b32bSmrg}
478bbe1b32bSmrg
479bbe1b32bSmrg
480bbe1b32bSmrg/****************
481bbe1b32bSmrg * IgnoreClient
482bbe1b32bSmrg *    Removes one client from input masks.
4838ae5c7d9Smrg *    Must have corresponding call to AttendClient.
484bbe1b32bSmrg ****************/
485bbe1b32bSmrg
486bbe1b32bSmrgstatic fd_set IgnoredClientsWithInput;
487bbe1b32bSmrg
488bbe1b32bSmrgvoid
489bbe1b32bSmrgIgnoreClient(ClientPtr client)
490bbe1b32bSmrg{
491bbe1b32bSmrg    OsCommPtr   oc = (OsCommPtr) client->osPrivate;
492bbe1b32bSmrg    int         connection = oc->fd;
493bbe1b32bSmrg
494bbe1b32bSmrg    if (FD_ISSET(connection, &ClientsWithInput))
495bbe1b32bSmrg	FD_SET(connection, &IgnoredClientsWithInput);
496bbe1b32bSmrg    else
497bbe1b32bSmrg	FD_CLR(connection, &IgnoredClientsWithInput);
498bbe1b32bSmrg    FD_CLR(connection, &ClientsWithInput);
499bbe1b32bSmrg    FD_CLR(connection, &AllSockets);
500bbe1b32bSmrg    FD_CLR(connection, &AllClients);
501bbe1b32bSmrg    FD_CLR(connection, &LastSelectMask);
502bbe1b32bSmrg    isItTimeToYield = TRUE;
503bbe1b32bSmrg}
504bbe1b32bSmrg
505bbe1b32bSmrg/****************
506bbe1b32bSmrg * AttendClient
507bbe1b32bSmrg *    Adds one client back into the input masks.
508bbe1b32bSmrg ****************/
509bbe1b32bSmrg
510bbe1b32bSmrgvoid
511bbe1b32bSmrgAttendClient(ClientPtr client)
512bbe1b32bSmrg{
513bbe1b32bSmrg    OsCommPtr   oc = (OsCommPtr) client->osPrivate;
514bbe1b32bSmrg    int         connection = oc->fd;
515bbe1b32bSmrg
516bbe1b32bSmrg    FD_SET(connection, &AllClients);
517bbe1b32bSmrg    FD_SET(connection, &AllSockets);
518bbe1b32bSmrg    FD_SET(connection, &LastSelectMask);
519bbe1b32bSmrg    if (FD_ISSET(connection, &IgnoredClientsWithInput))
520bbe1b32bSmrg	FD_SET(connection, &ClientsWithInput);
521bbe1b32bSmrg}
522bbe1b32bSmrg
523bbe1b32bSmrg/*
524bbe1b32bSmrg * figure out which clients need to be toasted
525bbe1b32bSmrg */
526bbe1b32bSmrgvoid
527bbe1b32bSmrgReapAnyOldClients(void)
528bbe1b32bSmrg{
529bbe1b32bSmrg    int         i;
530bbe1b32bSmrg    long        cur_time = GetTimeInMillis();
531bbe1b32bSmrg    ClientPtr   client;
532bbe1b32bSmrg
533bbe1b32bSmrg#ifdef DEBUG
534bbe1b32bSmrg    fprintf(stderr, "looking for clients to reap\n");
535bbe1b32bSmrg#endif
536bbe1b32bSmrg
537bbe1b32bSmrg    for (i = MINCLIENT; i < currentMaxClients; i++) {
538bbe1b32bSmrg	client = clients[i];
539bbe1b32bSmrg	if (client) {
540bbe1b32bSmrg	    if ((cur_time - client->last_request_time) >= ReapClientTime) {
541bbe1b32bSmrg		if (client->clientGone == CLIENT_AGED) {
542bbe1b32bSmrg		    client->clientGone = CLIENT_TIMED_OUT;
543bbe1b32bSmrg
544bbe1b32bSmrg#ifdef DEBUG
545bbe1b32bSmrg		    fprintf(stderr, "reaping client #%d\n", i);
546bbe1b32bSmrg#endif
547bbe1b32bSmrg
548bbe1b32bSmrg		    CloseDownClient(client);
549bbe1b32bSmrg		} else {
550bbe1b32bSmrg		    client->clientGone = CLIENT_AGED;
551bbe1b32bSmrg		    SendKeepAliveEvent(client);
552bbe1b32bSmrg		}
553bbe1b32bSmrg	    }
554bbe1b32bSmrg	}
555bbe1b32bSmrg    }
556bbe1b32bSmrg}
557