913 lines
24 KiB
C
913 lines
24 KiB
C
/*
|
|
* 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 librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* $TOG: DbUtil.c /main/13 1998/04/09 17:47:56 mgreess $
|
|
*
|
|
* (c) Copyright 1988, 1989, 1990, 1991, 1992, 1993
|
|
* by Hewlett-Packard Company, all rights reserved.
|
|
*
|
|
* (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. *
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#ifdef NLS16
|
|
#include <limits.h>
|
|
#endif
|
|
#include <sys/stat.h>
|
|
#include <sys/param.h> /* MAXPATHLEN, MAXHOSTNAMELEN */
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Intrinsic.h>
|
|
#include <X11/StringDefs.h>
|
|
#define X_INCLUDE_DIRENT_H
|
|
#define XOS_USE_XT_LOCKING
|
|
#include <X11/Xos_r.h>
|
|
#include <Dt/DtP.h>
|
|
#include <Dt/Connect.h>
|
|
#include <Dt/FileUtil.h>
|
|
#include <Dt/DtNlUtils.h>
|
|
#include <Dt/Action.h>
|
|
#include <Dt/ActionP.h>
|
|
#include <Dt/ActionDbP.h>
|
|
#include <Dt/ActionUtilP.h>
|
|
#include <Dt/DbUtil.h>
|
|
#include <Dt/Utility.h>
|
|
|
|
#include <Dt/ActionDb.h>
|
|
|
|
#ifndef S_ISLNK
|
|
/* This macro is normally defined in stat.h, but not on USL systems. */
|
|
# define S_ISLNK(_M) ((_M & S_IFMT)==S_IFLNK) /* test for symbolic link */
|
|
#endif
|
|
|
|
#ifndef CDE_INSTALLATION_TOP
|
|
#define CDE_INSTALLATION_TOP "/opt/dt"
|
|
#endif
|
|
|
|
#ifndef CDE_CONFIGURATION_TOP
|
|
#define CDE_CONFIGURATION_TOP "/etc/opt/dt"
|
|
#endif
|
|
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
#define FILE_INCREMENT 20
|
|
|
|
/* The following string holds the default value of the Dt database
|
|
* search path. This default search path has the following major
|
|
* components:
|
|
*
|
|
* $HOME/.dt/types[/%L] A location for the user's personal
|
|
* actions and filetypes.
|
|
*
|
|
* <config-location>/appconfig/types[/%L]
|
|
* The DT location for system-wide
|
|
* customizations.
|
|
*
|
|
* <top-of-dt>/types/[%L] The DT location for default
|
|
* system-wide actions and filetypes.
|
|
*/
|
|
static char DTDATABASESEARCHPATH_DEFAULT[] =
|
|
"%s/.dt/types/%%L,"
|
|
"%s/.dt/types,"
|
|
CDE_CONFIGURATION_TOP "/appconfig/types/%%L,"
|
|
CDE_CONFIGURATION_TOP "/appconfig/types,"
|
|
CDE_INSTALLATION_TOP "/appconfig/types/%%L,"
|
|
CDE_INSTALLATION_TOP "/appconfig/types";
|
|
|
|
|
|
/**** Substitution records used by XtFindFile() in _DtExpandLang() ****/
|
|
static SubstitutionRec langSubstitutions[] =
|
|
{
|
|
{'L', (char *)NULL},
|
|
{'l', (char *)NULL},
|
|
{'t', (char *)NULL},
|
|
{'c', (char *)NULL}
|
|
};
|
|
static int nLangSubstitutions = XtNumber(langSubstitutions);
|
|
|
|
|
|
/******** Static Function Declarations ********/
|
|
|
|
static Boolean __testPath(
|
|
String str );
|
|
static void __setupLangSubstitutions(
|
|
void );
|
|
static void __freeLangSubstitutions(
|
|
void );
|
|
static char *_DtExpandLang(
|
|
char *string ) ;
|
|
static char _DtIsDir(
|
|
char *path,
|
|
char *name) ;
|
|
static void _DtFreeDirVector(
|
|
char **dir_vector) ;
|
|
static void __swap(
|
|
int i ,
|
|
DtDirPaths *data );
|
|
static void _DtSortFiles(
|
|
int low,
|
|
int n,
|
|
DtDirPaths *data) ;
|
|
|
|
/******** End Static Function Declarations ********/
|
|
|
|
/******************
|
|
*
|
|
* Function Name: __testPath
|
|
*
|
|
* Description:
|
|
*
|
|
* This function is needed by XtFindFile(). Always returns True.
|
|
*
|
|
* Synopsis:
|
|
*
|
|
* path = XtFindFile(..., __testPath);
|
|
*
|
|
******************/
|
|
|
|
static Boolean
|
|
__testPath(String str)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
/******************
|
|
*
|
|
* Function Name: __setupLangSubstitutions
|
|
*
|
|
* Description:
|
|
*
|
|
* This function initializes langSubstitutions[] for use by
|
|
* XtFindFile().
|
|
*
|
|
* Synopsis:
|
|
*
|
|
* __setupLangSubstitutions();
|
|
*
|
|
******************/
|
|
|
|
static void
|
|
__setupLangSubstitutions(void)
|
|
{
|
|
char *lang;
|
|
char *languagePart;
|
|
char *territoryPart;
|
|
char *codesetPart;
|
|
char *tlPtr, *ttPtr, *tcPtr, *endPtr;
|
|
|
|
/*
|
|
* We should really be calling setlocale to determine the "default"
|
|
* locale but setlocale's return value is not standardized across
|
|
* the various vendor platforms nor is it consistent within differnt
|
|
* revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
|
|
* HP-UX 10.0). The "right" call would be the following line:
|
|
*
|
|
* if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
|
|
*
|
|
* Here we hard code the default to "C" instead of leaving it NULL.
|
|
*/
|
|
languagePart = territoryPart = codesetPart = (char *)NULL;
|
|
if ((lang = getenv ("LANG")) == (char *)NULL)
|
|
lang = "C";
|
|
|
|
lang = XtNewString(lang); /* free'd in __freeLangSubstitutions() */
|
|
|
|
tlPtr = lang;
|
|
endPtr = (char *)NULL;
|
|
if ((ttPtr = DtStrchr(tlPtr, '_')) != (char *)NULL)
|
|
ttPtr++;
|
|
|
|
if ((tcPtr = DtStrchr(ttPtr ? ttPtr : tlPtr, '.')) != (char *)NULL)
|
|
{
|
|
endPtr = tcPtr++;
|
|
if (*tcPtr != '\0')
|
|
codesetPart =
|
|
XtNewString(tcPtr); /* free'd in __freeLangSubstitutions() */
|
|
}
|
|
|
|
if (ttPtr)
|
|
{
|
|
if (endPtr)
|
|
{
|
|
int ttLen = endPtr - ttPtr;
|
|
|
|
if (ttLen > 0)
|
|
{
|
|
/* free'd in __freeLangSubstitutions() */
|
|
territoryPart = (char *)XtMalloc((ttLen + 1) * sizeof(char));
|
|
strncpy(territoryPart, ttPtr, ttLen);
|
|
territoryPart[ttLen] = '\0';
|
|
}
|
|
}
|
|
else territoryPart =
|
|
XtNewString(ttPtr); /* free'd in __freeLangSubstitutions() */
|
|
|
|
endPtr = ttPtr - 1;
|
|
}
|
|
|
|
if (endPtr)
|
|
{
|
|
int tlLen = endPtr - tlPtr;
|
|
|
|
if (tlLen > 0)
|
|
{
|
|
/* free'd in __freeLangSubstitutions() */
|
|
languagePart = (char *)XtMalloc((tlLen + 1) * sizeof(char));
|
|
strncpy(languagePart, tlPtr, tlLen);
|
|
languagePart[tlLen] = '\0';
|
|
}
|
|
}
|
|
else languagePart =
|
|
XtNewString(tlPtr); /* free'd in __freeLangSubstitutions() */
|
|
|
|
langSubstitutions[0].substitution = lang;
|
|
langSubstitutions[1].substitution = languagePart;
|
|
langSubstitutions[2].substitution = territoryPart;
|
|
langSubstitutions[3].substitution = codesetPart;
|
|
}
|
|
|
|
/******************
|
|
*
|
|
* Function Name: __freeLangSubstitutions
|
|
*
|
|
* Description:
|
|
*
|
|
* This function free's the strings allocated by
|
|
* __setupLangSubstitutions and placed into langSubstitutions[]
|
|
*
|
|
* Synopsis:
|
|
*
|
|
* __freeLangSubstitutions();
|
|
*
|
|
******************/
|
|
|
|
static void
|
|
__freeLangSubstitutions(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < nLangSubstitutions; i++)
|
|
XtFree(langSubstitutions[i].substitution);
|
|
}
|
|
|
|
/******************
|
|
*
|
|
* Function Name: _DtExpandLang
|
|
*
|
|
* Description:
|
|
*
|
|
* This function takes the string "string", and performs the following
|
|
* replacements:
|
|
* %L : contents of LANG environment variable.
|
|
* %l : language part of the LANG environment variable.
|
|
* %t : territory part of the LANG environment variable.
|
|
* %c : codeset part of the LANG environment variable.
|
|
* %% : % (e.g. %%L would be replaced by %L, and
|
|
* no substitution would be performed on %L)
|
|
*
|
|
* If $LANG is not defined, the $LANG is assumed to be "C".
|
|
*
|
|
* Synopsis:
|
|
*
|
|
* ret_string = _DtExpandLang (string);
|
|
*
|
|
* char *ret_string; Returns NULL if "string" is NULL, or it points
|
|
* to the expanded string.
|
|
*
|
|
* char *string; The comma-separated pathnames to expand.
|
|
*
|
|
* Note: The caller is responsible for free'ing the returned string.
|
|
*
|
|
******************/
|
|
|
|
static char *
|
|
_DtExpandLang(
|
|
char *string )
|
|
{
|
|
char *thisPath;
|
|
char *newPath;
|
|
char *modPath;
|
|
int pathLen, maxPathLen;
|
|
int nColons;
|
|
char *tmpPtr, *tmpPtr1;
|
|
char *newString;
|
|
char *tokPtr;
|
|
|
|
if (string == NULL)
|
|
return (NULL);
|
|
|
|
/*
|
|
* We're going to use XtFindFile() to perform the replacements;
|
|
* the colon character ':' is used as a delimiter in XtFindFile,
|
|
* so we escape all colon characters in our string before
|
|
* passing it along.
|
|
*/
|
|
for (nColons = 0, tmpPtr = string;
|
|
(tmpPtr = DtStrchr(tmpPtr, ':')) != (char *)NULL;
|
|
nColons++, tmpPtr++)
|
|
/* EMPTY */
|
|
;
|
|
|
|
newString =
|
|
(char *)XtCalloc(1, (strlen(string) + nColons + 1) * sizeof(char));
|
|
for (tmpPtr = string;
|
|
(tmpPtr1 = DtStrchr(tmpPtr, ':')) != (char *)NULL;
|
|
tmpPtr = tmpPtr1 + 1)
|
|
{
|
|
strncat(newString, tmpPtr, tmpPtr1 - tmpPtr);
|
|
strcat(newString, "%:");
|
|
}
|
|
strcat(newString, tmpPtr);
|
|
|
|
__setupLangSubstitutions();
|
|
|
|
/*
|
|
* XtFindFile() assumes that the string into which it's making
|
|
* substitutions is a path, and therefore it assumes that the
|
|
* length of the string does not exceed MAXPATHLEN. Since
|
|
* our string is a series of paths, it CAN exceed MAXPATHLEN.
|
|
* So, we split our string into individual paths which we then
|
|
* pass off to XtFindFile().
|
|
*/
|
|
pathLen = maxPathLen = 0;
|
|
newPath = (char *)NULL;
|
|
for (thisPath = DtStrtok_r(newString, ",", &tokPtr);
|
|
thisPath != (char *)NULL;
|
|
thisPath = DtStrtok_r((char *)NULL, ",", &tokPtr))
|
|
{
|
|
modPath = XtFindFile(thisPath, langSubstitutions,
|
|
nLangSubstitutions, __testPath);
|
|
if (modPath)
|
|
{
|
|
char *origPath = modPath;
|
|
int modLen;
|
|
|
|
/*
|
|
* For some reason, XtFindFile() collapses all '/'
|
|
* characters EXCEPT at the beginning of the path!
|
|
* For backwards compatibility, we collapse those here.
|
|
*/
|
|
if (*modPath == '/')
|
|
{
|
|
while (*(modPath + 1) == '/')
|
|
modPath++;
|
|
}
|
|
modLen = strlen(modPath);
|
|
|
|
if (pathLen + modLen + 2 > maxPathLen)
|
|
{
|
|
maxPathLen =
|
|
((pathLen + modLen + 2 + MAXPATHLEN) / MAXPATHLEN) *
|
|
MAXPATHLEN;
|
|
newPath =
|
|
(char *)XtRealloc(newPath, maxPathLen * sizeof(char));
|
|
}
|
|
|
|
if (pathLen > 0)
|
|
newPath[pathLen++] = ',';
|
|
strcpy(&(newPath[pathLen]), modPath);
|
|
pathLen += modLen;
|
|
|
|
XtFree(origPath);
|
|
}
|
|
}
|
|
|
|
__freeLangSubstitutions();
|
|
XtFree(newString);
|
|
|
|
return newPath;
|
|
}
|
|
|
|
|
|
/******************
|
|
*
|
|
* Function Name: _DtIsDir
|
|
*
|
|
* Description:
|
|
*
|
|
* This function tests a pathname to see if it is a directory.
|
|
* The path name is received in two pieces, which makes it easy
|
|
* for the calling function to test a bunch of files in a directory
|
|
* to see if any are subdirectories.
|
|
*
|
|
* This function does NOT handle Softbench-style pathnames with
|
|
* embedded hostnames.
|
|
*
|
|
* Synopsis:
|
|
*
|
|
* dir = _DtIsDir (path, name);
|
|
*
|
|
* char dir; Returns 0 if the item is not a directory,
|
|
* 1 if it is.
|
|
* char *path; The first part of the pathname. Typically
|
|
* the directory containing the item of interest.
|
|
* char *name; The second half of the pathname. Typically
|
|
* the name of the item of interest.
|
|
*
|
|
******************/
|
|
|
|
static char
|
|
_DtIsDir(
|
|
char *path,
|
|
char *name )
|
|
{
|
|
struct stat stat_buf;
|
|
char *stat_name;
|
|
|
|
stat_name = XtMalloc ((Cardinal)(strlen(path) + strlen(name) + 2));
|
|
(void)strcpy (stat_name, path);
|
|
(void)strcat (stat_name, "/");
|
|
(void)strcat (stat_name, name);
|
|
|
|
if(stat (stat_name, &stat_buf))
|
|
{
|
|
stat_buf.st_mode = 0;
|
|
}
|
|
XtFree (stat_name);
|
|
|
|
if (stat_buf.st_mode & S_IFDIR)
|
|
return (TRUE);
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
/******************************
|
|
*
|
|
* Function Name: _DtFreeDirVector
|
|
*
|
|
* Description:
|
|
*
|
|
* This function frees a database-directory string vector.
|
|
*
|
|
* Synoposis:
|
|
*
|
|
* FreeDatabaseDirs (dirs);
|
|
*
|
|
* char **dirs; The string vector to free.
|
|
*
|
|
********************************/
|
|
|
|
static void
|
|
_DtFreeDirVector(
|
|
char **dir_vector )
|
|
{
|
|
char **v;
|
|
|
|
if (dir_vector)
|
|
{
|
|
for (v = dir_vector; *v != NULL; v++)
|
|
XtFree ((char *)*v);
|
|
|
|
XtFree ((char *)dir_vector);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************
|
|
*
|
|
* Function Name: __swap
|
|
*
|
|
* Description:
|
|
*
|
|
* This function exchanges two elements in an array of DtDirPaths.
|
|
*
|
|
* Synoposis:
|
|
*
|
|
* __swap (i, data);
|
|
*
|
|
* int i; The base index to change.
|
|
* DtDirPaths *data; The data to change.
|
|
*
|
|
********************************/
|
|
|
|
static void
|
|
__swap(
|
|
int i ,
|
|
DtDirPaths *data )
|
|
{
|
|
char *tmp;
|
|
|
|
/* The "names" field of the structure is not touched because
|
|
* this field is "NULL" for all of the entries.
|
|
*/
|
|
tmp = data->dirs[i];
|
|
data->dirs[i] = data->dirs[i+1]; data->dirs[i+1] = tmp;
|
|
|
|
tmp = data->paths[i];
|
|
data->paths[i] = data->paths[i+1]; data->paths[i+1] = tmp;
|
|
}
|
|
|
|
|
|
/******************************
|
|
*
|
|
* Function Name: _DtSortFiles
|
|
*
|
|
* Description:
|
|
*
|
|
* Given an index, an array of "char" data and the number of elements to
|
|
* sort, this function sorts the data. The sorting algorithm is based
|
|
* on a bubble sort because the number of elements is usually less than
|
|
* ten.
|
|
*
|
|
* Synoposis:
|
|
*
|
|
* _DtSortFiles (index, n, data);
|
|
*
|
|
* int low; The base of the array to begin the sorting.
|
|
* int n; The number of elements to sort.
|
|
* DtDirPaths *data; The data to sort.
|
|
*
|
|
********************************/
|
|
|
|
static void
|
|
_DtSortFiles(
|
|
int low,
|
|
int n,
|
|
DtDirPaths *data )
|
|
{
|
|
int i, j;
|
|
int high = low + n;
|
|
|
|
/*
|
|
* This sorting routine needs to be able to sort any portion of
|
|
* an array - it does not always start at element '0'.
|
|
*/
|
|
|
|
for (i = low; i < (high - 1); i++)
|
|
for (j = low; j < (high - 1); j++)
|
|
#ifndef NO_MESSAGE_CATALOG
|
|
if ((strcoll (data->paths[j], data->paths[j+1])) > 0)
|
|
#else
|
|
if ((strcmp (data->paths[j], data->paths[j+1])) > 0)
|
|
#endif
|
|
__swap (j, data);
|
|
}
|
|
|
|
|
|
/******************
|
|
*
|
|
* Function Name: _DtFindMatchingFiles
|
|
*
|
|
* Description:
|
|
*
|
|
* This function takes a string vector of directory names (which
|
|
* are in "host:/path/file" format) and a filename suffix and
|
|
* finds all of the files in those directories with the specified
|
|
* suffix. It returns a string vector of the filenames.
|
|
*
|
|
* You will typically first call _DtGetDatabaseDirPaths() to get the
|
|
* 'dirs' info.
|
|
*
|
|
* Use _DtFreeDatabaseDirPaths() to free up the return structure.
|
|
*
|
|
* Synopsis:
|
|
*
|
|
* filev = _DtFindMatchingFiles (dirs, suffix, sort_files);
|
|
*
|
|
* DtDirPaths *filev; A structure containing the names
|
|
* of all the files that were found.
|
|
* DtDirPaths *dirs; A structure of directories to be
|
|
* searched.
|
|
* char *suffix; The suffix string which is compared
|
|
* to the end of the filenames. This
|
|
* string must contain a "." if it is
|
|
* part of the suffix you want to match
|
|
* on (e.g. ".c").
|
|
* Boolean sort_files; Should the files within a directory be sorted.
|
|
*
|
|
*
|
|
******************/
|
|
|
|
DtDirPaths *
|
|
_DtFindMatchingFiles(
|
|
DtDirPaths *dirs,
|
|
char *suffix,
|
|
Boolean sort_files )
|
|
{
|
|
/* LOCAL VARIABLES */
|
|
|
|
register DtDirPaths *files; /* An array of pointers to the filenames which
|
|
have been found. */
|
|
int max_files; /* The total number of filenames that can be
|
|
stored in the "files" array before it must
|
|
be reallocd. */
|
|
int num_found; /* The number of files which have been found. */
|
|
register DIR *dirp; /* Variables for walking through the directory
|
|
entries. */
|
|
char * next_file;
|
|
struct dirent *dp = NULL;
|
|
char *file_suffix;
|
|
int suffixLen, nameLen;
|
|
int nextIndex;
|
|
register char * next_path;
|
|
int files_in_this_directory;
|
|
int base;
|
|
|
|
_Xreaddirparams dirEntryBuf;
|
|
struct dirent *result;
|
|
|
|
/* CODE */
|
|
if (dirs == NULL)
|
|
return(NULL);
|
|
|
|
files = (DtDirPaths *) XtMalloc((Cardinal)(sizeof(DtDirPaths)));
|
|
files->dirs = (char **) XtMalloc(sizeof(char *) * FILE_INCREMENT);
|
|
files->paths = (char **) XtMalloc(sizeof(char *) * FILE_INCREMENT);
|
|
max_files = FILE_INCREMENT;
|
|
num_found = 0;
|
|
nextIndex = 0;
|
|
|
|
/* Process each one of the directories in priority order. */
|
|
while (dirs->paths[nextIndex] != NULL) {
|
|
|
|
next_path = dirs->paths[nextIndex];
|
|
dirp = opendir (next_path);
|
|
base = num_found;
|
|
|
|
files_in_this_directory = 0;
|
|
while ((result = _XReaddir(dirp, dirEntryBuf)) != NULL) {
|
|
|
|
/* Check the name to see if it matches the suffix and is
|
|
a file. */
|
|
if (strlen (result->d_name) >= strlen(suffix))
|
|
{
|
|
/* Find the end of the name and compare it to the suffix. */
|
|
/* Get the number of chars (not bytes) in each string */
|
|
suffixLen = DtCharCount(suffix);
|
|
nameLen = DtCharCount(result->d_name);
|
|
file_suffix = _DtGetNthChar(result->d_name, nameLen - suffixLen);
|
|
if (file_suffix && (strcmp(file_suffix, suffix) == 0) &&
|
|
!_DtIsDir((char *)next_path, (char *)result->d_name))
|
|
{
|
|
|
|
/* The file is a match. See if there is room in the array
|
|
or whether we need to realloc. The "-1" is to save room
|
|
for the terminating NULL pointer. */
|
|
if (num_found == max_files - 1) {
|
|
files->dirs = (char **) XtRealloc ((char *)files->dirs,
|
|
(Cardinal)(sizeof(char *) * (max_files + FILE_INCREMENT)));
|
|
files->paths = (char **) XtRealloc ((char *)files->paths,
|
|
(Cardinal)(sizeof(char *) * (max_files + FILE_INCREMENT)));
|
|
max_files += FILE_INCREMENT;
|
|
}
|
|
|
|
/* Get some memory and copy the filename to the array. */
|
|
files->dirs[num_found] = next_file = (char *)
|
|
XtMalloc((Cardinal)(strlen(dirs->dirs[nextIndex]) +
|
|
strlen (result->d_name) + 2));
|
|
(void)strcpy(next_file, dirs->dirs[nextIndex]);
|
|
(void)strcat(next_file, "/");
|
|
(void)strcat(next_file, result->d_name);
|
|
|
|
files->paths[num_found] = next_file = (char *)
|
|
XtMalloc((Cardinal)(strlen(next_path) +
|
|
strlen (result->d_name) + 2));
|
|
(void)strcpy(next_file, next_path);
|
|
(void)strcat(next_file, "/");
|
|
(void)strcat(next_file, result->d_name);
|
|
|
|
num_found++;
|
|
files_in_this_directory++;
|
|
|
|
}
|
|
}
|
|
}
|
|
closedir (dirp);
|
|
if (sort_files && (files_in_this_directory > 1))
|
|
_DtSortFiles (base, files_in_this_directory, files);
|
|
nextIndex++;
|
|
}
|
|
files->dirs[num_found] = NULL;
|
|
files->paths[num_found] = NULL;
|
|
return (files);
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* _DtDbGetDataBaseEnv( )
|
|
* ------------------------
|
|
* This function provides a PRIVATE API for internal manipulation of the
|
|
* DTDATABASEDIRPATH environment variable before loading the databases.
|
|
* -- used by the front panel code in dtwm.
|
|
*
|
|
* If the environment variable it returns a default path.
|
|
*
|
|
* NOTE: This function returns a freshly malloc'ed string. It is up to
|
|
* the caller to free it.
|
|
*
|
|
******************************************************************************/
|
|
|
|
char *
|
|
_DtDbGetDataBaseEnv( void )
|
|
{
|
|
char *nwh_dir;
|
|
char *temp_buf;
|
|
char *temp_s;
|
|
|
|
nwh_dir = getenv ("HOME");
|
|
/*
|
|
* Get the DTDATABASESEARCHPATH environment variable. If it is not set,
|
|
* create the default value.
|
|
*/
|
|
if ( temp_s = getenv ("DTDATABASESEARCHPATH"))
|
|
if ( *temp_s != 0 ) return XtNewString(temp_s);
|
|
|
|
temp_buf =
|
|
XtMalloc((2*strlen(nwh_dir)) + strlen(DTDATABASESEARCHPATH_DEFAULT) + 1);
|
|
sprintf (temp_buf, DTDATABASESEARCHPATH_DEFAULT, nwh_dir, nwh_dir);
|
|
return temp_buf;
|
|
|
|
}
|
|
|
|
/******************************
|
|
*
|
|
* Function Name: _DtGetDatabaseDirPaths
|
|
*
|
|
* Description:
|
|
*
|
|
* This function returns a structure containing the external
|
|
* and internal forms for all of the database directories that must be
|
|
* searched for Dt database files.
|
|
* The structure is freed using _DtFreeDatabaseDirPaths().
|
|
*
|
|
* The directories are all guaranteed to be fully-specified names;
|
|
* i.e. host:/path/dir.
|
|
*
|
|
* THIS IS TYPICALLY CALLED BEFORE USING ANY OF THE FOLLOWING:
|
|
*
|
|
* DtReadDatabases()
|
|
* DtPrepareToolboxDirs()
|
|
* _DtDbRead()
|
|
* _DtFindMatchingFiles()
|
|
*
|
|
* Synoposis:
|
|
*
|
|
* DtDirPaths * _DtGetDatabaseDirPaths ();
|
|
*
|
|
********************************/
|
|
|
|
DtDirPaths *
|
|
_DtGetDatabaseDirPaths( void )
|
|
{
|
|
XrmValue resource_value;
|
|
char *rep_type;
|
|
char *dir_string, *remote_hosts;
|
|
char *nwh_host; /* Holds the host portion of the user's
|
|
network-home. */
|
|
char **dir_vector; /* The list of directories are turned into
|
|
a vector of strings. This points to the
|
|
start of the vector. */
|
|
char **hosts_vector;
|
|
char **next_dir; /* A pointer used to walk through dir_vector. */
|
|
char **next_host;
|
|
char *dir; /* Points to next dir being processed */
|
|
int valid_dirs; /* A count of the number of valid directories
|
|
found. */
|
|
char *home;
|
|
char *nextc;
|
|
DtDirPaths * ret_paths;
|
|
char * internal;
|
|
int i;
|
|
char *tmp_dir_string;
|
|
|
|
/* Get our host name, and the user's home directory */
|
|
nwh_host = _DtGetLocalHostName ();
|
|
tmp_dir_string = _DtDbGetDataBaseEnv();
|
|
dir_string = _DtExpandLang (tmp_dir_string);
|
|
XtFree (tmp_dir_string);
|
|
|
|
/* Prepare the input vector and the two output vectors. */
|
|
dir_vector = _DtVectorizeInPlace (dir_string, ',');
|
|
ret_paths = (DtDirPaths *)XtMalloc(sizeof(DtDirPaths));
|
|
ret_paths->dirs = NULL;
|
|
ret_paths->paths = NULL;
|
|
valid_dirs = 0;
|
|
|
|
for (next_dir = dir_vector; *next_dir != NULL; next_dir++) {
|
|
|
|
if (DtStrchr (*next_dir, '/') == NULL){
|
|
/* It must be a relative path. */
|
|
/* Ignore relative paths */
|
|
continue;
|
|
}
|
|
|
|
/* If the name is not a valid directory, get rid of it. */
|
|
if (!_DtIsOpenableDirContext (*next_dir, &internal)) {
|
|
continue;
|
|
}
|
|
else {
|
|
/* If not already in the list, add it to the structure. */
|
|
for (i = 0; i < valid_dirs; i++)
|
|
{
|
|
if (strcmp(ret_paths->paths[i], internal) == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == valid_dirs)
|
|
{
|
|
valid_dirs++;
|
|
ret_paths->dirs = (char **) XtRealloc ((char *)ret_paths->dirs,
|
|
(Cardinal) (sizeof (char *) * valid_dirs));
|
|
|
|
/* Make sure the directory name is fully-qualified with a host
|
|
component. */
|
|
if (DtStrchr (*next_dir, ':') != NULL)
|
|
dir = XtNewString(*next_dir);
|
|
|
|
/* If there is no host component, see if there is
|
|
an absolute path. */
|
|
else if (
|
|
#ifdef NLS16
|
|
(!is_multibyte || (mblen(*next_dir, MB_LEN_MAX) == 1)) &&
|
|
#endif
|
|
(**next_dir == '/')) {
|
|
dir = XtMalloc ((Cardinal) (strlen (nwh_host) + 2 +
|
|
strlen (*next_dir)));
|
|
(void) sprintf (dir, "%s:%s", nwh_host, *next_dir);
|
|
}
|
|
else
|
|
dir = XtNewString(*next_dir);
|
|
|
|
ret_paths->dirs[valid_dirs - 1] = dir;
|
|
ret_paths->paths = (char **) XtRealloc ((char *)ret_paths->paths,
|
|
(Cardinal) (sizeof (char *) * valid_dirs));
|
|
ret_paths->paths[valid_dirs - 1] = internal;
|
|
}
|
|
else {
|
|
XtFree(internal);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* The three vectors must be NULL terminated. */
|
|
ret_paths->dirs = (char **) XtRealloc ((char *)ret_paths->dirs,
|
|
(Cardinal) (sizeof (char *) *
|
|
(valid_dirs + 1)));
|
|
ret_paths->dirs[valid_dirs] = NULL;
|
|
ret_paths->paths = (char **) XtRealloc ((char *)ret_paths->paths,
|
|
(Cardinal) (sizeof (char *) *
|
|
(valid_dirs + 1)));
|
|
ret_paths->paths[valid_dirs] = NULL;
|
|
|
|
XtFree ((char *) dir_string);
|
|
XtFree ((char *) nwh_host);
|
|
XtFree ((char *) dir_vector);
|
|
return(ret_paths);
|
|
}
|
|
|
|
|
|
/***************************
|
|
* void _DtFreeDatabaseDirPaths (paths)
|
|
*
|
|
* DtDirPaths * paths;
|
|
*
|
|
* This function will free up each of the arrays within the directory
|
|
* information structure, and will then free the structure itself.
|
|
*
|
|
**************************/
|
|
|
|
void
|
|
_DtFreeDatabaseDirPaths(
|
|
DtDirPaths *paths )
|
|
{
|
|
_DtFreeDirVector(paths->dirs);
|
|
_DtFreeDirVector(paths->paths);
|
|
XtFree((char *)paths);
|
|
}
|
|
|