/* * 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: resource.c /main/7 1997/03/14 13:45:09 barstow $ */ /* (c) Copyright 1997 The Open Group */ /* * * (c) Copyright 1993, 1994 Hewlett-Packard Company * * (c) Copyright 1993, 1994 International Business Machines Corp. * * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * * (c) Copyright 1993, 1994 Novell, Inc. * */ /* * xdm - display manager daemon * * Copyright 1988 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, 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 M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * Author: Keith Packard, MIT X Consortium */ /* * resource.c */ # include "dm.h" # include "vgmsg.h" # include # include # include void CleanUpName( char *src, char *dst, int len) ; static char * getFullFileName(char *name, int special, char * lang); extern char * qualifyWithFirst(char *, char *); void GetSysParms(char **tzpp, char **fhpp, char **ftpp); // fontpath.c /* XtOffset() hack for ibmrt BandAidCompiler */ int session_set = False; char *config; char *servers; int request_port; int debugLevel; char *errorLogFile; int errorLogSize; int daemonMode; int quiet; char *pidFile; int lockPidFile; char *authDir; int autoRescan; int removeDomainname; char *keyFile; char *accessFile; char **exportList; /* List of all export env vars */ char *sysParmsFile; char *timeZone; char *fpHead = NULL; char *fpTail = NULL; int wakeupInterval; int langListTimeout; #ifdef DEF_NETWORK_DEV char *networkDev; #endif /* * Dtlogin will accept both Dtlogin and XDM resources. The string variable * "AppName" contains the proper application name to use in looking up * resources. */ # define DISPLAYMANAGER "DisplayManager" # define DTLOGIN "Dtlogin" static char AppName[16] = DTLOGIN; # define DM_STRING 0 # define DM_INT 1 # define DM_BOOL 2 # define DM_ARGV 3 /* * the following constants are supposed to be set in the makefile from * parameters set util/imake.includes/site.def (or *.macros in that directory * if it is server-specific). DO NOT CHANGE THESE DEFINITIONS! */ #ifndef DEF_SERVER_LINE # ifdef sun #define DEF_SERVER_LINE ":0 local /usr/openwin/bin/X :0" # else #define DEF_SERVER_LINE ":0 local /usr/bin/X11/X :0" # endif /* sun */ #endif #ifndef XRDB_PROGRAM # ifdef sun #define XRDB_PROGRAM "/usr/openwin/bin/xrdb" # else #define XRDB_PROGRAM "/usr/bin/X11/xrdb" # endif /* sun */ #endif #ifndef DEF_SESSION #define DEF_SESSION CDE_INSTALLATION_TOP "/bin/Xsession" #endif #ifndef DEF_USER_PATH # ifdef sun # define DEF_USER_PATH "/usr/openwin/bin:/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin:." # else # define DEF_USER_PATH "/usr/bin/X11:/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin" # endif /* sun */ #endif #ifndef DEF_SYSTEM_PATH # ifdef sun # define DEF_SYSTEM_PATH "/usr/openwin/bin:/etc:/bin:/usr/bin" # else # define DEF_SYSTEM_PATH "/usr/bin/X11:/etc:/bin:/usr/bin" # endif /* sun */ #endif #ifndef DEF_SYSTEM_SHELL #define DEF_SYSTEM_SHELL "/bin/sh" #endif #ifndef DEF_FAILSAFE_CLIENT # ifdef sun #define DEF_FAILSAFE_CLIENT "/usr/openwin/bin/xterm" # else #define DEF_FAILSAFE_CLIENT "/usr/bin/X11/xterm" # endif /* sun */ #endif #ifndef DEF_XDM_CONFIG #define DEF_XDM_CONFIG "Xconfig" #endif #ifndef DEF_CHOOSER #define DEF_CHOOSER CDE_INSTALLATION_TOP "/bin/chooser" #endif #ifndef CPP_PROGRAM #define CPP_PROGRAM "/lib/cpp" #endif #ifndef DEF_XDM_AUTH_GEN #define DEF_XDM_AUTH_GEN CDE_CONFIGURATION_TOP "/xdmauthgen" #endif #ifndef DEF_AUTH_NAME #define DEF_AUTH_NAME "MIT-MAGIC-COOKIE-1" #endif #ifndef DEF_AUTH_DIR #define DEF_AUTH_DIR CDE_CONFIGURATION_TOP #endif #ifndef DEF_USER_AUTH_DIR #define DEF_USER_AUTH_DIR "/tmp" #endif #ifndef DEF_KEY_FILE #define DEF_KEY_FILE CDE_CONFIGURATION_TOP "/Xkeys" #endif #ifndef DEF_ACCESS_FILE #define DEF_ACCESS_FILE "" #endif #ifndef DEF_TIMEZONE #define DEF_TIMEZONE "MST7MDT" #endif #ifndef DEF_SYS_PARMS_FILE # define DEF_SYS_PARMS_FILE "/etc/TIMEZONE" #endif #define DEF_UDP_PORT "177" /* registered XDMCP port, don't change */ #ifndef DEF_ENV # ifdef sun /* need to set the environment for Sun OpenWindows */ # define DEF_ENV "OPENWINHOME=/usr/openwin" # else # define DEF_ENV "" # endif #endif #ifndef DEF_LANG /* LANG default settings for various architectures */ # ifdef sun /* default language under Solaris */ # define DEF_LANG "C" # endif #endif #ifndef DEF_LANG /* set LANG to NULL if not already defined */ #define DEF_LANG "" #endif struct dmResources { char *name, *class; int type; char **dm_value; char *default_value; } DmResources[] = { "servers", "Servers", DM_STRING, &servers, DEF_SERVER_LINE, "requestPort", "RequestPort", DM_INT, (char **) &request_port, DEF_UDP_PORT, "debugLevel", "DebugLevel", DM_INT, (char **) &debugLevel, "0", "errorLogFile", "ErrorLogFile", DM_STRING, &errorLogFile, "", "errorLogSize", "ErrorLogSize", DM_INT, (char **) &errorLogSize, "50", "daemonMode", "DaemonMode", DM_BOOL, (char **) &daemonMode, "false", "quiet", "quiet", DM_BOOL, (char **) &quiet, "false", "pidFile", "PidFile", DM_STRING, &pidFile, "", "lockPidFile", "LockPidFile", DM_BOOL, (char **) &lockPidFile, "true", "authDir", "AuthDir", DM_STRING, &authDir, DEF_AUTH_DIR, "autoRescan", "AutoRescan", DM_BOOL, (char **) &autoRescan, "true", "removeDomainname","RemoveDomainname",DM_BOOL, (char **) &removeDomainname, "true", "keyFile", "KeyFile", DM_STRING, &keyFile, DEF_KEY_FILE, "accessFile", "AccessFile", DM_STRING, &accessFile, DEF_ACCESS_FILE, /* exportList env var resource RK 08.17.93 */ "exportList", "ExportList", DM_ARGV, (char **) &exportList, "", "timeZone", "TimeZone", DM_STRING, &timeZone, "", "fontPathHead", "FontPathHead", DM_STRING, &fpHead, "", "fontPathTail", "FontPathTail", DM_STRING, &fpTail, "", "sysParmsFile", "SysParmsFile", DM_STRING, &sysParmsFile, DEF_SYS_PARMS_FILE, "wakeupInterval","WakeupInterval",DM_INT, (char **) &wakeupInterval, "10", "langListTimeout","langListTimeout",DM_INT, (char **) &langListTimeout, "30", #ifdef DEF_NETWORK_DEV "networkDevice","NetworkDevice",DM_STRING, &networkDev, DEF_NETWORK_DEV, #endif }; # define NUM_DM_RESOURCES (sizeof DmResources / sizeof DmResources[0]) # define boffset(f) ((char *) &(((struct display *) 0)->f) - (char *) 0) struct displayResources { char *name, *class; int type; int offset; char *default_value; } DisplayResources[] = { /* * resources for managing the server... */ "serverAttempts","ServerAttempts", DM_INT, boffset(serverAttempts), "1", "openDelay", "OpenDelay", DM_INT, boffset(openDelay), "5", "openRepeat", "OpenRepeat", DM_INT, boffset(openRepeat), "5", "openTimeout", "OpenTimeout", DM_INT, boffset(openTimeout), "30", "startAttempts","StartAttempts",DM_INT, boffset(startAttempts), "4", "pingInterval", "PingInterval", DM_INT, boffset(pingInterval), "5", "pingTimeout", "PingTimeout", DM_INT, boffset(pingTimeout), "5", "terminateServer","TerminateServer",DM_BOOL, boffset(terminateServer), "false", "grabServer", "GrabServer", DM_BOOL, boffset(grabServer), "true", "grabTimeout", "GrabTimeout", DM_INT, boffset(grabTimeout), "3", "resetSignal", "Signal", DM_INT, boffset(resetSignal), "1", /* SIGHUP */ "termSignal", "Signal", DM_INT, boffset(termSignal), "15", /* SIGTERM */ "resetForAuth", "ResetForAuth", DM_BOOL, boffset(resetForAuth), "false", "authorize", "Authorize", DM_BOOL, boffset(authorize), "true", "authName", "AuthName", DM_ARGV, boffset(authNames), DEF_AUTH_NAME, "authFile", "AuthFile", DM_STRING, boffset(authFile), "", #if 0 "gettyLine", "GettyLine", DM_STRING, boffset(gettyLine), "", "gettySpeed", "GettySpeed", DM_STRING, boffset(gettySpeed), "9600", #endif /* * resources which control the session behavior... */ "resources", "Resources", DM_STRING, boffset(resources), "", "xrdb", "Xrdb", DM_STRING, boffset(xrdb), XRDB_PROGRAM, "cpp", "Cpp", DM_STRING, boffset(cpp), CPP_PROGRAM, "setup", "Setup", DM_STRING, boffset(setup), "", "startup", "Startup", DM_STRING, boffset(startup), "", "reset", "Reset", DM_STRING, boffset(reset), "", "session", "Session", DM_STRING, boffset(session), DEF_SESSION, "userPath", "Path", DM_STRING, boffset(userPath), DEF_USER_PATH, "systemPath", "Path", DM_STRING, boffset(systemPath), DEF_SYSTEM_PATH, "systemShell", "Shell", DM_STRING, boffset(systemShell), DEF_SYSTEM_SHELL, "failsafeClient","FailsafeClient", DM_STRING, boffset(failsafeClient), DEF_FAILSAFE_CLIENT, "userAuthDir", "UserAuthDir", DM_STRING, boffset(userAuthDir), DEF_AUTH_DIR, "chooser", "Chooser", DM_STRING, boffset(chooser), DEF_CHOOSER, "language", "Language", DM_STRING, boffset(language), DEF_LANG, "languageList", "LanguageList", DM_STRING, boffset(langList), "", "environment", "Environment", DM_STRING, boffset(environStr), DEF_ENV, "dtlite", "Dtlite", DM_BOOL, boffset(dtlite), "false", "xdmMode", "XdmMode", DM_BOOL, boffset(xdmMode), "false", "authenticationName","AuthenticationName", DM_STRING, boffset(verifyName), "", "pmSearchPath", "PmSearchPath", DM_STRING, boffset(pmSearchPath), DEF_PM_SEARCH_PATH, "bmSearchPath", "bmSearchPath", DM_STRING, boffset(bmSearchPath), DEF_BM_SEARCH_PATH, }; # define NUM_DISPLAY_RESOURCES (sizeof DisplayResources/sizeof DisplayResources[0]) XrmDatabase DmResourceDB; int GetResource( char *name, char *class, int valueType, char **valuep, char *default_value ) { char *type; XrmValue value; char *string, *new_string; char empty[] = ""; char str_buf[50]; int len; if (DmResourceDB && XrmGetResource (DmResourceDB, name, class, &type, &value)) { string = value.addr; len = value.size; } else { if(default_value) { string = default_value; len = strlen (string); } else { string = empty; len = 0; } } Debug ("%s/%s value %*.*s\n", name, class, len, len, string); /* * check if new resource is the same as old... */ if (valueType == DM_STRING && *valuep) { if (string != NULL && strlen (*valuep) == len && !strncmp (*valuep, string, len)) return 0; else { free (*valuep); *(valuep) = NULL; } } switch (valueType) { case DM_STRING: if ( len > 0 ) { new_string = malloc ((unsigned) (len+1)); if (!new_string) { LogOutOfMem( ReadCatalog(MC_LOG_SET,MC_LOG_GET_RSC,MC_DEF_LOG_GET_RSC)); return 0; } strncpy (new_string, string, len); new_string[len] = '\0'; *(valuep) = new_string; } break; case DM_INT: strncpy (str_buf, string, sizeof (str_buf)); str_buf[sizeof (str_buf)-1] = '\0'; *((int *) valuep) = atoi (str_buf); break; case DM_BOOL: strncpy (str_buf, string, sizeof (str_buf)); str_buf[sizeof (str_buf)-1] = '\0'; XmuCopyISOLatin1Lowered (str_buf, str_buf); if (!strcmp (str_buf, "true") || !strcmp (str_buf, "on") || !strcmp (str_buf, "yes")) *((int *) valuep) = 1; else if (!strcmp (str_buf, "false") || !strcmp (str_buf, "off") || !strcmp (str_buf, "no")) *((int *) valuep) = 0; break; case DM_ARGV: *((char ***) valuep) = parseArgs ((char **) 0, string); break; } return 1; } XrmOptionDescRec configTable [] = { {"-server", NULL, XrmoptionSkipArg, (caddr_t) NULL }, {"-udpPort", NULL, XrmoptionSkipArg, (caddr_t) NULL }, {"-error", NULL, XrmoptionSkipArg, (caddr_t) NULL }, {"-resources", NULL, XrmoptionSkipArg, (caddr_t) NULL }, {"-session", NULL, XrmoptionSkipArg, (caddr_t) NULL }, {"-debug", NULL, XrmoptionSkipArg, (caddr_t) NULL }, {"-xrm", NULL, XrmoptionSkipArg, (caddr_t) NULL }, {"-config", ".configFile", XrmoptionSepArg, (caddr_t) NULL } }; XrmOptionDescRec optionTable [] = { {"-server", ".servers", XrmoptionSepArg, (caddr_t) NULL }, {"-udpPort", ".requestPort", XrmoptionSepArg, (caddr_t) NULL }, {"-error", ".errorLogFile", XrmoptionSepArg, (caddr_t) NULL }, {"-resources", "*resources", XrmoptionSepArg, (caddr_t) NULL }, {"-session", "*session", XrmoptionSepArg, (caddr_t) NULL }, {"-debug", "*debugLevel", XrmoptionSepArg, (caddr_t) NULL }, {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL }, {"-daemon", ".daemonMode", XrmoptionNoArg, "true" }, {"-nodaemon", ".daemonMode", XrmoptionNoArg, "false" }, {"-quiet", ".quiet", XrmoptionNoArg, "true" } }; static int originalArgc; static char **originalArgv; void InitResources( int argc, char **argv ) { XrmInitialize (); originalArgc = argc; originalArgv = argv; ReinitResources (); } void ReinitResources( void ) { int argc; char **a; char **argv; XrmDatabase newDB; char * configFileName; char *type; XrmValue value; argv = (char **) malloc ((originalArgc + 1) * sizeof (char *)); if (!argv) LogOutOfMem( ReadCatalog(MC_LOG_SET,MC_LOG_NO_SPACE,MC_DEF_LOG_NO_SPACE)); for (argc = 0; argc < originalArgc; argc++) argv[argc] = originalArgv[argc]; argv[argc] = 0; if (DmResourceDB) XrmDestroyDatabase (DmResourceDB); DmResourceDB = XrmGetStringDatabase (""); /* pre-parse the command line to get the -config option, if any */ XrmParseCommand (&DmResourceDB, configTable, sizeof (configTable) / sizeof (configTable[0]), "Dtlogin", &argc, argv); configFileName = qualifyWithFirst(DEF_XDM_CONFIG, CDE_CONFIGURATION_TOP "/config:" CDE_INSTALLATION_TOP "/config"); GetResource ("Dtlogin.configFile", "Dtlogin.ConfigFile", DM_STRING, &config, configFileName); free(configFileName); newDB = XrmGetFileDatabase ( config ); if (newDB) { if (DmResourceDB) XrmDestroyDatabase (DmResourceDB); DmResourceDB = newDB; } else if (argc != originalArgc) LogError( ReadCatalog(MC_LOG_SET,MC_LOG_NO_OPENCFG,MC_DEF_LOG_NO_OPENCFG), config ); /* * scan the resource database to set the application name... */ SetAppName(); XrmParseCommand (&DmResourceDB, optionTable, sizeof (optionTable) / sizeof (optionTable[0]), AppName, &argc, argv); /* * test to see if the session variable is set. * for enabling the toggle in the options menu, if it is set.. */ if((XrmGetResource (DmResourceDB, "Dtlogin*session", "Dtlogin*Session", &type, &value)) == True) session_set = True; if (argc > 1) { LogError(ReadCatalog(MC_LOG_SET,MC_LOG_EXTRA_ARG,MC_DEF_LOG_EXTRA_ARG)); for (a = argv + 1; *a; a++) LogError ((unsigned char *)" \"%s\"", *a); LogError ((unsigned char *)"\n"); } free (argv); } void LoadDMResources( void ) { int i; char name[1024], class[1024]; FILE *fp; if (servers) {free(servers); servers=NULL;} if (keyFile) {free(keyFile); keyFile=NULL;} if (accessFile) {free(accessFile); accessFile=NULL;} for (i = 0; i < NUM_DM_RESOURCES; i++) { sprintf (name, "%s.%s", AppName, DmResources[i].name); sprintf (class, "%s.%s", AppName, DmResources[i].class); GetResource (name, class, DmResources[i].type, (char **) DmResources[i].dm_value, DmResources[i].default_value); } servers = getFullFileName(servers, 1, NULL); keyFile = getFullFileName(keyFile, 0, NULL); accessFile = getFullFileName(accessFile, 0, NULL); /* set a TZ default */ if (timeZone == NULL || strlen(timeZone) == 0) { /* * dynamically determine the timeZone resource default value... */ GetSysParms(&timeZone,0,0); } } void CleanUpName( char *src, char *dst, int len ) { while (*src) { if (--len <= 0) break; switch (*src) { case ':': case '.': *dst++ = '_'; break; default: *dst++ = *src; } ++src; } *dst = '\0'; } void LoadDisplayResources( struct display *d ) { int i; char name[1024], class[1024]; char dpyName[512], dpyClass[512]; char *lang; Debug("Loading display resources for %s\n", d->name); if (d->resources) {free(d->resources); d->resources=NULL;} if (d->setup) {free(d->setup); d->setup=NULL;} if (d->startup) {free(d->startup); d->startup=NULL;} if (d->reset) {free(d->reset); d->reset=NULL;} if (d->session) {free(d->session); d->session=NULL;} if (d->failsafeClient) {free(d->failsafeClient); d->failsafeClient=NULL;} CleanUpName (d->name, dpyName, sizeof (dpyName)); CleanUpName (d->class ? d->class : d->name, dpyClass, sizeof (dpyClass)); if((lang = getenv("LANG")) != NULL) for (i = NUM_DISPLAY_RESOURCES - 1; i >= 0; i--) { if(strcmp(DisplayResources[i].name,"language") == 0){ DisplayResources[i].default_value = lang; break; } } lang = d->language; d->language = NULL; for (i = 0; i < NUM_DISPLAY_RESOURCES; i++) { sprintf (name, "%s.%s.%s", AppName, dpyName, DisplayResources[i].name); sprintf (class, "%s.%s.%s", AppName, dpyClass, DisplayResources[i].class); GetResource (name, class, DisplayResources[i].type, (char **) (((char *) d) + DisplayResources[i].offset), DisplayResources[i].default_value); } if (!strlen(lang) && d->language && strlen(d->language)) *(strncpy(lang, d->language, LANGUAGESIZE) + LANGUAGESIZE) = '\0'; free(d->language); d->language = lang; #ifdef _AIX if(d->language == NULL || strlen(d->language) == 0) SetDefaultLanguage(d); #endif /* _AIX */ d->resources = getFullFileName(d->resources, 2, d->language); d->setup = getFullFileName(d->setup, 0, NULL); d->startup = getFullFileName(d->startup, 0, NULL); d->reset = getFullFileName(d->reset, 0, NULL); d->session = getFullFileName(d->session, 0, NULL); d->failsafeClient = getFullFileName(d->failsafeClient, 0, NULL); } /*************************************************************************** * * SetAppName * * Probe the resource database to see whether the config file is using * "Dtlogin" or "DisplayManager" as the application name. * * If it cannot be determined, "Dtlogin" is used. ***************************************************************************/ void SetAppName( void ) { int i; char name[1024], class[1024]; char *type; XrmValue value; for (i = 0; i < NUM_DM_RESOURCES; i++) { /* * try "Dtlogin" (default) ... */ sprintf (name, "%s.%s", DTLOGIN, DmResources[i].name); sprintf (class, "%s.%s", DTLOGIN, DmResources[i].class); if (DmResourceDB && XrmGetResource (DmResourceDB, name, class, &type, &value)) { strcpy(AppName, DTLOGIN); break; } /* * try "DisplayManager" ... */ sprintf (name, "%s.%s", DISPLAYMANAGER, DmResources[i].name); sprintf (class, "%s.%s", DISPLAYMANAGER, DmResources[i].class); if (DmResourceDB && XrmGetResource (DmResourceDB, name, class, &type, &value)) { strcpy(AppName, DISPLAYMANAGER); break; } } } /*************************************************************************** * * getFullFileName * * Try to produce a fully qualified file name by prepending * /etc/dt/config or /usr/dt/config to a resource file name. * There are 2 special cases: servers - which can be a command, and * resources - which can an imbeded %L. ***************************************************************************/ extern char *_ExpandLang( char *string, char *lang ); static char * getFullFileName(char *name, int special, char *lang) { char * newname; if (name == NULL) return(NULL); /** if the file already starts with a '/' **/ /** then just return a copy of it **/ if (name[0] == '/') { if ((newname = (char *)malloc((strlen(name)+1)*sizeof(char))) == NULL) { return (NULL); } else { strcpy(newname, name); return(newname); } } switch (special) { /*********************/ case 0: /** no special case **/ /*********************/ newname = qualifyWithFirst(name, CDE_CONFIGURATION_TOP "/config:" CDE_INSTALLATION_TOP "/config"); return (newname); /***************************************/ case 1: /** special handling for servers file **/ /***************************************/ if (strchr(name, ':') != NULL) { /** This is probably a command and not a file name **/ /** so just return a copy of it. **/ if ((newname = (char *)malloc((strlen(name)+1)*sizeof(char))) == NULL) { return (NULL); } else { strcpy(newname, name); return(newname); } } else { newname = qualifyWithFirst(name, CDE_CONFIGURATION_TOP "/config:" CDE_INSTALLATION_TOP "/config"); return (newname); } /********************************************/ case 2: /** special handling for d->resources file **/ /********************************************/ if (strchr(name, '%') == NULL) { /** no special processing needed **/ newname = qualifyWithFirst(name, CDE_CONFIGURATION_TOP "/config:" CDE_INSTALLATION_TOP "/config"); return (newname); } else { char *langString; char *tempName; int tempLen; /** need to remember the %L **/ if (lang == NULL) lang = "C"; langString = _ExpandLang(name, lang); if ( (tempName = qualifyWithFirst(langString, CDE_CONFIGURATION_TOP "/config:" CDE_INSTALLATION_TOP "/config") ) == NULL) { free(langString); langString = _ExpandLang(name, "C"); if ( (tempName = qualifyWithFirst(langString, CDE_CONFIGURATION_TOP "/config:" CDE_INSTALLATION_TOP "/config") ) == NULL) { free(langString); return(NULL); } } /** We have a fully qualified and expanded file name **/ /** but we need to return a fully qualified but NOT **/ /** expanded file name. **/ tempLen = strlen(tempName) - strlen(langString) + strlen(name) + 1; if ((newname = (char *)malloc(tempLen * sizeof(char))) == NULL){ free(langString); return(tempName); } else { tempLen = strlen(tempName) - strlen(langString); strncpy(newname, tempName, tempLen); strcpy(newname+tempLen, name); free (langString); free (tempName); return(newname); } } default: /* special is of an unknown value */ return(NULL); } }