DbUtil.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * $TOG: DbUtil.c /main/13 1998/04/09 17:47:56 mgreess $
  25. *
  26. * (c) Copyright 1988, 1989, 1990, 1991, 1992, 1993
  27. * by Hewlett-Packard Company, all rights reserved.
  28. *
  29. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  30. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  31. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  32. * (c) Copyright 1993, 1994 Novell, Inc. *
  33. */
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <sys/types.h>
  37. #include <dirent.h>
  38. #include <ctype.h>
  39. #include <string.h>
  40. #ifdef NLS16
  41. #include <limits.h>
  42. #endif
  43. #include <sys/stat.h>
  44. #include <sys/param.h> /* MAXPATHLEN, MAXHOSTNAMELEN */
  45. #include <X11/Xlib.h>
  46. #include <X11/Intrinsic.h>
  47. #include <X11/StringDefs.h>
  48. #define X_INCLUDE_DIRENT_H
  49. #define XOS_USE_XT_LOCKING
  50. #include <X11/Xos_r.h>
  51. #include <Dt/DtP.h>
  52. #include <Dt/Connect.h>
  53. #include <Dt/FileUtil.h>
  54. #include <Dt/DtNlUtils.h>
  55. #include <Dt/Action.h>
  56. #include <Dt/ActionP.h>
  57. #include <Dt/ActionDbP.h>
  58. #include <Dt/ActionUtilP.h>
  59. #include <Dt/DbUtil.h>
  60. #include <Dt/Utility.h>
  61. #include <Dt/ActionDb.h>
  62. #ifndef S_ISLNK
  63. /* This macro is normally defined in stat.h, but not on USL systems. */
  64. # define S_ISLNK(_M) ((_M & S_IFMT)==S_IFLNK) /* test for symbolic link */
  65. #endif
  66. #ifndef CDE_INSTALLATION_TOP
  67. #define CDE_INSTALLATION_TOP "/opt/dt"
  68. #endif
  69. #ifndef CDE_CONFIGURATION_TOP
  70. #define CDE_CONFIGURATION_TOP "/etc/opt/dt"
  71. #endif
  72. #define TRUE 1
  73. #define FALSE 0
  74. #define FILE_INCREMENT 20
  75. /* The following string holds the default value of the Dt database
  76. * search path. This default search path has the following major
  77. * components:
  78. *
  79. * $HOME/.dt/types[/%L] A location for the user's personal
  80. * actions and filetypes.
  81. *
  82. * <config-location>/appconfig/types[/%L]
  83. * The DT location for system-wide
  84. * customizations.
  85. *
  86. * <top-of-dt>/types/[%L] The DT location for default
  87. * system-wide actions and filetypes.
  88. */
  89. static char DTDATABASESEARCHPATH_DEFAULT[] =
  90. "%s/.dt/types/%%L,"
  91. "%s/.dt/types,"
  92. CDE_CONFIGURATION_TOP "/appconfig/types/%%L,"
  93. CDE_CONFIGURATION_TOP "/appconfig/types,"
  94. CDE_INSTALLATION_TOP "/appconfig/types/%%L,"
  95. CDE_INSTALLATION_TOP "/appconfig/types";
  96. /**** Substitution records used by XtFindFile() in _DtExpandLang() ****/
  97. static SubstitutionRec langSubstitutions[] =
  98. {
  99. {'L', (char *)NULL},
  100. {'l', (char *)NULL},
  101. {'t', (char *)NULL},
  102. {'c', (char *)NULL}
  103. };
  104. static int nLangSubstitutions = XtNumber(langSubstitutions);
  105. /******** Static Function Declarations ********/
  106. static Boolean __testPath(
  107. String str );
  108. static void __setupLangSubstitutions(
  109. void );
  110. static void __freeLangSubstitutions(
  111. void );
  112. static char *_DtExpandLang(
  113. char *string ) ;
  114. static char _DtIsDir(
  115. char *path,
  116. char *name) ;
  117. static void _DtFreeDirVector(
  118. char **dir_vector) ;
  119. static void __swap(
  120. int i ,
  121. DtDirPaths *data );
  122. static void _DtSortFiles(
  123. int low,
  124. int n,
  125. DtDirPaths *data) ;
  126. /******** End Static Function Declarations ********/
  127. /******************
  128. *
  129. * Function Name: __testPath
  130. *
  131. * Description:
  132. *
  133. * This function is needed by XtFindFile(). Always returns True.
  134. *
  135. * Synopsis:
  136. *
  137. * path = XtFindFile(..., __testPath);
  138. *
  139. ******************/
  140. static Boolean
  141. __testPath(String str)
  142. {
  143. return True;
  144. }
  145. /******************
  146. *
  147. * Function Name: __setupLangSubstitutions
  148. *
  149. * Description:
  150. *
  151. * This function initializes langSubstitutions[] for use by
  152. * XtFindFile().
  153. *
  154. * Synopsis:
  155. *
  156. * __setupLangSubstitutions();
  157. *
  158. ******************/
  159. static void
  160. __setupLangSubstitutions(void)
  161. {
  162. char *lang;
  163. char *languagePart;
  164. char *territoryPart;
  165. char *codesetPart;
  166. char *tlPtr, *ttPtr, *tcPtr, *endPtr;
  167. /*
  168. * We should really be calling setlocale to determine the "default"
  169. * locale but setlocale's return value is not standardized across
  170. * the various vendor platforms nor is it consistent within differnt
  171. * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
  172. * HP-UX 10.0). The "right" call would be the following line:
  173. *
  174. * if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
  175. *
  176. * Here we hard code the default to "C" instead of leaving it NULL.
  177. */
  178. languagePart = territoryPart = codesetPart = (char *)NULL;
  179. if ((lang = getenv ("LANG")) == (char *)NULL)
  180. lang = "C";
  181. lang = XtNewString(lang); /* free'd in __freeLangSubstitutions() */
  182. tlPtr = lang;
  183. endPtr = (char *)NULL;
  184. if ((ttPtr = DtStrchr(tlPtr, '_')) != (char *)NULL)
  185. ttPtr++;
  186. if ((tcPtr = DtStrchr(ttPtr ? ttPtr : tlPtr, '.')) != (char *)NULL)
  187. {
  188. endPtr = tcPtr++;
  189. if (*tcPtr != '\0')
  190. codesetPart =
  191. XtNewString(tcPtr); /* free'd in __freeLangSubstitutions() */
  192. }
  193. if (ttPtr)
  194. {
  195. if (endPtr)
  196. {
  197. int ttLen = endPtr - ttPtr;
  198. if (ttLen > 0)
  199. {
  200. /* free'd in __freeLangSubstitutions() */
  201. territoryPart = (char *)XtMalloc((ttLen + 1) * sizeof(char));
  202. strncpy(territoryPart, ttPtr, ttLen);
  203. territoryPart[ttLen] = '\0';
  204. }
  205. }
  206. else territoryPart =
  207. XtNewString(ttPtr); /* free'd in __freeLangSubstitutions() */
  208. endPtr = ttPtr - 1;
  209. }
  210. if (endPtr)
  211. {
  212. int tlLen = endPtr - tlPtr;
  213. if (tlLen > 0)
  214. {
  215. /* free'd in __freeLangSubstitutions() */
  216. languagePart = (char *)XtMalloc((tlLen + 1) * sizeof(char));
  217. strncpy(languagePart, tlPtr, tlLen);
  218. languagePart[tlLen] = '\0';
  219. }
  220. }
  221. else languagePart =
  222. XtNewString(tlPtr); /* free'd in __freeLangSubstitutions() */
  223. langSubstitutions[0].substitution = lang;
  224. langSubstitutions[1].substitution = languagePart;
  225. langSubstitutions[2].substitution = territoryPart;
  226. langSubstitutions[3].substitution = codesetPart;
  227. }
  228. /******************
  229. *
  230. * Function Name: __freeLangSubstitutions
  231. *
  232. * Description:
  233. *
  234. * This function free's the strings allocated by
  235. * __setupLangSubstitutions and placed into langSubstitutions[]
  236. *
  237. * Synopsis:
  238. *
  239. * __freeLangSubstitutions();
  240. *
  241. ******************/
  242. static void
  243. __freeLangSubstitutions(void)
  244. {
  245. int i;
  246. for (i = 0; i < nLangSubstitutions; i++)
  247. XtFree(langSubstitutions[i].substitution);
  248. }
  249. /******************
  250. *
  251. * Function Name: _DtExpandLang
  252. *
  253. * Description:
  254. *
  255. * This function takes the string "string", and performs the following
  256. * replacements:
  257. * %L : contents of LANG environment variable.
  258. * %l : language part of the LANG environment variable.
  259. * %t : territory part of the LANG environment variable.
  260. * %c : codeset part of the LANG environment variable.
  261. * %% : % (e.g. %%L would be replaced by %L, and
  262. * no substitution would be performed on %L)
  263. *
  264. * If $LANG is not defined, the $LANG is assumed to be "C".
  265. *
  266. * Synopsis:
  267. *
  268. * ret_string = _DtExpandLang (string);
  269. *
  270. * char *ret_string; Returns NULL if "string" is NULL, or it points
  271. * to the expanded string.
  272. *
  273. * char *string; The comma-separated pathnames to expand.
  274. *
  275. * Note: The caller is responsible for free'ing the returned string.
  276. *
  277. ******************/
  278. static char *
  279. _DtExpandLang(
  280. char *string )
  281. {
  282. char *thisPath;
  283. char *newPath;
  284. char *modPath;
  285. int pathLen, maxPathLen;
  286. int nColons;
  287. char *tmpPtr, *tmpPtr1;
  288. char *newString;
  289. char *tokPtr;
  290. if (string == NULL)
  291. return (NULL);
  292. /*
  293. * We're going to use XtFindFile() to perform the replacements;
  294. * the colon character ':' is used as a delimiter in XtFindFile,
  295. * so we escape all colon characters in our string before
  296. * passing it along.
  297. */
  298. for (nColons = 0, tmpPtr = string;
  299. (tmpPtr = DtStrchr(tmpPtr, ':')) != (char *)NULL;
  300. nColons++, tmpPtr++)
  301. /* EMPTY */
  302. ;
  303. newString =
  304. (char *)XtCalloc(1, (strlen(string) + nColons + 1) * sizeof(char));
  305. for (tmpPtr = string;
  306. (tmpPtr1 = DtStrchr(tmpPtr, ':')) != (char *)NULL;
  307. tmpPtr = tmpPtr1 + 1)
  308. {
  309. strncat(newString, tmpPtr, tmpPtr1 - tmpPtr);
  310. strcat(newString, "%:");
  311. }
  312. strcat(newString, tmpPtr);
  313. __setupLangSubstitutions();
  314. /*
  315. * XtFindFile() assumes that the string into which it's making
  316. * substitutions is a path, and therefore it assumes that the
  317. * length of the string does not exceed MAXPATHLEN. Since
  318. * our string is a series of paths, it CAN exceed MAXPATHLEN.
  319. * So, we split our string into individual paths which we then
  320. * pass off to XtFindFile().
  321. */
  322. pathLen = maxPathLen = 0;
  323. newPath = (char *)NULL;
  324. for (thisPath = DtStrtok_r(newString, ",", &tokPtr);
  325. thisPath != (char *)NULL;
  326. thisPath = DtStrtok_r((char *)NULL, ",", &tokPtr))
  327. {
  328. modPath = XtFindFile(thisPath, langSubstitutions,
  329. nLangSubstitutions, __testPath);
  330. if (modPath)
  331. {
  332. char *origPath = modPath;
  333. int modLen;
  334. /*
  335. * For some reason, XtFindFile() collapses all '/'
  336. * characters EXCEPT at the beginning of the path!
  337. * For backwards compatibility, we collapse those here.
  338. */
  339. if (*modPath == '/')
  340. {
  341. while (*(modPath + 1) == '/')
  342. modPath++;
  343. }
  344. modLen = strlen(modPath);
  345. if (pathLen + modLen + 2 > maxPathLen)
  346. {
  347. maxPathLen =
  348. ((pathLen + modLen + 2 + MAXPATHLEN) / MAXPATHLEN) *
  349. MAXPATHLEN;
  350. newPath =
  351. (char *)XtRealloc(newPath, maxPathLen * sizeof(char));
  352. }
  353. if (pathLen > 0)
  354. newPath[pathLen++] = ',';
  355. strcpy(&(newPath[pathLen]), modPath);
  356. pathLen += modLen;
  357. XtFree(origPath);
  358. }
  359. }
  360. __freeLangSubstitutions();
  361. XtFree(newString);
  362. return newPath;
  363. }
  364. /******************
  365. *
  366. * Function Name: _DtIsDir
  367. *
  368. * Description:
  369. *
  370. * This function tests a pathname to see if it is a directory.
  371. * The path name is received in two pieces, which makes it easy
  372. * for the calling function to test a bunch of files in a directory
  373. * to see if any are subdirectories.
  374. *
  375. * This function does NOT handle Softbench-style pathnames with
  376. * embedded hostnames.
  377. *
  378. * Synopsis:
  379. *
  380. * dir = _DtIsDir (path, name);
  381. *
  382. * char dir; Returns 0 if the item is not a directory,
  383. * 1 if it is.
  384. * char *path; The first part of the pathname. Typically
  385. * the directory containing the item of interest.
  386. * char *name; The second half of the pathname. Typically
  387. * the name of the item of interest.
  388. *
  389. ******************/
  390. static char
  391. _DtIsDir(
  392. char *path,
  393. char *name )
  394. {
  395. struct stat stat_buf;
  396. char *stat_name;
  397. stat_name = XtMalloc ((Cardinal)(strlen(path) + strlen(name) + 2));
  398. (void)strcpy (stat_name, path);
  399. (void)strcat (stat_name, "/");
  400. (void)strcat (stat_name, name);
  401. if(stat (stat_name, &stat_buf))
  402. {
  403. stat_buf.st_mode = 0;
  404. }
  405. XtFree (stat_name);
  406. if (stat_buf.st_mode & S_IFDIR)
  407. return (TRUE);
  408. else
  409. return (FALSE);
  410. }
  411. /******************************
  412. *
  413. * Function Name: _DtFreeDirVector
  414. *
  415. * Description:
  416. *
  417. * This function frees a database-directory string vector.
  418. *
  419. * Synoposis:
  420. *
  421. * FreeDatabaseDirs (dirs);
  422. *
  423. * char **dirs; The string vector to free.
  424. *
  425. ********************************/
  426. static void
  427. _DtFreeDirVector(
  428. char **dir_vector )
  429. {
  430. char **v;
  431. if (dir_vector)
  432. {
  433. for (v = dir_vector; *v != NULL; v++)
  434. XtFree ((char *)*v);
  435. XtFree ((char *)dir_vector);
  436. }
  437. }
  438. /******************************
  439. *
  440. * Function Name: __swap
  441. *
  442. * Description:
  443. *
  444. * This function exchanges two elements in an array of DtDirPaths.
  445. *
  446. * Synoposis:
  447. *
  448. * __swap (i, data);
  449. *
  450. * int i; The base index to change.
  451. * DtDirPaths *data; The data to change.
  452. *
  453. ********************************/
  454. static void
  455. __swap(
  456. int i ,
  457. DtDirPaths *data )
  458. {
  459. char *tmp;
  460. /* The "names" field of the structure is not touched because
  461. * this field is "NULL" for all of the entries.
  462. */
  463. tmp = data->dirs[i];
  464. data->dirs[i] = data->dirs[i+1]; data->dirs[i+1] = tmp;
  465. tmp = data->paths[i];
  466. data->paths[i] = data->paths[i+1]; data->paths[i+1] = tmp;
  467. }
  468. /******************************
  469. *
  470. * Function Name: _DtSortFiles
  471. *
  472. * Description:
  473. *
  474. * Given an index, an array of "char" data and the number of elements to
  475. * sort, this function sorts the data. The sorting algorithm is based
  476. * on a bubble sort because the number of elements is usually less than
  477. * ten.
  478. *
  479. * Synoposis:
  480. *
  481. * _DtSortFiles (index, n, data);
  482. *
  483. * int low; The base of the array to begin the sorting.
  484. * int n; The number of elements to sort.
  485. * DtDirPaths *data; The data to sort.
  486. *
  487. ********************************/
  488. static void
  489. _DtSortFiles(
  490. int low,
  491. int n,
  492. DtDirPaths *data )
  493. {
  494. int i, j;
  495. int high = low + n;
  496. /*
  497. * This sorting routine needs to be able to sort any portion of
  498. * an array - it does not always start at element '0'.
  499. */
  500. for (i = low; i < (high - 1); i++)
  501. for (j = low; j < (high - 1); j++)
  502. #ifndef NO_MESSAGE_CATALOG
  503. if ((strcoll (data->paths[j], data->paths[j+1])) > 0)
  504. #else
  505. if ((strcmp (data->paths[j], data->paths[j+1])) > 0)
  506. #endif
  507. __swap (j, data);
  508. }
  509. /******************
  510. *
  511. * Function Name: _DtFindMatchingFiles
  512. *
  513. * Description:
  514. *
  515. * This function takes a string vector of directory names (which
  516. * are in "host:/path/file" format) and a filename suffix and
  517. * finds all of the files in those directories with the specified
  518. * suffix. It returns a string vector of the filenames.
  519. *
  520. * You will typically first call _DtGetDatabaseDirPaths() to get the
  521. * 'dirs' info.
  522. *
  523. * Use _DtFreeDatabaseDirPaths() to free up the return structure.
  524. *
  525. * Synopsis:
  526. *
  527. * filev = _DtFindMatchingFiles (dirs, suffix, sort_files);
  528. *
  529. * DtDirPaths *filev; A structure containing the names
  530. * of all the files that were found.
  531. * DtDirPaths *dirs; A structure of directories to be
  532. * searched.
  533. * char *suffix; The suffix string which is compared
  534. * to the end of the filenames. This
  535. * string must contain a "." if it is
  536. * part of the suffix you want to match
  537. * on (e.g. ".c").
  538. * Boolean sort_files; Should the files within a directory be sorted.
  539. *
  540. *
  541. ******************/
  542. DtDirPaths *
  543. _DtFindMatchingFiles(
  544. DtDirPaths *dirs,
  545. char *suffix,
  546. Boolean sort_files )
  547. {
  548. /* LOCAL VARIABLES */
  549. DtDirPaths *files; /* An array of pointers to the filenames which
  550. have been found. */
  551. int max_files; /* The total number of filenames that can be
  552. stored in the "files" array before it must
  553. be reallocd. */
  554. int num_found; /* The number of files which have been found. */
  555. DIR *dirp; /* Variables for walking through the directory
  556. entries. */
  557. char * next_file;
  558. struct dirent *dp = NULL;
  559. char *file_suffix;
  560. int suffixLen, nameLen;
  561. int nextIndex;
  562. char * next_path;
  563. int files_in_this_directory;
  564. int base;
  565. _Xreaddirparams dirEntryBuf;
  566. struct dirent *result;
  567. /* CODE */
  568. if (dirs == NULL)
  569. return(NULL);
  570. files = (DtDirPaths *) XtMalloc((Cardinal)(sizeof(DtDirPaths)));
  571. files->dirs = (char **) XtMalloc(sizeof(char *) * FILE_INCREMENT);
  572. files->paths = (char **) XtMalloc(sizeof(char *) * FILE_INCREMENT);
  573. max_files = FILE_INCREMENT;
  574. num_found = 0;
  575. nextIndex = 0;
  576. /* Process each one of the directories in priority order. */
  577. while (dirs->paths[nextIndex] != NULL) {
  578. next_path = dirs->paths[nextIndex];
  579. dirp = opendir (next_path);
  580. base = num_found;
  581. files_in_this_directory = 0;
  582. while ((result = _XReaddir(dirp, dirEntryBuf)) != NULL) {
  583. /* Check the name to see if it matches the suffix and is
  584. a file. */
  585. if (strlen (result->d_name) >= strlen(suffix))
  586. {
  587. /* Find the end of the name and compare it to the suffix. */
  588. /* Get the number of chars (not bytes) in each string */
  589. suffixLen = DtCharCount(suffix);
  590. nameLen = DtCharCount(result->d_name);
  591. file_suffix = _DtGetNthChar(result->d_name, nameLen - suffixLen);
  592. if (file_suffix && (strcmp(file_suffix, suffix) == 0) &&
  593. !_DtIsDir((char *)next_path, (char *)result->d_name))
  594. {
  595. /* The file is a match. See if there is room in the array
  596. or whether we need to realloc. The "-1" is to save room
  597. for the terminating NULL pointer. */
  598. if (num_found == max_files - 1) {
  599. files->dirs = (char **) XtRealloc ((char *)files->dirs,
  600. (Cardinal)(sizeof(char *) * (max_files + FILE_INCREMENT)));
  601. files->paths = (char **) XtRealloc ((char *)files->paths,
  602. (Cardinal)(sizeof(char *) * (max_files + FILE_INCREMENT)));
  603. max_files += FILE_INCREMENT;
  604. }
  605. /* Get some memory and copy the filename to the array. */
  606. files->dirs[num_found] = next_file = (char *)
  607. XtMalloc((Cardinal)(strlen(dirs->dirs[nextIndex]) +
  608. strlen (result->d_name) + 2));
  609. (void)strcpy(next_file, dirs->dirs[nextIndex]);
  610. (void)strcat(next_file, "/");
  611. (void)strcat(next_file, result->d_name);
  612. files->paths[num_found] = next_file = (char *)
  613. XtMalloc((Cardinal)(strlen(next_path) +
  614. strlen (result->d_name) + 2));
  615. (void)strcpy(next_file, next_path);
  616. (void)strcat(next_file, "/");
  617. (void)strcat(next_file, result->d_name);
  618. num_found++;
  619. files_in_this_directory++;
  620. }
  621. }
  622. }
  623. closedir (dirp);
  624. if (sort_files && (files_in_this_directory > 1))
  625. _DtSortFiles (base, files_in_this_directory, files);
  626. nextIndex++;
  627. }
  628. files->dirs[num_found] = NULL;
  629. files->paths[num_found] = NULL;
  630. return (files);
  631. }
  632. /******************************************************************************
  633. *
  634. * _DtDbGetDataBaseEnv( )
  635. * ------------------------
  636. * This function provides a PRIVATE API for internal manipulation of the
  637. * DTDATABASEDIRPATH environment variable before loading the databases.
  638. * -- used by the front panel code in dtwm.
  639. *
  640. * If the environment variable it returns a default path.
  641. *
  642. * NOTE: This function returns a freshly malloc'ed string. It is up to
  643. * the caller to free it.
  644. *
  645. ******************************************************************************/
  646. char *
  647. _DtDbGetDataBaseEnv( void )
  648. {
  649. char *nwh_dir;
  650. char *temp_buf;
  651. char *temp_s;
  652. int slen = 0;
  653. nwh_dir = getenv ("HOME");
  654. /*
  655. * Get the DTDATABASESEARCHPATH environment variable. If it is not set,
  656. * create the default value.
  657. */
  658. if (( temp_s = getenv ("DTDATABASESEARCHPATH")))
  659. if ( *temp_s != 0 ) return XtNewString(temp_s);
  660. slen = (2 * strlen(nwh_dir)) + strlen(DTDATABASESEARCHPATH_DEFAULT) + 1;
  661. temp_buf = XtCalloc(1, slen);
  662. snprintf (temp_buf, slen - 1,
  663. DTDATABASESEARCHPATH_DEFAULT, nwh_dir, nwh_dir);
  664. return temp_buf;
  665. }
  666. /******************************
  667. *
  668. * Function Name: _DtGetDatabaseDirPaths
  669. *
  670. * Description:
  671. *
  672. * This function returns a structure containing the external
  673. * and internal forms for all of the database directories that must be
  674. * searched for Dt database files.
  675. * The structure is freed using _DtFreeDatabaseDirPaths().
  676. *
  677. * The directories are all guaranteed to be fully-specified names;
  678. * i.e. host:/path/dir.
  679. *
  680. * THIS IS TYPICALLY CALLED BEFORE USING ANY OF THE FOLLOWING:
  681. *
  682. * DtReadDatabases()
  683. * DtPrepareToolboxDirs()
  684. * _DtDbRead()
  685. * _DtFindMatchingFiles()
  686. *
  687. * Synoposis:
  688. *
  689. * DtDirPaths * _DtGetDatabaseDirPaths ();
  690. *
  691. ********************************/
  692. DtDirPaths *
  693. _DtGetDatabaseDirPaths( void )
  694. {
  695. XrmValue resource_value;
  696. char *rep_type;
  697. char *dir_string, *remote_hosts;
  698. char *nwh_host; /* Holds the host portion of the user's
  699. network-home. */
  700. char **dir_vector; /* The list of directories are turned into
  701. a vector of strings. This points to the
  702. start of the vector. */
  703. char **hosts_vector;
  704. char **next_dir; /* A pointer used to walk through dir_vector. */
  705. char **next_host;
  706. char *dir; /* Points to next dir being processed */
  707. int valid_dirs; /* A count of the number of valid directories
  708. found. */
  709. char *home;
  710. char *nextc;
  711. DtDirPaths * ret_paths;
  712. char * internal;
  713. int i;
  714. char *tmp_dir_string;
  715. /* Get our host name, and the user's home directory */
  716. nwh_host = _DtGetLocalHostName ();
  717. tmp_dir_string = _DtDbGetDataBaseEnv();
  718. dir_string = _DtExpandLang (tmp_dir_string);
  719. XtFree (tmp_dir_string);
  720. /* Prepare the input vector and the two output vectors. */
  721. dir_vector = _DtVectorizeInPlace (dir_string, ',');
  722. ret_paths = (DtDirPaths *)XtMalloc(sizeof(DtDirPaths));
  723. ret_paths->dirs = NULL;
  724. ret_paths->paths = NULL;
  725. valid_dirs = 0;
  726. for (next_dir = dir_vector; *next_dir != NULL; next_dir++) {
  727. if (DtStrchr (*next_dir, '/') == NULL){
  728. /* It must be a relative path. */
  729. /* Ignore relative paths */
  730. continue;
  731. }
  732. /* If the name is not a valid directory, get rid of it. */
  733. if (!_DtIsOpenableDirContext (*next_dir, &internal)) {
  734. continue;
  735. }
  736. else {
  737. /* If not already in the list, add it to the structure. */
  738. for (i = 0; i < valid_dirs; i++)
  739. {
  740. if (strcmp(ret_paths->paths[i], internal) == 0)
  741. {
  742. break;
  743. }
  744. }
  745. if (i == valid_dirs)
  746. {
  747. valid_dirs++;
  748. ret_paths->dirs = (char **) XtRealloc ((char *)ret_paths->dirs,
  749. (Cardinal) (sizeof (char *) * valid_dirs));
  750. /* Make sure the directory name is fully-qualified with a host
  751. component. */
  752. if (DtStrchr (*next_dir, ':') != NULL)
  753. dir = XtNewString(*next_dir);
  754. /* If there is no host component, see if there is
  755. an absolute path. */
  756. else if (
  757. #ifdef NLS16
  758. (!is_multibyte || (mblen(*next_dir, MB_LEN_MAX) == 1)) &&
  759. #endif
  760. (**next_dir == '/')) {
  761. dir = XtMalloc ((Cardinal) (strlen (nwh_host) + 2 +
  762. strlen (*next_dir)));
  763. (void) sprintf (dir, "%s:%s", nwh_host, *next_dir);
  764. }
  765. else
  766. dir = XtNewString(*next_dir);
  767. ret_paths->dirs[valid_dirs - 1] = dir;
  768. ret_paths->paths = (char **) XtRealloc ((char *)ret_paths->paths,
  769. (Cardinal) (sizeof (char *) * valid_dirs));
  770. ret_paths->paths[valid_dirs - 1] = internal;
  771. }
  772. else {
  773. XtFree(internal);
  774. }
  775. }
  776. }
  777. /* The three vectors must be NULL terminated. */
  778. ret_paths->dirs = (char **) XtRealloc ((char *)ret_paths->dirs,
  779. (Cardinal) (sizeof (char *) *
  780. (valid_dirs + 1)));
  781. ret_paths->dirs[valid_dirs] = NULL;
  782. ret_paths->paths = (char **) XtRealloc ((char *)ret_paths->paths,
  783. (Cardinal) (sizeof (char *) *
  784. (valid_dirs + 1)));
  785. ret_paths->paths[valid_dirs] = NULL;
  786. XtFree ((char *) dir_string);
  787. XtFree ((char *) nwh_host);
  788. XtFree ((char *) dir_vector);
  789. return(ret_paths);
  790. }
  791. /***************************
  792. * void _DtFreeDatabaseDirPaths (paths)
  793. *
  794. * DtDirPaths * paths;
  795. *
  796. * This function will free up each of the arrays within the directory
  797. * information structure, and will then free the structure itself.
  798. *
  799. **************************/
  800. void
  801. _DtFreeDatabaseDirPaths(
  802. DtDirPaths *paths )
  803. {
  804. _DtFreeDirVector(paths->dirs);
  805. _DtFreeDirVector(paths->paths);
  806. XtFree((char *)paths);
  807. }