/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $TOG: SmDB.c /main/5 1998/07/23 18:11:31 mgreess $ */ /* * (c) Copyright 1996 Digital Equipment Corporation. * (c) Copyright 1996 Hewlett-Packard Company. * (c) Copyright 1996 International Business Machines Corp. * (c) Copyright 1996 Sun Microsystems, Inc. * (c) Copyright 1996 Novell, Inc. * (c) Copyright 1996 FUJITSU LIMITED. * (c) Copyright 1996 Hitachi. */ #include #include #include #include #include "SmDB.h" #define RESOURCE_BUF_SZ 1024 #define CLIENT_ID_SZ 20 typedef struct _ClientDBRec { XrmDatabase xrmDB; /* Xrm resource database. */ Boolean openForInput; /* True if input, False if output. */ char *xrmDBFileName; /* Filename, for openForInput == False. */ char *tmpDBFileName; FILE *xrmDBFile; /* Below used if openForInput. */ char **XSMPClients; /* malloc'd array of XSMP client IDs. */ int nXSMPClients; /* number of XSMP clients. */ int nextXSMPClientIndex; /* index of next XSMP client to Get; * also used as sequence # for Put. */ char **proxyClients; /* malloc'd array of Proxy client IDs. */ int nProxyClients; /* number of Proxy clients. */ int nextProxyClientIndex; /* index of next Proxy client to Get; * also used as sequence # for Put. */ } ClientDBRec; static Boolean xrmInitialized = False; static XrmName XSMPName[2]; static XrmClass XSMPClass[2]; static XrmName proxyName[2]; static XrmClass proxyClass[2]; static XrmQuark anyQuark; static char *resourceBuf = NULL; static char *clientIDBuf = NULL; /* Public strings */ char *versionStr = ".version"; char *dtsessionIDStr = ".dtsessionID"; /* Strings for XSMP clients. */ static char *clientStr = "!\nClient.%s"; static char *programStr = "%s.Program"; static char *cwdStr = "%s.Cwd"; static char *restartCmdStr = "%s.RestartCommand"; static char *cloneCmdStr = "%s.CloneCommand"; static char *discardCmdStr = "%s.DiscardCommand"; static char *environmentStr = "%s.Environment"; static char *restartHintStr = "%s.RestartHint"; static char *sessionIDStr = "%s.SessionID"; /* Strings for Proxy clients. */ static char *proxyStr = "!\nProxyClient.%s"; static char *commandStr = "%s.Command"; /* Common resources (XSMP and Proxy). */ static char *clientHostStr = "%s.ClientHost"; static char *screenNumStr = "%s.ScreenNum"; static void _initXrm(void); static Bool _countProc(XrmDatabase *, XrmBindingList, XrmQuarkList, XrmRepresentation *, XrmValue *, XPointer); static Bool _fillClientIDProc(XrmDatabase *, XrmBindingList, XrmQuarkList, XrmRepresentation *, XrmValue *, XPointer); static Bool _fillStringArrayProc(XrmDatabase *, XrmBindingList, XrmQuarkList, XrmRepresentation *, XrmValue *, XPointer); static Boolean _getStringResource(XrmDatabase, char *, char *, char **, char *); static Boolean _getIntResource(XrmDatabase, char *, char *, int *, int); static Boolean _getStringArrayResource(XrmDatabase, char *, char *, char ***, char **); static void _freeStringArray(char **); static Boolean _putStringResource(ClientDBRec *, char *, char *, char *); static Boolean _putIntResource(ClientDBRec *, char *, char *, int); static Boolean _putStringArrayResource(ClientDBRec *, char *, char *, char **); static char *_tmpFileName(char *); static void _initXrm(void) { if (!xrmInitialized) { XrmInitialize(); /* Just in case. */ anyQuark = XrmStringToQuark("?"); XSMPName[0] = proxyName[0] = anyQuark; XSMPClass[0] = XrmStringToClass("Client"); proxyClass[0] = XrmStringToClass("ProxyClient"); XSMPName[1] = XSMPClass[1] = proxyName[1] = proxyClass[1] = NULLQUARK; xrmInitialized = True; } } static Bool _countProc(XrmDatabase *clientDB, XrmBindingList bindingList, XrmQuarkList quarkList, XrmRepresentation *reps, XrmValue *value, XPointer uData) { int *countP = (int *)uData; (*countP)++; return FALSE; } static Bool _fillClientIDProc(XrmDatabase *clientDB, XrmBindingList bindingList, XrmQuarkList quarkList, XrmRepresentation *reps, XrmValue *value, XPointer uData) { char ***idListPtr = (char ***)uData; char **clientIDPtr = *idListPtr; *clientIDPtr = (char *)value->addr; (*idListPtr)++; return FALSE; } static Bool _fillStringArrayProc(XrmDatabase *clientDB, XrmBindingList bindingList, XrmQuarkList quarkList, XrmRepresentation *reps, XrmValue *value, XPointer uData) { char **stringsPtr = (char **)uData; char *indexStr; /* Our index into this string array is at quarkList[2]. */ if ((indexStr = XrmQuarkToString(quarkList[2])) == (char *)NULL) return True; if ((stringsPtr[atoi(indexStr)] = XtNewString((char *)value->addr)) == (char *)NULL) return True; return FALSE; } static Boolean _getStringResource(XrmDatabase xrmDB, char *fmtStr, char *clientID, char **resourcePtr, char *defaultVal) { char *resourceType; XrmValue resourceValue; if (NULL == resourceBuf) resourceBuf = XtMalloc(RESOURCE_BUF_SZ); sprintf(resourceBuf, fmtStr, clientID); if (XrmGetResource(xrmDB, resourceBuf, resourceBuf, &resourceType, &resourceValue)) { if ((*resourcePtr = XtNewString(resourceValue.addr)) == (char *)NULL) return False; return True; } *resourcePtr = defaultVal; return True; } static Boolean _getIntResource(XrmDatabase xrmDB, char *fmtStr, char *clientID, int *resourcePtr, int defaultVal) { char *resourceType; XrmValue resourceValue; if (NULL == resourceBuf) resourceBuf = XtMalloc(RESOURCE_BUF_SZ); sprintf(resourceBuf, fmtStr, clientID); *resourcePtr = (XrmGetResource(xrmDB, resourceBuf, resourceBuf, &resourceType, &resourceValue)) ? atoi(resourceValue.addr) : defaultVal; return True; } static Boolean _getStringArrayResource(XrmDatabase xrmDB, char *fmtStr, char *clientID, char ***resourcePtr, char **defaultVal) { XrmQuark resourceName[3]; XrmQuark resourceClass[3]; char *resourceType; XrmValue resourceValue; int nStrings; resourceName[0] = resourceName[1] = anyQuark; resourceName[2] = NULLQUARK; if (NULL == resourceBuf) resourceBuf = XtMalloc(RESOURCE_BUF_SZ); sprintf(resourceBuf, fmtStr, clientID); XrmStringToQuarkList(resourceBuf, resourceClass); nStrings = 0; XrmEnumerateDatabase(xrmDB, resourceName, resourceClass, XrmEnumOneLevel, _countProc, (XPointer)&nStrings); if (nStrings > 0) { char **stringsPtr; int i; if ((stringsPtr = (char **)XtMalloc((nStrings + 1) * sizeof(char *))) == (char **)NULL) return False; /* Initialize array entries to NULL so free can work. */ /* NOTE: Final entry (nStrings) will remain NULL. */ for (i = 0; i <= nStrings; i++) stringsPtr[i] = (char *)NULL; if (XrmEnumerateDatabase(xrmDB, resourceName, resourceClass, XrmEnumOneLevel, _fillStringArrayProc, (XPointer)stringsPtr)) { for (i = 0; i < nStrings; i++) XtFree(stringsPtr[i]); XtFree((char *)stringsPtr); return False; } *resourcePtr = stringsPtr; return True; } *resourcePtr = defaultVal; return True; } static void _freeStringArray(char **stringsPtr) { if (stringsPtr) { int i; for (i = 0; stringsPtr[i] != (char *)NULL; i++) XtFree(stringsPtr[i]); XtFree((char *)stringsPtr); } } static Boolean _putStringResource(ClientDBRec *clientDB, char *fmtStr, char *clientID, char *resourceVal) { if (resourceVal != (char *)NULL) { if (NULL == clientIDBuf) clientIDBuf = XtMalloc(RESOURCE_BUF_SZ); sprintf(clientIDBuf, fmtStr, clientID); if (fprintf(clientDB->xrmDBFile, "%s: %s\n", clientIDBuf, resourceVal) < 0) return False; } return True; } static Boolean _putIntResource(ClientDBRec *clientDB, char *fmtStr, char *clientID, int resourceVal) { if (NULL == clientIDBuf) clientIDBuf = XtMalloc(RESOURCE_BUF_SZ); sprintf(clientIDBuf, fmtStr, clientID); if (fprintf(clientDB->xrmDBFile, "%s: %d\n", clientIDBuf, resourceVal) < 0) return False; return True; } static Boolean _putStringArrayResource(ClientDBRec *clientDB, char *fmtStr, char *clientID, char **resourceVal) { int i; if (resourceVal != (char **)NULL) { for (i = 0; resourceVal[i] != (char *)NULL; i++) { if (NULL == clientIDBuf) clientIDBuf = XtMalloc(RESOURCE_BUF_SZ); sprintf(clientIDBuf, fmtStr, clientID); if (fprintf(clientDB->xrmDBFile, "%s.%d: %s\n", clientIDBuf, i, resourceVal[i]) < 0) return False; } } return True; } static char * _tmpFileName(char *fileName) { int fileNameLen = strlen(fileName); char *newFileName = (char *)XtMalloc((fileNameLen + 20) * sizeof(char)); if (newFileName != (char *)NULL) { int i; char *ptr = &(newFileName[fileNameLen]); strcpy(newFileName, fileName); /* Hm. I suppose if a couple billion versions of this file exist */ /* we could loop forever, but that's not likely. */ for (i = 0; ; i++) { sprintf(ptr, "%d", i); if (access(newFileName, F_OK) != 0) break; } } return newFileName; } ClientDB OpenInputClientDB(char *fileName, char **version, char **dtsessionID) { ClientDBRec *inputDB; char **tmpPtr; char *resourceType; XrmValue resourceValue; *version = (char *)NULL; *dtsessionID = (char *)NULL; _initXrm(); if ((fileName == (char *)NULL) || ((inputDB = (ClientDBRec *)XtMalloc(sizeof(ClientDBRec))) == (ClientDBRec *)NULL)) return (ClientDB)NULL; if ((inputDB->xrmDB = XrmGetFileDatabase(fileName)) == (XrmDatabase)NULL) { XtFree((char *)inputDB); return (ClientDB)NULL; } inputDB->openForInput = True; inputDB->XSMPClients = inputDB->proxyClients = (char **)NULL; inputDB->nXSMPClients = inputDB->nProxyClients = 0; inputDB->nextXSMPClientIndex = inputDB->nextProxyClientIndex = 0; /* Count the number of XSMP and Proxy clients. */ XrmEnumerateDatabase(inputDB->xrmDB, XSMPName, XSMPClass, XrmEnumOneLevel, _countProc, (XPointer)&inputDB->nXSMPClients); XrmEnumerateDatabase(inputDB->xrmDB, proxyName, proxyClass, XrmEnumOneLevel, _countProc, (XPointer)&inputDB->nProxyClients); /* Allocate space for the client IDs and fill from database. */ if (inputDB->nXSMPClients > 0) { if ((inputDB->XSMPClients = (char **)XtMalloc(inputDB->nXSMPClients * sizeof(char *))) == (char **)NULL) { XrmDestroyDatabase(inputDB->xrmDB); XtFree((char *)inputDB); return (ClientDB)NULL; } tmpPtr = inputDB->XSMPClients; XrmEnumerateDatabase(inputDB->xrmDB, XSMPName, XSMPClass, XrmEnumOneLevel, _fillClientIDProc, (XPointer)&tmpPtr); } if (inputDB->nProxyClients > 0) { if ((inputDB->proxyClients = (char **)XtMalloc(inputDB->nProxyClients * sizeof(char *))) == (char **)NULL) { XrmDestroyDatabase(inputDB->xrmDB); XtFree((char *)inputDB->XSMPClients); XtFree((char *)inputDB); return (ClientDB)NULL; } tmpPtr = inputDB->proxyClients; XrmEnumerateDatabase(inputDB->xrmDB, proxyName, proxyClass, XrmEnumOneLevel, _fillClientIDProc, (XPointer)&tmpPtr); } if ((!XrmGetResource(inputDB->xrmDB, versionStr, versionStr, &resourceType, &resourceValue)) || ((*version = XtNewString(resourceValue.addr)) == (char *)NULL) || (!XrmGetResource(inputDB->xrmDB, dtsessionIDStr, dtsessionIDStr, &resourceType, &resourceValue)) || ((*dtsessionID = XtNewString(resourceValue.addr)) == (char *)NULL)) { if (*version) { XtFree(*version); *version = (char *)NULL; } XrmDestroyDatabase(inputDB->xrmDB); XtFree((char *)inputDB->XSMPClients); XtFree((char *)inputDB->proxyClients); XtFree((char *)inputDB); return (ClientDB)NULL; } return (ClientDB)inputDB; } ClientDB OpenOutputClientDB(char *fileName, char *version, char *dtsessionID) { ClientDBRec *outputDB; _initXrm(); if ((fileName == (char *)NULL) || (version == (char *)NULL) || (dtsessionID == (char *)NULL) || ((outputDB = (ClientDBRec *)XtMalloc(sizeof(ClientDBRec))) == (ClientDBRec *)NULL)) return (ClientDB)NULL; outputDB->xrmDB = (XrmDatabase)NULL; outputDB->openForInput = False; outputDB->nextXSMPClientIndex = 0; outputDB->nextProxyClientIndex = 0; /* Save current DB to tmp file in case we need to restore later. */ if (((outputDB->xrmDBFileName = XtNewString(fileName)) == (char *)NULL) || ((outputDB->tmpDBFileName = _tmpFileName(fileName)) == (char *)NULL)) { if (outputDB->xrmDBFileName != (char *)NULL) XtFree(outputDB->xrmDBFileName); XtFree((char *)outputDB); return (ClientDB)NULL; } if ((rename(fileName, outputDB->tmpDBFileName) != 0) && (errno != ENOENT)) { XtFree(outputDB->xrmDBFileName); XtFree(outputDB->tmpDBFileName); XtFree((char *)outputDB); return (ClientDB)NULL; } /* Open fileName for writing. */ if ((outputDB->xrmDBFile = fopen(fileName, "w")) == (FILE *)NULL) { int rv; rv = rename(outputDB->tmpDBFileName, fileName); XtFree(outputDB->xrmDBFileName); XtFree(outputDB->tmpDBFileName); XtFree((char *)outputDB); return (ClientDB)NULL; } /* Store version and session ID. */ fprintf(outputDB->xrmDBFile, "! dtsession.db\n!\n%s: %s\n", versionStr, version); fprintf(outputDB->xrmDBFile, "%s: %s\n", dtsessionIDStr, dtsessionID); return (ClientDB)outputDB; } XSMPClientDBRecPtr GetXSMPClientDBRec(ClientDB inputDBPtr) { ClientDBRec *inputDB = (ClientDBRec *)inputDBPtr; XSMPClientDBRecPtr clientPtr; char *clientID; if ((inputDB == (ClientDBRec *)NULL) || (!inputDB->openForInput) || (inputDB->nextXSMPClientIndex >= inputDB->nXSMPClients) || ((clientPtr = (XSMPClientDBRecPtr)XtMalloc(sizeof(XSMPClientDBRec))) == (XSMPClientDBRecPtr)NULL)) { return (XSMPClientDBRecPtr)NULL; } clientID = inputDB->XSMPClients[inputDB->nextXSMPClientIndex]; /* Initialize pointers so Free is easy. */ clientPtr->clientId = (char *)NULL; clientPtr->clientHost = clientPtr->program = clientPtr->cwd = (char *)NULL; clientPtr->restartCommand = clientPtr->cloneCommand = clientPtr->discardCommand = clientPtr->environment = (char **)NULL; /* Retrieve resources from the database. */ if (!_getStringResource(inputDB->xrmDB, sessionIDStr, clientID, &clientPtr->clientId, (char *)NULL) || !_getStringResource(inputDB->xrmDB, clientHostStr, clientID, &clientPtr->clientHost, (char *)NULL) || !_getStringResource(inputDB->xrmDB, programStr, clientID, &clientPtr->program, (char *)NULL) || !_getStringResource(inputDB->xrmDB, cwdStr, clientID, &clientPtr->cwd, (char *)NULL) || !_getIntResource(inputDB->xrmDB, screenNumStr, clientID, &clientPtr->screenNum, 0) || !_getStringArrayResource(inputDB->xrmDB, restartCmdStr, clientID, &clientPtr->restartCommand, (char **)NULL) || !_getStringArrayResource(inputDB->xrmDB, cloneCmdStr, clientID, &clientPtr->cloneCommand, (char **)NULL) || !_getStringArrayResource(inputDB->xrmDB, discardCmdStr, clientID, &clientPtr->discardCommand, (char **)NULL) || !_getStringArrayResource(inputDB->xrmDB, environmentStr, clientID, &clientPtr->environment, (char **)NULL) || !_getIntResource(inputDB->xrmDB, restartHintStr, clientID, (int *)&clientPtr->restartHint, 0)) { FreeXSMPClientDBRec(clientPtr); return (XSMPClientDBRecPtr)NULL; } clientPtr->next = (XSMPClientDBRec *)NULL; inputDB->nextXSMPClientIndex++; return clientPtr; } ProxyClientDBRecPtr GetProxyClientDBRec(ClientDB inputDBPtr) { ClientDBRec *inputDB = (ClientDBRec *)inputDBPtr; ProxyClientDBRecPtr clientPtr; char *clientID; if ((inputDB == (ClientDBRec *)NULL) || (!inputDB->openForInput) || (inputDB->nextProxyClientIndex >= inputDB->nProxyClients) || ((clientPtr = (ProxyClientDBRecPtr)XtMalloc(sizeof(ProxyClientDBRec))) == (ProxyClientDBRecPtr)NULL)) { return (ProxyClientDBRecPtr)NULL; } clientID = inputDB->proxyClients[inputDB->nextProxyClientIndex]; /* Initialize pointers so Free is easy. */ clientPtr->clientHost = (char *)NULL; clientPtr->command = (char **)NULL; /* Retrieve resources from the database. */ if (!_getStringResource(inputDB->xrmDB, clientHostStr, clientID, &clientPtr->clientHost, (char *)NULL) || !_getStringArrayResource(inputDB->xrmDB, commandStr, clientID, &clientPtr->command, (char **)NULL) || !_getIntResource(inputDB->xrmDB, screenNumStr, clientID, &clientPtr->screenNum, 0)) { FreeProxyClientDBRec(clientPtr); return (ProxyClientDBRecPtr)NULL; } inputDB->nextProxyClientIndex++; return clientPtr; } Boolean PutXSMPClientDBRec(ClientDB outputDBPtr, XSMPClientDBRecPtr clientPtr) { ClientDBRec *outputDB = (ClientDBRec *)outputDBPtr; char clientID[CLIENT_ID_SZ]; if ((outputDB == (ClientDBRec *)NULL) || (outputDB->openForInput) || (clientPtr == (XSMPClientDBRecPtr)NULL) || (clientPtr->clientId == (char *)NULL)) return False; sprintf(clientID, "C%d", outputDB->nextXSMPClientIndex++); if (!_putStringResource(outputDB, clientStr, clientID, clientID) || !_putStringResource(outputDB, sessionIDStr, clientID, clientPtr->clientId) || !_putStringResource(outputDB, clientHostStr, clientID, clientPtr->clientHost) || !_putStringResource(outputDB, programStr, clientID, clientPtr->program) || !_putStringResource(outputDB, cwdStr, clientID, clientPtr->cwd) || !_putIntResource(outputDB, screenNumStr, clientID, clientPtr->screenNum) || !_putStringArrayResource(outputDB, restartCmdStr, clientID, clientPtr->restartCommand) || !_putStringArrayResource(outputDB, cloneCmdStr, clientID, clientPtr->cloneCommand) || !_putStringArrayResource(outputDB, discardCmdStr, clientID, clientPtr->discardCommand) || !_putStringArrayResource(outputDB, environmentStr, clientID, clientPtr->environment) || !_putIntResource(outputDB, restartHintStr, clientID, (int)clientPtr->restartHint)) return False; return True; } Boolean PutProxyClientDBRec(ClientDB outputDBPtr, ProxyClientDBRecPtr clientPtr) { ClientDBRec *outputDB = (ClientDBRec *)outputDBPtr; char clientID[CLIENT_ID_SZ]; if ((outputDB == (ClientDBRec *)NULL) || (outputDB->openForInput) || (clientPtr == (ProxyClientDBRecPtr)NULL)) return False; sprintf(clientID, "PC%d", outputDB->nextProxyClientIndex++); if (!_putStringResource(outputDB, proxyStr, clientID, clientID) || !_putStringResource(outputDB, clientHostStr, clientID, clientPtr->clientHost) || !_putStringArrayResource(outputDB, commandStr, clientID, clientPtr->command) || !_putIntResource(outputDB, screenNumStr, clientID, clientPtr->screenNum)) return False; return True; } Boolean CloseClientDB(ClientDB clientDBPtr, Boolean writeDB) { ClientDBRec *clientDB = (ClientDBRec *)clientDBPtr; if (clientDB == (ClientDBRec *)NULL) return False; /* Input? */ if (clientDB->openForInput) { XtFree((char *)clientDB->XSMPClients); XtFree((char *)clientDB->proxyClients); XrmDestroyDatabase(clientDB->xrmDB); XtFree((char *)clientDB); return True; } /* Otherwise, output. */ if (writeDB) { /* Close file and remove temp DB. */ fclose(clientDB->xrmDBFile); unlink(clientDB->tmpDBFileName); } else { int rv; /* Close file and remove it; restore original DB. */ fclose(clientDB->xrmDBFile); rv = rename(clientDB->tmpDBFileName, clientDB->xrmDBFileName); } XtFree(clientDB->xrmDBFileName); XtFree(clientDB->tmpDBFileName); XtFree((char *)clientDB); return True; } void FreeXSMPClientDBRec(XSMPClientDBRecPtr clientPtr) { if (clientPtr != (XSMPClientDBRecPtr)NULL) { XtFree(clientPtr->clientId); XtFree(clientPtr->clientHost); XtFree(clientPtr->program); XtFree(clientPtr->cwd); _freeStringArray(clientPtr->restartCommand); _freeStringArray(clientPtr->cloneCommand); _freeStringArray(clientPtr->discardCommand); _freeStringArray(clientPtr->environment); XtFree((char *)clientPtr); } } void FreeProxyClientDBRec(ProxyClientDBRecPtr clientPtr) { if (clientPtr != (ProxyClientDBRecPtr)NULL) { XtFree(clientPtr->clientHost); _freeStringArray(clientPtr->command); XtFree((char *)clientPtr); } }