DtEnvMap.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  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. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  25. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  26. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  27. * (c) Copyright 1993, 1994 Novell, Inc. *
  28. */
  29. /******************************************************************************
  30. ******************************************************************************
  31. **
  32. ** DtEnvMap.c
  33. **
  34. ** $TOG: DtEnvMap.c /main/7 1998/07/30 12:11:59 mgreess $
  35. **
  36. ** Map the path elements of environment strings as specified by yet
  37. ** another environment string from the local host to a remote host.
  38. ** When possible, cache the results since filename mapping is expensive.
  39. **
  40. ** DTENVMAPFORREMOTE="NAME1[:NAME2[...]]"
  41. **
  42. ** NAME1=path1:path2
  43. ** NAME2=path3:path4:...
  44. **
  45. ******************************************************************************
  46. *****************************************************************************/
  47. #define X_INCLUDE_STRING_H
  48. #define XOS_USE_XT_LOCKING
  49. #include <X11/Xos_r.h>
  50. #include <DtNlUtils.h>
  51. #include <Tt/tt_c.h>
  52. #include "DtSvcLock.h"
  53. /******************************************************************************
  54. ******************************************************************************
  55. **
  56. ** Data Structures and Defines.
  57. **
  58. **/
  59. /**********************************************************
  60. *
  61. * What to map...
  62. *
  63. * ... is specified by either an environment variable or
  64. * a global X resource. If present, the X resource acts
  65. * globally, and is referred to on every attempt to map.
  66. * If an environment variable is set, it overrides the X
  67. * resource setting, thereby allowing for local control
  68. * of individual process threads (by way of propagated
  69. * environments).
  70. */
  71. #define _DTENV_MAP_RESOURCE_NAME "dtEnvMapForRemote"
  72. #define _DTENV_MAP_RESOURCE_CLASS "DtEnvMapForRemote"
  73. #define _DTENV_MAP_ENV_VAR "DTENVMAPFORREMOTE"
  74. /**********************************************************
  75. *
  76. * The primary caching/mapping data structures.
  77. */
  78. typedef struct {
  79. char *localEnvVarPtr; /* original ptr, used for restoring */
  80. char *localEnvVarCopy; /* eg, /users/foo:/usr/bar */
  81. char *mappedEnvVarPtr; /* eg, PATH=/nfs/.../foo:/nfs/.../bar */
  82. } cachedEnvVar;
  83. typedef struct {
  84. char *remoteHost; /* host to map env vars to */
  85. int cacheHit; /* usage rate for this mapping info */
  86. char *mapListStr; /* copy of DTENVMAPFORREMOTE=... */
  87. int mapListCnt; /* how many _real_ env vars to map */
  88. char **mapList; /* simple list of env var names to map*/
  89. cachedEnvVar *mapListDetails; /* list of map info per env var name */
  90. } cacheForTargetHost;
  91. /*
  92. * Cache information. Keep mapping information for MAX_HOSTS_CACHED
  93. * targetHosts.
  94. */
  95. #define MAX_HOSTS_CACHED 8
  96. static cacheForTargetHost cachePoolG[MAX_HOSTS_CACHED];
  97. /*
  98. * Track the most recent targetHost.
  99. */
  100. static char *mostRecentRemoteHostG;
  101. /**********************************************************
  102. *
  103. * Misc defines.
  104. *
  105. * To reduce malloc calls when creating lists, malloc
  106. * "list" in blocks:
  107. *
  108. * char *list[0..15 , 16..31, 32..63, ...]
  109. */
  110. #define MALLOC_BUMP_SIZE 16
  111. #define freeAndNull(ptr) if (ptr) free(ptr); ptr = NULL;
  112. #define ttfreeAndNull(ptr) if (ptr) tt_free(ptr); ptr = NULL;
  113. /**********************************************************
  114. *
  115. * Functionality hooks.
  116. *
  117. * - _DTENV_SUPPORT_COMMA_SEPARATED - turn on code that
  118. * special cases some environment variables and
  119. * treats them as comma separated and possibly
  120. * host qualified.
  121. *
  122. * - _DTENV_SUPPORT_MAPERROR_CACHING - turn on code that
  123. * would cache error codes when mapping files in
  124. * addition to caching successfully mapped files.
  125. * In configurations where mapping errors are
  126. * common, this could be a big help, but on the
  127. * downside, a mapping error that is the result
  128. * of a temporary network error (for example)
  129. * could get locked into a cache.
  130. *
  131. * - _DTENV_OPTIMIZATION_LOCALHOST - turn on code that
  132. * would prevent even trying to map/cache environment
  133. * variables if the targetHost was the localhost.
  134. */
  135. #define _DTENV_SUPPORT_COMMA_SEPARATED 1
  136. #undef _DTENV_SUPPORT_MAPERROR_CACHING
  137. #undef _DTENV_OPTIMIZATION_LOCALHOST
  138. /**********************************************************
  139. *
  140. * Performance hooks.
  141. *
  142. * - DTENV_PERF_HOOK - instrunment file mapping code for
  143. * performance measuring.
  144. */
  145. #undef DTENV_PERF_HOOK
  146. #ifdef DTENV_PERF_HOOK
  147. #include <time.h>
  148. int stopwatch_repeat_rate = 10;
  149. unsigned long stopwatch_tt_file_netfile;
  150. unsigned long stopwatch_tt_netfile_file;
  151. #endif /* DTENV_PERF_HOOK */
  152. /******************************************************************************
  153. ******************************************************************************
  154. **
  155. ** _DtEnv_tt_file_netfile()
  156. ** _DtEnv_tt_netfile_file()
  157. **
  158. ** Both are caching versions built on the non-caching Tooltalk versions.
  159. **
  160. ** The one flaw in both is that if the filesystem topology changes
  161. ** (eg, NFS mounts, symlinks, etc), old and incorrect mapping information
  162. ** may be returned. To minimize this, a cached mapping will only be used
  163. ** so many times before being recomputed. An alternative (not implemented
  164. ** here) would be to recompute based on age of the mapping via
  165. ** gettimeofday().
  166. **
  167. ** ******************* XXX Alert **************************
  168. **
  169. ** Tooltalk currently allocates a range of char*'s
  170. ** and then associates them with a range of error
  171. ** messages (ala tt_ptr_error()). In effect, the
  172. ** allocated char*'s become constants within Tooltalk.
  173. **
  174. ** This code takes this into account when returning
  175. ** values. Non-reserved char*'s are strdup()ed
  176. ** often, while reserved char*'s are not to preserve
  177. ** their ptr value.
  178. **
  179. ** tjg: Other than differing cache repositories, all the onion-skin
  180. ** routines below look the same. Probably better to have one
  181. ** core routine to minimize code size.
  182. **/
  183. /*
  184. * Per cache setup (ie, one for _DtEnv_tt_file_netfile(), one for
  185. * _DtEnv_tt_netfile_file()), start off by caching SIZE_START
  186. * mappings, growing by SIZE_BUMP as needed, while limiting the
  187. * total cache growth to SIZE_MAX mappings.
  188. */
  189. #define CACHE_FILEFRAG_SIZE_START 15
  190. #define CACHE_FILEFRAG_SIZE_BUMP 15
  191. #define CACHE_FILEFRAG_SIZE_MAX 45
  192. /*
  193. * After a cached mapping is used REMAP_AFTER times, age it out
  194. * and force a recomputation of the mapping from scratch.
  195. */
  196. #define CACHE_FILEFRAG_REMAP_AFTER 25
  197. /*
  198. * After RESET_PRI hits on a cache of size SIZE_MAX, reset all
  199. * cacheHit counters. This will allow new mappings to work into
  200. * the cache against mappings that might have been popular long
  201. * ago.
  202. */
  203. #define CACHE_FILEFRAG_RESET_PRI 200
  204. /******************************************************************************
  205. *
  206. * _DtEnv_tt_file_netfile()
  207. *
  208. * A caching version of tt_file_netfile().
  209. */
  210. typedef struct {
  211. char *pathFragOrig; /* eg, /usr/dt */
  212. char *pathFragMapped; /* eg, <from tt_file_netfile> */
  213. int cacheHit; /* usage of */
  214. } cachedFileFrag;
  215. char *_DtEnv_tt_file_netfile(
  216. const char *filename)
  217. {
  218. static int first_time = 1;
  219. static int fragListAvail = CACHE_FILEFRAG_SIZE_START;
  220. static int fragListCnt = 0;
  221. static cachedFileFrag *fragList;
  222. static int cacheGen = 0;
  223. static int hitIdxStart = 0;
  224. char *netpath;
  225. int hitval, hitIdx, i;
  226. cachedFileFrag *tmpCffP;
  227. char *tmpStr;
  228. int newCount = fragListCnt;
  229. _DtSvcProcessLock();
  230. if (first_time) {
  231. fragList = (cachedFileFrag *) calloc( fragListAvail,
  232. sizeof(cachedFileFrag) );
  233. first_time = 0;
  234. }
  235. /*
  236. * Take care of the obvious.
  237. */
  238. if (!filename) {
  239. _DtSvcProcessUnlock();
  240. return( (char *) NULL );
  241. }
  242. /*
  243. * Look for existing answer in cache.
  244. *
  245. * While at it, also look for least used entry just in case.
  246. */
  247. if (fragListCnt)
  248. hitIdxStart = (hitIdxStart + 7) % fragListCnt;
  249. else
  250. hitIdxStart = 0;
  251. hitIdx = hitIdxStart;
  252. hitval = fragList[hitIdx].cacheHit;
  253. tmpCffP = fragList; /* walk rather than index */
  254. for ( i = 0; i < fragListCnt; i++ ) {
  255. if (tmpCffP->cacheHit && !strcmp( filename, tmpCffP->pathFragOrig ) ) {
  256. break;
  257. }
  258. if (tmpCffP->cacheHit < hitval) {
  259. hitIdx = i;
  260. hitval = tmpCffP->cacheHit;
  261. }
  262. tmpCffP++;
  263. }
  264. /*
  265. * Decide what was found.
  266. */
  267. if ( i != fragListCnt ) {
  268. /*
  269. * Found a cached entry.
  270. */
  271. hitIdx = i;
  272. if ( fragList[hitIdx].cacheHit++ > CACHE_FILEFRAG_REMAP_AFTER ) {
  273. /*
  274. * This looks like an old entry, so re-compute it.
  275. */
  276. freeAndNull( fragList[hitIdx].pathFragOrig );
  277. ttfreeAndNull( fragList[hitIdx].pathFragMapped );
  278. fragList[hitIdx].cacheHit = 0; /* 0 means remap below */
  279. }
  280. }
  281. else {
  282. /*
  283. * Did not find a cache entry, so scrounge around for
  284. * a new entry.
  285. */
  286. if ( fragListCnt < fragListAvail ) {
  287. /*
  288. * Use next already-malloc'ed cacheEntry.
  289. */
  290. hitIdx = fragListCnt;
  291. newCount = fragListCnt + 1;
  292. }
  293. else if ( fragListCnt < CACHE_FILEFRAG_SIZE_MAX ) {
  294. /*
  295. * Can grow fragList[]
  296. */
  297. fragListAvail += CACHE_FILEFRAG_SIZE_BUMP;
  298. fragList = (cachedFileFrag *) realloc( (char *) fragList,
  299. sizeof(cachedFileFrag) * fragListAvail);
  300. /*
  301. * Zero out new memory.
  302. */
  303. memset( fragList + (fragListAvail-CACHE_FILEFRAG_SIZE_BUMP),
  304. 0, CACHE_FILEFRAG_SIZE_BUMP*sizeof(cachedFileFrag) );
  305. hitIdx = fragListCnt;
  306. newCount = fragListCnt + 1;
  307. }
  308. else {
  309. /*
  310. * Last resort - bump out the least used entry.
  311. */
  312. freeAndNull( fragList[hitIdx].pathFragOrig );
  313. ttfreeAndNull( fragList[hitIdx].pathFragMapped );
  314. /*
  315. * Since the cache is 100% full, occasionally reset
  316. * everyone's cacheHit rate so entries that were only
  317. * popular long ago don't get locked in.
  318. */
  319. if ( cacheGen++ > CACHE_FILEFRAG_RESET_PRI ) {
  320. cacheGen = 0;
  321. tmpCffP = fragList;
  322. for ( i = 0; i < fragListCnt; i++ ) {
  323. tmpCffP->cacheHit = 1;
  324. tmpCffP++;
  325. }
  326. }
  327. }
  328. fragList[hitIdx].cacheHit = 0; /* 0 means remap below */
  329. }
  330. if ( ! fragList[hitIdx].cacheHit ) {
  331. /*
  332. * Need to perform mapping.
  333. */
  334. netpath = tt_file_netfile( filename );
  335. #ifdef _DTENV_SUPPORT_MAPERROR_CACHING
  336. fragList[hitIdx].pathFragOrig = strdup( filename );
  337. fragList[hitIdx].cacheHit = 1;
  338. fragList[hitIdx].pathFragMapped = netpath;
  339. fragListCnt = newCount;
  340. #else
  341. if ( tt_ptr_error(netpath) == TT_OK ) {
  342. fragList[hitIdx].pathFragOrig = strdup( filename );
  343. fragList[hitIdx].cacheHit = 1;
  344. fragList[hitIdx].pathFragMapped = netpath;
  345. /*
  346. * Only change the count if we are successful in adding
  347. * a new entry.
  348. */
  349. fragListCnt = newCount;
  350. }
  351. else {
  352. /*
  353. * Don't cache errors. Leave this cache slot empty
  354. * and it will be rediscovered and used in the future.
  355. */
  356. fragList[hitIdx].cacheHit = 0;
  357. /*
  358. * Do not change the fragListCount since we don't want to
  359. * add in error entries.
  360. */
  361. }
  362. #endif /* _DTENV_SUPPORT_MAPERROR_CACHING */
  363. }
  364. /*
  365. * Dig out answer and return it.
  366. */
  367. #ifdef _DTENV_SUPPORT_MAPERROR_CACHING
  368. if ( tt_ptr_error(netpath) == TT_OK )
  369. #else
  370. if ( fragList[hitIdx].cacheHit )
  371. #endif /* _DTENV_SUPPORT_MAPERROR_CACHING */
  372. {
  373. /*
  374. * Return a tt_free-able copy of the answer.
  375. */
  376. tmpStr = tt_malloc( strlen(fragList[hitIdx].pathFragMapped) + 1 );
  377. strcpy( tmpStr, fragList[hitIdx].pathFragMapped );
  378. _DtSvcProcessUnlock();
  379. return(tmpStr);
  380. }
  381. else {
  382. /*
  383. * See XXX comment.
  384. *
  385. * Since netpath is an error code, return as is.
  386. */
  387. _DtSvcProcessUnlock();
  388. return(netpath);
  389. }
  390. }
  391. /******************************************************************************
  392. *
  393. * _DtEnv_tt_netfile_file()
  394. *
  395. * A caching version of tt_netfile_file().
  396. */
  397. typedef struct {
  398. char *targetHost;
  399. char *pathFragOrig; /* eg, <from tt_file_netfile> */
  400. char *pathFragMapped; /* eg, /nfs/hostb/usr/dt */
  401. int cacheHit; /* usage of */
  402. } cachedNetfileFrag;
  403. char *_DtEnv_tt_host_netfile_file(
  404. const char *host,
  405. const char *filename)
  406. {
  407. static int first_time = 1;
  408. static int fragListAvail = CACHE_FILEFRAG_SIZE_START;
  409. static int fragListCnt = 0;
  410. static cachedNetfileFrag *fragList;
  411. static int cacheGen = 0;
  412. static int hitIdxStart = 0;
  413. char *newfile;
  414. int hitval, hitIdx, i;
  415. cachedNetfileFrag *tmpCffP;
  416. char *tmpStr;
  417. int newCount = fragListCnt;
  418. _DtSvcProcessLock();
  419. if (first_time) {
  420. fragList = (cachedNetfileFrag *) calloc( fragListAvail,
  421. sizeof(cachedNetfileFrag) );
  422. first_time = 0;
  423. }
  424. /*
  425. * Take care of the obvious.
  426. */
  427. if (!filename) {
  428. _DtSvcProcessUnlock();
  429. return( (char *) NULL );
  430. }
  431. if (!host) {
  432. /*
  433. * Return a tt_free-able un-mapped copy.
  434. */
  435. tmpStr = tt_malloc( strlen(filename) + 1 );
  436. strcpy( tmpStr, filename );
  437. _DtSvcProcessUnlock();
  438. return(tmpStr);
  439. }
  440. /*
  441. * Look for existing answer in cache.
  442. *
  443. * While at it, also look for least used entry just in case.
  444. */
  445. if (fragListCnt)
  446. hitIdxStart = (hitIdxStart + 7) % fragListCnt;
  447. else
  448. hitIdxStart = 0;
  449. hitIdx = hitIdxStart;
  450. hitval = fragList[hitIdx].cacheHit;
  451. tmpCffP = fragList; /* walk rather than index */
  452. for ( i = 0; i < fragListCnt; i++ ) {
  453. if (tmpCffP->cacheHit && !strcmp( filename, tmpCffP->pathFragOrig ) ) {
  454. if (!strcmp( host, tmpCffP->targetHost ) ) {
  455. break;
  456. }
  457. }
  458. /*
  459. * Save index of least used entry
  460. */
  461. if (tmpCffP->cacheHit < hitval) {
  462. hitIdx = i;
  463. hitval = tmpCffP->cacheHit;
  464. }
  465. tmpCffP++;
  466. }
  467. /*
  468. * Decide what was found.
  469. */
  470. if ( i != fragListCnt ) {
  471. /*
  472. * Found a cached entry.
  473. */
  474. hitIdx = i;
  475. if ( fragList[hitIdx].cacheHit++ > CACHE_FILEFRAG_REMAP_AFTER ) {
  476. /*
  477. * This looks like an old entry, so re-compute it.
  478. */
  479. freeAndNull( fragList[hitIdx].targetHost );
  480. freeAndNull( fragList[hitIdx].pathFragOrig );
  481. ttfreeAndNull( fragList[hitIdx].pathFragMapped );
  482. fragList[hitIdx].cacheHit = 0; /* 0 means remap below */
  483. }
  484. }
  485. else {
  486. /*
  487. * Did not find a cache entry, so scrounge around for
  488. * a new entry.
  489. */
  490. if ( fragListCnt < fragListAvail ) {
  491. /*
  492. * Use next already-malloc'ed cacheEntry.
  493. */
  494. hitIdx = fragListCnt;
  495. newCount = fragListCnt + 1;
  496. }
  497. else if ( fragListCnt < CACHE_FILEFRAG_SIZE_MAX ) {
  498. /*
  499. * Can grow fragList[]
  500. */
  501. fragListAvail += CACHE_FILEFRAG_SIZE_BUMP;
  502. fragList = (cachedNetfileFrag *) realloc( (char *) fragList,
  503. sizeof(cachedNetfileFrag) * fragListAvail);
  504. /*
  505. * Zero out new memory.
  506. */
  507. memset( fragList + (fragListAvail-CACHE_FILEFRAG_SIZE_BUMP),
  508. 0, CACHE_FILEFRAG_SIZE_BUMP*sizeof(cachedNetfileFrag) );
  509. hitIdx = fragListCnt;
  510. newCount = fragListCnt + 1;
  511. }
  512. else {
  513. /*
  514. * Last resort - bump out the least used entry.
  515. */
  516. freeAndNull( fragList[hitIdx].targetHost );
  517. freeAndNull( fragList[hitIdx].pathFragOrig );
  518. ttfreeAndNull( fragList[hitIdx].pathFragMapped );
  519. /*
  520. * Since the cache is 100% full, occasionally reset
  521. * everyone's cacheHit rate so entries that were only
  522. * popular long ago don't get locked in.
  523. */
  524. if ( cacheGen++ > CACHE_FILEFRAG_RESET_PRI ) {
  525. cacheGen = 0;
  526. tmpCffP = fragList;
  527. for ( i = 0; i < fragListCnt; i++ ) {
  528. tmpCffP->cacheHit = 1;
  529. tmpCffP++;
  530. }
  531. }
  532. }
  533. fragList[hitIdx].cacheHit = 0; /* 0 means remap below */
  534. }
  535. if ( ! fragList[hitIdx].cacheHit ) {
  536. /*
  537. * Need to perform mapping.
  538. */
  539. newfile = tt_host_netfile_file( host, filename );
  540. #ifdef _DTENV_SUPPORT_MAPERROR_CACHING
  541. fragList[hitIdx].targetHost = strdup ( host );
  542. fragList[hitIdx].pathFragOrig = strdup( filename );
  543. fragList[hitIdx].cacheHit = 1;
  544. fragList[hitIdx].pathFragMapped = newfile;
  545. fragListCnt = newCount;
  546. #else
  547. if ( tt_ptr_error(newfile) == TT_OK ) {
  548. fragList[hitIdx].targetHost = strdup ( host );
  549. fragList[hitIdx].pathFragOrig = strdup( filename );
  550. fragList[hitIdx].cacheHit = 1;
  551. fragList[hitIdx].pathFragMapped = newfile;
  552. /*
  553. * Only change the count if we are successful in adding
  554. * a new entry.
  555. */
  556. fragListCnt = newCount;
  557. }
  558. else {
  559. /*
  560. * Don't cache errors. Leave this cache slot empty
  561. * and it will be rediscovered and used in the future.
  562. */
  563. fragList[hitIdx].cacheHit = 0;
  564. /*
  565. * Do not change the fragListCount since we are not saving
  566. * error entries.
  567. */
  568. }
  569. #endif /* _DTENV_SUPPORT_MAPERROR_CACHING */
  570. }
  571. /*
  572. * Dig out answer and return it.
  573. */
  574. #ifdef _DTENV_SUPPORT_MAPERROR_CACHING
  575. if ( tt_ptr_error(newfile) == TT_OK )
  576. #else
  577. if ( fragList[hitIdx].cacheHit )
  578. #endif /* _DTENV_SUPPORT_MAPERROR_CACHING */
  579. {
  580. /*
  581. * Return a tt_free-able copy of the answer.
  582. */
  583. tmpStr = tt_malloc( strlen(fragList[hitIdx].pathFragMapped) + 1 );
  584. strcpy( tmpStr, fragList[hitIdx].pathFragMapped );
  585. _DtSvcProcessUnlock();
  586. return(tmpStr);
  587. }
  588. else {
  589. /*
  590. * See XXX comment.
  591. *
  592. * Since newfile is an error code, return as is.
  593. */
  594. _DtSvcProcessUnlock();
  595. return(newfile);
  596. }
  597. }
  598. /******************************************************************************
  599. ******************************************************************************
  600. **
  601. ** Environment variable mapping code.
  602. **
  603. */
  604. /******************************************************************************
  605. *
  606. * _DtEnvGetMapList()
  607. *
  608. * Fetch the environment variable who's value is a colon separated list
  609. * of environment variable names who's values need to be mapped. Then
  610. * break down the list into an indexable array.
  611. */
  612. static char **_DtEnvGetMapList(
  613. char *mapListStr,
  614. int *mapListCount)
  615. {
  616. char **mapList; /* decomposition of above */
  617. char *tmpPtr, *tmpPtr2;
  618. int availListSize;
  619. int firstTime;
  620. _Xstrtokparams strtok_buf;
  621. /*
  622. * Handle NULL mapListStr.
  623. */
  624. *mapListCount = 0;
  625. if ( !mapListStr ) {
  626. return( (char **) NULL );
  627. }
  628. /*
  629. * Create a block of string pointers - remalloc() as needed.
  630. */
  631. availListSize = MALLOC_BUMP_SIZE;
  632. mapList = (char **) malloc( sizeof(char *) * (availListSize) );
  633. /*
  634. * Break up the colon separated string into an indexable array.
  635. */
  636. tmpPtr = strdup(mapListStr); /* work copy for strtok */
  637. firstTime = 1;
  638. while (1) {
  639. if (firstTime) {
  640. tmpPtr2 = _XStrtok( tmpPtr, ":", strtok_buf );
  641. firstTime = 0;
  642. }
  643. else
  644. tmpPtr2 = _XStrtok( (char *) NULL, ":", strtok_buf );
  645. if (tmpPtr2) {
  646. /*
  647. * Have possible env var name to map - make sure it exists.
  648. */
  649. if ( getenv(tmpPtr2) ) {
  650. (*mapListCount)++;
  651. if (*mapListCount > availListSize) {
  652. availListSize += MALLOC_BUMP_SIZE;
  653. mapList = (char **) realloc( (char *) mapList,
  654. sizeof(char *) * (availListSize) );
  655. }
  656. mapList[*mapListCount-1] = strdup(tmpPtr2);
  657. }
  658. }
  659. else {
  660. break;
  661. }
  662. }
  663. free(tmpPtr);
  664. return( (char **) mapList );
  665. }
  666. /******************************************************************************
  667. *
  668. * _DtEnvCleanCacheSlot()
  669. *
  670. * Free up all memory associated with a cache slot for a targetHost.
  671. */
  672. static void _DtEnvCleanCacheSlot( cacheForTargetHost *targetCache )
  673. {
  674. int i;
  675. freeAndNull( targetCache->remoteHost );
  676. targetCache->cacheHit = 1;
  677. freeAndNull( targetCache->mapListStr );
  678. for ( i = 0; i < targetCache->mapListCnt; i++ ) {
  679. freeAndNull( targetCache->mapList[i] );
  680. freeAndNull( targetCache->mapListDetails[i].localEnvVarCopy );
  681. freeAndNull( targetCache->mapListDetails[i].mappedEnvVarPtr );
  682. /* do not free .localEnvVarPtr - belongs to environ */
  683. }
  684. freeAndNull( targetCache->mapList );
  685. targetCache->mapListCnt = 0;
  686. }
  687. /******************************************************************************
  688. *
  689. * _DtEnvGetTargetCache()
  690. *
  691. * For a specified targetHost, find existing cache information and
  692. * optionally create a cache for a targetHost if one doesn't exist.
  693. *
  694. * The define MAX_HOSTS_CACHED controls how many targetHosts can
  695. * be cached.
  696. */
  697. static cacheForTargetHost *_DtEnvGetTargetCache(
  698. char *targetHost,
  699. int createIfNeeded)
  700. {
  701. static int cacheHitGen = 0;
  702. static int hitIdxStart;
  703. int i, hitidx, hitval;
  704. /*
  705. * Handle obvious.
  706. */
  707. if (!targetHost) {
  708. return( (cacheForTargetHost *) NULL );
  709. }
  710. _DtSvcProcessLock();
  711. /*
  712. * Look for targetHost in current cache pool.
  713. */
  714. for ( i = 0; i < MAX_HOSTS_CACHED; i++ ) {
  715. if ( cachePoolG[i].remoteHost ) {
  716. if ( !strcmp( targetHost, cachePoolG[i].remoteHost ) ) {
  717. cachePoolG[i].cacheHit++;
  718. break;
  719. }
  720. }
  721. }
  722. if ( i != MAX_HOSTS_CACHED ) {
  723. /*
  724. * targetHost is in a cache slot already.
  725. */
  726. _DtSvcProcessUnlock();
  727. return( &cachePoolG[i] );
  728. }
  729. else if ( !createIfNeeded ) {
  730. /*
  731. * No cache slot for, and we shouldn't create one either.
  732. */
  733. _DtSvcProcessUnlock();
  734. return( (cacheForTargetHost *) NULL );
  735. }
  736. else {
  737. /*
  738. * Find an empty cache slot or take over a rarely used slot.
  739. */
  740. hitIdxStart = (hitIdxStart + 7) % MAX_HOSTS_CACHED;
  741. hitidx = hitIdxStart;
  742. hitval = cachePoolG[hitidx].cacheHit;
  743. for ( i = 0; i < MAX_HOSTS_CACHED; i++ ) {
  744. if ( ! cachePoolG[i].remoteHost ) {
  745. /*
  746. * Empty slot - take it.
  747. */
  748. hitidx = i;
  749. break;
  750. }
  751. else if ( cachePoolG[i].cacheHit < hitval ) {
  752. hitidx = i;
  753. hitval = cachePoolG[i].cacheHit;
  754. }
  755. }
  756. if ( cachePoolG[hitidx].remoteHost ) {
  757. /*
  758. * Cache was in use, clean first.
  759. */
  760. _DtEnvCleanCacheSlot( &cachePoolG[hitidx] );
  761. cachePoolG[hitidx].remoteHost = strdup( targetHost );
  762. /*
  763. * Since all the slots are full, occasionally reset everyones
  764. * cacheHit counters. This gives new targetHosts a chance
  765. * to compete with targetHosts that were popular long ago.
  766. */
  767. if ( cacheHitGen++ > 50 ) {
  768. for ( i = 0; i < MAX_HOSTS_CACHED; i++ ) {
  769. cachePoolG[i].cacheHit = 1;
  770. }
  771. cacheHitGen = 1;
  772. }
  773. }
  774. _DtSvcProcessUnlock();
  775. return( &cachePoolG[hitidx] );
  776. }
  777. }
  778. /******************************************************************************
  779. *
  780. * _DtEnvMapIt()
  781. *
  782. * Fill out a map cache for a single environment variable.
  783. */
  784. static void _DtEnvMapIt(
  785. char *envVar,
  786. cachedEnvVar *envVarCache,
  787. char *targetHost)
  788. {
  789. char *separator, *tmpPtr, *tmpPtr2, swapout, *netpath;
  790. char *prePend, *postPend, *newPrePend;
  791. char **pathList;
  792. int availPathListSize, pathListCount, availEnvStrSize, len, tmpi, i;
  793. int considerMapping;
  794. _Xstrtokparams strtok_buf;
  795. /*
  796. * Information Layout:
  797. *
  798. * localEnvVarPtr = ptr to original "PATH=/users/foo:/users/bar"
  799. * localEnvVarCopy = copy of original "/users/foo:/users/bar"
  800. * mappedEnvVarPtr = mapped "PATH=/nfs/.../users/foo:/nfs/.../users/bar"
  801. */
  802. if ( (envVarCache->localEnvVarPtr = getenv( envVar )) ) {
  803. envVarCache->localEnvVarCopy = strdup( envVarCache->localEnvVarPtr );
  804. /* sneak back past "NAME=" portion. */
  805. envVarCache->localEnvVarPtr -= strlen( envVar ) + 1;
  806. }
  807. else {
  808. /*
  809. * Nothing to map. Punt.
  810. */
  811. envVarCache->localEnvVarCopy = (char *) NULL;
  812. envVarCache->localEnvVarPtr = (char *) NULL;
  813. return;
  814. }
  815. #ifdef _DTENV_SUPPORT_COMMA_SEPARATED
  816. /*
  817. * Pick between colon-separated and comma-separated host-qualified
  818. * mapping code.
  819. */
  820. if ( !strcmp(envVar, "DTDATABASESEARCHPATH") ) {
  821. /*
  822. * comma-separated and host-qualified mapping.
  823. */
  824. separator = ",";
  825. }
  826. else {
  827. /*
  828. * colon-separated mapping.
  829. */
  830. separator = ":";
  831. }
  832. #else
  833. separator = ":";
  834. #endif /* _DTENV_SUPPORT_COMMA_SEPARATED */
  835. /*
  836. * Break path list into elements
  837. */
  838. availPathListSize = MALLOC_BUMP_SIZE;
  839. pathListCount = 0;
  840. pathList = (char **) malloc( sizeof(char *) * availPathListSize );
  841. /*
  842. * Break up path list into an array of path elements.
  843. */
  844. tmpPtr = strdup( envVarCache->localEnvVarCopy ); /* work copy */
  845. while (1) {
  846. if (!pathListCount)
  847. tmpPtr2 = _XStrtok( tmpPtr, separator, strtok_buf );
  848. else
  849. tmpPtr2 = _XStrtok( (char *) NULL, separator, strtok_buf );
  850. if (tmpPtr2) {
  851. pathListCount++;
  852. if (pathListCount > availPathListSize) {
  853. availPathListSize += MALLOC_BUMP_SIZE;
  854. pathList = (char **) realloc( (char *) pathList,
  855. sizeof(char *) * availPathListSize );
  856. }
  857. pathList[pathListCount-1] = strdup( tmpPtr2 );
  858. }
  859. else {
  860. break;
  861. }
  862. }
  863. free( tmpPtr );
  864. /*
  865. * Setup new "NAME=....." string.
  866. */
  867. availEnvStrSize = strlen( envVar ) + 64;
  868. envVarCache->mappedEnvVarPtr = (char *) calloc( availEnvStrSize, sizeof(char) );
  869. strcpy( envVarCache->mappedEnvVarPtr, envVar );
  870. strcat( envVarCache->mappedEnvVarPtr, "=" );
  871. /*
  872. * Start mapping each path element.
  873. */
  874. for ( i = 0; i < pathListCount; i++ ) {
  875. prePend = pathList[i];
  876. postPend = (char *) NULL;
  877. newPrePend = (char *) NULL;
  878. /*
  879. * Assume we need to map this path element.
  880. */
  881. considerMapping = 1;
  882. #ifdef _DTENV_SUPPORT_COMMA_SEPARATED
  883. if ( !strcmp( separator, "," ) ) {
  884. if ( DtStrchr(prePend, ':' ) ) {
  885. /*
  886. * Host qualified elements in a comma separated list
  887. * will NOT be mapped.
  888. */
  889. considerMapping = 0;
  890. }
  891. }
  892. #endif /* _DTENV_SUPPORT_COMMA_SEPARATED */
  893. if (considerMapping) {
  894. /*
  895. * Tear apart and check for so called substitution characters.
  896. */
  897. if (( tmpPtr = DtStrchr(prePend, '%') )) {
  898. /*
  899. * Temporarly shorten path up to substitution character.
  900. */
  901. swapout = *tmpPtr;
  902. *tmpPtr = '\0';
  903. /*
  904. * Move the dividing point back to a directory element.
  905. */
  906. tmpPtr2 = DtStrrchr( prePend, '/' );
  907. /*
  908. * Restore the send half of the string.
  909. */
  910. *tmpPtr = swapout;
  911. if (tmpPtr2) {
  912. /*
  913. * Can do a split around the "/".
  914. *
  915. * Will have "<prePath>/" and "/<postPath>".
  916. */
  917. postPend = strdup( tmpPtr2 );
  918. *(tmpPtr2 + mblen(tmpPtr2, MB_CUR_MAX)) = '\0';
  919. }
  920. }
  921. #ifdef DTENV_PERF_HOOK
  922. {
  923. int tpi;
  924. extern unsigned long stopwatch_tt_file_netfile;
  925. extern int stopwatch_repeat_rate;
  926. struct timeval start, stop;
  927. struct timezone junk;
  928. gettimeofday( &start, &junk );
  929. for ( tpi = 0; tpi < stopwatch_repeat_rate-1; tpi++ ) {
  930. netpath = _DtEnv_tt_file_netfile( prePend );
  931. if ( tt_ptr_error(netpath) == TT_OK )
  932. ttfreeAndNull( netpath );
  933. }
  934. netpath = _DtEnv_tt_file_netfile( prePend );
  935. gettimeofday( &stop, &junk );
  936. if (start.tv_usec > stop.tv_usec) {
  937. stop.tv_usec += 1000000;
  938. stop.tv_sec--;
  939. }
  940. stopwatch_tt_file_netfile += (stop.tv_usec - start.tv_usec);
  941. stopwatch_tt_file_netfile += (stop.tv_sec - start.tv_sec) * 1000000;
  942. }
  943. #else
  944. netpath = _DtEnv_tt_file_netfile( prePend );
  945. #endif /* DTENV_PERF_HOOK */
  946. if ( tt_ptr_error(netpath) != TT_OK ) {
  947. newPrePend = (char *) NULL;
  948. }
  949. else {
  950. #ifdef DTENV_PERF_HOOK
  951. {
  952. int tpi;
  953. extern unsigned long stopwatch_tt_netfile_file;
  954. extern int stopwatch_repeat_rate;
  955. struct timeval start, stop;
  956. struct timezone junk;
  957. gettimeofday( &start, &junk );
  958. for ( tpi = 0; tpi < stopwatch_repeat_rate-1; tpi++ ) {
  959. newPrePend = _DtEnv_tt_host_netfile_file (targetHost, netpath);
  960. if ( tt_ptr_error(newPrePend) == TT_OK )
  961. ttfreeAndNull( newPrePend );
  962. }
  963. newPrePend = _DtEnv_tt_host_netfile_file (targetHost, netpath);
  964. gettimeofday( &stop, &junk );
  965. if (start.tv_usec > stop.tv_usec) {
  966. stop.tv_usec += 1000000;
  967. stop.tv_sec--;
  968. }
  969. stopwatch_tt_netfile_file += (stop.tv_usec - start.tv_usec);
  970. stopwatch_tt_netfile_file += (stop.tv_sec - start.tv_sec) * 1000000;
  971. }
  972. #else
  973. newPrePend = _DtEnv_tt_host_netfile_file (targetHost, netpath);
  974. #endif /* DTENV_PERF_HOOK */
  975. if ( tt_ptr_error(newPrePend) != TT_OK ) {
  976. newPrePend = (char *) NULL;
  977. }
  978. ttfreeAndNull( netpath );
  979. }
  980. }
  981. /*
  982. * Calculate length of the new path element to the new path list.
  983. */
  984. tmpi = strlen(envVarCache->mappedEnvVarPtr)+1; /* current list + ... */
  985. if ( i != 0 )
  986. tmpi += 1; /* separator */
  987. if (newPrePend)
  988. tmpi += strlen(newPrePend); /* new prePend or ... */
  989. else
  990. tmpi += strlen(prePend); /* ... old prePend */
  991. if (postPend)
  992. tmpi += strlen(postPend); /* new postPend */
  993. if ( tmpi > availEnvStrSize ) {
  994. /*
  995. * Grow new mappedEnvVar space.
  996. */
  997. availEnvStrSize = tmpi + 64;
  998. envVarCache->mappedEnvVarPtr = (char *) realloc(
  999. (char *) envVarCache->mappedEnvVarPtr,
  1000. availEnvStrSize );
  1001. }
  1002. /*
  1003. * Add the new path element.
  1004. */
  1005. if ( i != 0 )
  1006. strcat( envVarCache->mappedEnvVarPtr, separator );
  1007. if (newPrePend)
  1008. strcat( envVarCache->mappedEnvVarPtr, newPrePend );
  1009. else
  1010. strcat( envVarCache->mappedEnvVarPtr, prePend );
  1011. if (postPend)
  1012. strcat( envVarCache->mappedEnvVarPtr, postPend );
  1013. freeAndNull( prePend ); /* aka pathList[i] */
  1014. ttfreeAndNull( newPrePend );
  1015. freeAndNull( postPend );
  1016. }
  1017. freeAndNull( pathList );
  1018. }
  1019. /******************************************************************************
  1020. *
  1021. * _DtEnvGetMapInformation()
  1022. */
  1023. #define _DtEnv_MAX_BUF_SIZE 1024
  1024. #define _DtEnv_NULL_GUARD(s) ((s) ? (s) : "")
  1025. static char *_DtEnvGetMapInformation( void )
  1026. {
  1027. char *mapInfo;
  1028. char nameBuf[_DtEnv_MAX_BUF_SIZE];
  1029. char classBuf[_DtEnv_MAX_BUF_SIZE];
  1030. XrmValue resource_value;
  1031. XrmDatabase db;
  1032. char *rep_type;
  1033. int bytesNeeded;
  1034. char *name;
  1035. char *class;
  1036. extern char *_DtApplicationName; /* set in DtUtil.c */
  1037. extern char *_DtApplicationClass;
  1038. extern Display *_DtDisplay;
  1039. /*
  1040. * See if an environment variable has been set. If so, get
  1041. * the map info from there.
  1042. */
  1043. mapInfo = getenv( _DTENV_MAP_ENV_VAR );
  1044. if (mapInfo)
  1045. return( XtNewString( mapInfo ) );
  1046. /*
  1047. * Try to get map info from the resource database.
  1048. */
  1049. bytesNeeded = strlen(_DTENV_MAP_RESOURCE_NAME)
  1050. + strlen(_DtApplicationName) + 4;
  1051. if ( bytesNeeded > _DtEnv_MAX_BUF_SIZE )
  1052. name = XtMalloc(bytesNeeded);
  1053. else
  1054. name = nameBuf;
  1055. sprintf (name, "%s*%s",
  1056. _DtEnv_NULL_GUARD( _DtApplicationName) , _DTENV_MAP_RESOURCE_NAME);
  1057. bytesNeeded = strlen(_DTENV_MAP_RESOURCE_CLASS)
  1058. + strlen(_DtApplicationClass) + 4;
  1059. if ( bytesNeeded > _DtEnv_MAX_BUF_SIZE )
  1060. class = XtMalloc(bytesNeeded);
  1061. else
  1062. class = classBuf;
  1063. sprintf (class, "%s*%s",
  1064. _DtEnv_NULL_GUARD(_DtApplicationClass) , _DTENV_MAP_RESOURCE_CLASS);
  1065. db = XtDatabase (_DtDisplay);
  1066. if (XrmGetResource (db, nameBuf, classBuf, &rep_type, &resource_value))
  1067. mapInfo = (char *) resource_value.addr;
  1068. else
  1069. mapInfo = (char *) NULL;
  1070. if ( name != nameBuf )
  1071. XtFree(name);
  1072. if ( class != classBuf )
  1073. XtFree(class);
  1074. if (mapInfo)
  1075. return( XtNewString( mapInfo ) );
  1076. else
  1077. return( (char *) NULL );
  1078. }
  1079. /******************************************************************************
  1080. *
  1081. * _DtEnvMapForRemote()
  1082. *
  1083. * Perform filename mapping on the current environment so it makes
  1084. * sense on the target host. The original environment is saved
  1085. * for later restoring, and caching is used to minimize mapping
  1086. * computations.
  1087. */
  1088. void _DtEnvMapForRemote (char *targetHost)
  1089. {
  1090. int i, cacheRegen;
  1091. char *mapListStr, *tmpPtr;
  1092. char **mapList;
  1093. cacheForTargetHost *targetCache;
  1094. int ttMark = 0;
  1095. extern char *mostRecentRemoteHostG;
  1096. _DtSvcProcessLock();
  1097. if (mostRecentRemoteHostG) {
  1098. /*
  1099. * Warning - a _DtEnvRestoreLocal() was not called for
  1100. * the most recent _DtEnvMapForRemote(). Tossing.
  1101. */
  1102. freeAndNull(mostRecentRemoteHostG);
  1103. }
  1104. if (!targetHost) {
  1105. /*
  1106. * No target host to cache.
  1107. */
  1108. _DtSvcProcessUnlock();
  1109. return;
  1110. }
  1111. /*
  1112. * Performance enhancement: Check if we can map our $HOME directory
  1113. * to the remote host. If we fail because the host cannot be accessed
  1114. * then give up the attempt to map the environment now because we'll
  1115. * run into a lot of timeouts on remote mapping failures otherwise.
  1116. */
  1117. ttMark = tt_mark();
  1118. switch ( tt_ptr_error(
  1119. _DtEnv_tt_host_netfile_file(targetHost,
  1120. _DtEnv_tt_file_netfile(getenv("HOME")) ) ) )
  1121. {
  1122. case TT_ERR_DBEXIST: /* cannot contact remote host */
  1123. case TT_ERR_DBAVAIL: /* timeouts occur trying to make contact */
  1124. case TT_ERR_UNIMP: /* remote server doesn't support file naming */
  1125. /*
  1126. * It will do no good to attempt to map filenames to this remote host
  1127. * So forget it -- the user may try again later.
  1128. */
  1129. tt_release(ttMark); /* free up tooltalk memory used for test */
  1130. _DtSvcProcessUnlock();
  1131. return;
  1132. break;
  1133. default:
  1134. tt_release(ttMark); /* free up tooltalk memory used for test */
  1135. break;
  1136. }
  1137. #ifdef _DTENV_OPTIMIZATION_LOCALHOST
  1138. /*
  1139. * _DtEnvMapForRemote() is normally called from the remote execution
  1140. * code within libDtSvc. If by chance it gets called when spawning
  1141. * local processes, then a test should be done here to bypass mapping
  1142. * environment variables for a local fork/exec.
  1143. */
  1144. if ( <unimplemented - targetHost is local test> ) {
  1145. mostRecentRemoteHostG = "localhost";
  1146. _DtSvcProcessUnlock();
  1147. return;
  1148. }
  1149. #endif /* _DTENV_OPTIMIZATION_LOCALHOST */
  1150. /*
  1151. * Get list of env vars to be mapped.
  1152. */
  1153. mapListStr = _DtEnvGetMapInformation();
  1154. if (!mapListStr) {
  1155. /*
  1156. * Nothing to map.
  1157. */
  1158. _DtSvcProcessUnlock();
  1159. return;
  1160. }
  1161. /*
  1162. * We have a targetHost that needs some mapping done. Start
  1163. * stashing data away.
  1164. */
  1165. mostRecentRemoteHostG = strdup( targetHost );
  1166. _DtSvcProcessUnlock();
  1167. /*
  1168. * Find or allocate a cache entry.
  1169. */
  1170. targetCache = _DtEnvGetTargetCache( targetHost, 1 );
  1171. /*
  1172. * See if cache information for targetHost is available, and
  1173. * if so, if it still looks valid.
  1174. *
  1175. * To maximize performance, an all-or-nothing regeneration of
  1176. * the cache will be done rather than incremental regeneration
  1177. * of some portions of the cache. One would expect that the
  1178. * list of variables to map and their contents would remain
  1179. * fairly static.
  1180. */
  1181. if (targetCache->mapListStr) {
  1182. if ( !strcmp( targetCache->mapListStr, mapListStr ) ) {
  1183. /*
  1184. * Atleast the list of environment variables that need
  1185. * to be mapped is the same as previous.
  1186. */
  1187. cacheRegen = 0;
  1188. for ( i = 0; i < targetCache->mapListCnt; i++ ) {
  1189. if (( tmpPtr = getenv(targetCache->mapList[i]) )) {
  1190. if ( strcmp( tmpPtr,
  1191. targetCache->mapListDetails[i].localEnvVarCopy) ) {
  1192. cacheRegen = 1; /* one map entry is no longer valid */
  1193. break;
  1194. }
  1195. }
  1196. else {
  1197. /*
  1198. * Env Var does not exist, but maybe it never did.
  1199. */
  1200. if (targetCache->mapListDetails[i].localEnvVarCopy) {
  1201. /*
  1202. * Was in cache, but now no longer exists.
  1203. */
  1204. cacheRegen = 1; /* env var no longer exists */
  1205. break;
  1206. }
  1207. }
  1208. }
  1209. }
  1210. else {
  1211. cacheRegen = 1; /* map list changed - need to regen cache */
  1212. }
  1213. }
  1214. else {
  1215. cacheRegen = 1; /* need to create cache */
  1216. }
  1217. if (cacheRegen) {
  1218. /*
  1219. * Toss out the old.
  1220. */
  1221. _DtEnvCleanCacheSlot(targetCache);
  1222. /*
  1223. * Bring in the new.
  1224. */
  1225. targetCache->remoteHost = strdup( targetHost );
  1226. targetCache->mapListStr = strdup( mapListStr );
  1227. targetCache->mapList = _DtEnvGetMapList( mapListStr,
  1228. &(targetCache->mapListCnt) );
  1229. targetCache->mapListDetails = (cachedEnvVar *)
  1230. malloc( sizeof(cachedEnvVar) *
  1231. targetCache->mapListCnt );
  1232. for ( i = 0; i < targetCache->mapListCnt; i++ ) {
  1233. _DtEnvMapIt( targetCache->mapList[i],
  1234. &(targetCache->mapListDetails[i]),
  1235. targetHost );
  1236. }
  1237. }
  1238. else {
  1239. /*
  1240. * We can use cached information. Even though all the
  1241. * environment variable "strings" match, the users
  1242. * (environ **) pointers may be different, so re-cache
  1243. * the restoration pointers.
  1244. */
  1245. for ( i = 0; i < targetCache->mapListCnt; i++ ) {
  1246. if (( targetCache->mapListDetails[i].localEnvVarPtr =
  1247. getenv( targetCache->mapList[i] ) )) {
  1248. targetCache->mapListDetails[i].localEnvVarPtr -=
  1249. strlen( targetCache->mapList[i] ) + 1;
  1250. }
  1251. }
  1252. }
  1253. /*
  1254. * Install the mapped environment variables.
  1255. */
  1256. for ( i = 0; i < targetCache->mapListCnt; i++ ) {
  1257. putenv( targetCache->mapListDetails[i].mappedEnvVarPtr );
  1258. }
  1259. XtFree(mapListStr);
  1260. }
  1261. /******************************************************************************
  1262. *
  1263. * _DtEnvRestoreLocal()
  1264. *
  1265. * Presuming a _DtEnvMapForRemote() was called, _DtEnvRestoreLocal()
  1266. * restores the original envirnment settings for a number of
  1267. * environment variables.
  1268. */
  1269. void _DtEnvRestoreLocal (void)
  1270. {
  1271. extern char *mostRecentRemoteHostG;
  1272. cacheForTargetHost *targetCache;
  1273. char *tmpP;
  1274. int i;
  1275. _DtSvcProcessLock();
  1276. if (mostRecentRemoteHostG) {
  1277. #ifdef _DTENV_OPTIMIZATION_LOCALHOST
  1278. /*
  1279. * See comment with the other ifdef'ed block.
  1280. *
  1281. * If localhost, then nothing to restore.
  1282. */
  1283. if ( !strcmp(mostRecentRemoteHostG, "localhost") ) {
  1284. mostRecentRemoteHostG = (char *) NULL;
  1285. _DtSvcProcessUnlock();
  1286. return;
  1287. }
  1288. #endif /* _DTENV_OPTIMIZATION_LOCALHOST */
  1289. targetCache = _DtEnvGetTargetCache( mostRecentRemoteHostG, 0 );
  1290. if (targetCache) {
  1291. /*
  1292. * Install the mapped environment variables.
  1293. */
  1294. for ( i = 0; i < targetCache->mapListCnt; i++ ) {
  1295. tmpP = targetCache->mapListDetails[i].localEnvVarPtr;
  1296. if ( tmpP ) {
  1297. putenv( targetCache->mapListDetails[i].localEnvVarPtr );
  1298. }
  1299. }
  1300. }
  1301. freeAndNull( mostRecentRemoteHostG );
  1302. }
  1303. _DtSvcProcessUnlock();
  1304. }