#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include "FSlibint.h"
#include <X11/Xtrans/Xtrans.h>
static int _FSdebug = 0;
static fsReq _dummy_request = {
0, 0, 0
};
static void OutOfMemory ( FSServer *svr, char *setup );
FSServer *_FSHeadOfServerList = NULL;
void _FSFreeServerStructure(FSServer *svr)
{
if (svr->server_name)
FSfree(svr->server_name);
if (svr->vendor)
FSfree(svr->vendor);
if (svr->buffer)
FSfree(svr->buffer);
FSfree((char *) svr);
}
static
void OutOfMemory(
FSServer *svr,
char *setup)
{
if (svr->trans_conn)
_FSDisconnectServer(svr->trans_conn);
_FSFreeServerStructure(svr);
FSfree(setup);
errno = ENOMEM;
}
FSServer *
FSOpenServer(char *server)
{
FSServer *svr;
int i;
int endian;
fsConnClientPrefix client;
fsConnSetup prefix;
char *setup = NULL;
fsConnSetupAccept conn;
char *auth_data = NULL;
char *alt_data = NULL,
*ad;
AlternateServer *alts = NULL;
int altlen;
char *vendor_string;
unsigned long setuplength;
if (server == NULL || *server == '\0') {
if ((server = getenv("FONTSERVER")) == NULL) {
return (FSServer *) NULL;
}
}
if ((svr = (FSServer *) FScalloc(1, sizeof(FSServer))) == NULL) {
errno = ENOMEM;
return (FSServer *) NULL;
}
if ((svr->server_name = FSmalloc((unsigned) (strlen(server) + 1)))
== NULL) {
goto fail;
}
(void) strcpy(svr->server_name, server);
if ((svr->trans_conn = _FSConnectServer(server)) == NULL) {
goto fail;
}
svr->fd = _FSTransGetConnectionNumber (svr->trans_conn);
endian = 1;
if (*(char *) &endian)
client.byteOrder = 'l';
else
client.byteOrder = 'B';
client.major_version = FS_PROTOCOL;
client.minor_version = FS_PROTOCOL_MINOR;
client.num_auths = 0;
client.auth_len = 0;
_FSSendClientPrefix(svr, &client);
_FSRead(svr, (char *) &prefix, (long) SIZEOF(fsConnSetup));
setuplength = prefix.alternate_len << 2;
if (setuplength > (SIZE_MAX>>2)
|| (alt_data = (char *)
(setup = FSmalloc((unsigned) setuplength))) == NULL) {
goto fail;
}
_FSRead(svr, (char *) alt_data, setuplength);
ad = alt_data;
#if SIZE_MAX <= UINT_MAX
if (prefix.num_alternates > SIZE_MAX / sizeof(AlternateServer)) {
goto fail;
}
#endif
alts = (AlternateServer *)
FSmalloc(sizeof(AlternateServer) * prefix.num_alternates);
if (!alts) {
goto fail;
}
for (i = 0; i < prefix.num_alternates; i++) {
alts[i].subset = (Bool) *ad++;
altlen = (int) *ad++;
alts[i].name = (char *) FSmalloc(altlen + 1);
if (!alts[i].name) {
while (--i) {
FSfree((char *) alts[i].name);
}
goto fail;
}
memmove(alts[i].name, ad, altlen);
alts[i].name[altlen] = '\0';
ad += altlen + ((4 - (altlen + 2)) & 3);
}
FSfree((char *) alt_data);
alt_data = NULL;
svr->alternate_servers = alts;
svr->num_alternates = prefix.num_alternates;
setuplength = prefix.auth_len << 2;
if (setuplength > (SIZE_MAX>>2)
|| (auth_data = (char *)
(setup = FSmalloc((unsigned) setuplength))) == NULL) {
goto fail;
}
_FSRead(svr, (char *) auth_data, setuplength);
if (prefix.status != AuthSuccess) {
fprintf(stderr, "%s: connection to \"%s\" refused by server\r\n%s: ",
"FSlib", server, "FSlib");
goto fail;
}
_FSRead(svr, (char *) &conn, (long) SIZEOF(fsConnSetupAccept));
if ((vendor_string = (char *)
FSmalloc((unsigned) conn.vendor_len + 1)) == NULL) {
goto fail;
}
_FSReadPad(svr, (char *) vendor_string, conn.vendor_len);
svr->next = (FSServer *) NULL;
svr->proto_version = prefix.major_version;
svr->release = conn.release_number;
svr->max_request_size = conn.max_request_len;
svr->event_vec[FS_Error] = _FSUnknownWireEvent;
svr->event_vec[FS_Reply] = _FSUnknownWireEvent;
svr->wire_vec[FS_Error] = _FSUnknownNativeEvent;
svr->wire_vec[FS_Reply] = _FSUnknownNativeEvent;
for (i = FSLASTEvent; i < 128; i++) {
svr->event_vec[i] = _FSUnknownWireEvent;
svr->wire_vec[i] = _FSUnknownNativeEvent;
}
svr->resource_id = 1;
svr->vendor = vendor_string;
svr->vendor[conn.vendor_len] = '\0';
svr->vnumber = FS_PROTOCOL;
svr->request = 0;
svr->last_request_read = 0;
svr->last_req = (char *) &_dummy_request;
if ((svr->bufptr = svr->buffer = FSmalloc(BUFSIZE)) == NULL) {
goto fail;
}
svr->bufmax = svr->buffer + BUFSIZE;
svr->head = svr->tail = NULL;
svr->qlen = 0;
FSfree(setup);
setup = NULL;
(void) FSSynchronize(svr, _FSdebug);
svr->next = _FSHeadOfServerList;
_FSHeadOfServerList = svr;
return (svr);
fail:
FSfree((char *) alts);
FSfree((char *) alt_data);
FSfree((char *) auth_data);
OutOfMemory(svr, setup);
return (FSServer *) NULL;
}