1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-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 librararies 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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 
28 #ifdef REV_INFO
29 #ifndef lint
30 static char rcsid[] = "$XConsortium: Mrmhier.c /main/17 1996/11/13 14:01:19 drk $"
31 #endif
32 #endif
33 
34 
35 /*
36  *++
37  *  FACILITY:
38  *
39  *      UIL Resource Manager (URM):
40  *
41  *  ABSTRACT:
42  *
43  *--
44  */
45 
46 /*
47  * This file contains routines which assist in managing URM hierarchies
48  */
49 
50 
51 /*
52  *
53  *  INCLUDE FILES
54  *
55  */
56 
57 #include <stdio.h>
58 #include <Mrm/MrmAppl.h>
59 #include <Mrm/Mrm.h>
60 
61 #include <Xm/XmosI.h>		/* for _XmOSInitPath() */
62 #include <Xm/XmI.h>		/* for _XmGetDefaultDisplay() */
63 
64 #include "MrmMsgI.h"
65 
66 #ifndef NO_MESSAGE_CATALOG
67 #if !defined(NL_CAT_LOCALE)
68 #define NL_CAT_LOCALE	0
69 #endif
70 #endif
71 
72 
73 /*
74  *
75  *  TABLE OF CONTENTS
76  *
77  *	Urm__OpenHierarchy		Open hierarchy (internal version)
78  *
79  *	Urm__CloseHierarchy		Close hierarchy (internal version)
80  *
81  *	UrmHGetIndexedResource		Get resource from hierarchy
82  *
83  */
84 
85 
86 /*
87  *
88  *  DEFINE and MACRO DEFINITIONS
89  *
90  */
91 
92 static Cardinal I18NOpenFile (Display		 *display,
93 			      String		 name ,
94 			      MrmOsOpenParamPtr	 os_ext ,
95 			      IDBFile		 *file_id_return );
96 
97 
98 /*
99  *
100  *  OWN VARIABLE DECLARATIONS
101  *
102  */
103 static char		*uidPath;
104 static SubstitutionRec	uidSubs[1];
105 
106 
107 
108 /*
109  *++
110  *
111  *  PROCEDURE DESCRIPTION:
112  *
113  *	This routine allocates a hierarchy descriptor, and opens
114  *	all the IDB files in the hierarchy. It initializes the
115  *	optimized search lists in the hierarchy from the open files.
116  *	All files are closed if there are any errors.
117  *
118  *  FORMAL PARAMETERS:
119  *
120  *	num_files		The number of files in the name list
121  *	name_list		A list of the file names
122  *	os_ext_list		A list of system-dependent ancillary
123  *				structures corresponding to the files.
124  *				This parameter may be NULL.
125  *	hierarchy_id_return	To return the hierarchy id
126  *
127  *  IMPLICIT INPUTS:
128  *
129  *  IMPLICIT OUTPUTS:
130  *
131  *  FUNCTION VALUE:
132  *
133  *	MrmSUCCESS		operation succeeded
134  *	MrmFAILURE		allocation or other failure
135  *	MrmDISPLAY_NOT_OPENED	Display hasn't been opened yet
136  *	Others			see UrmIdbOpenFileRead
137  *
138  *  SIDE EFFECTS:
139  *
140  *--
141  */
142 
143 Cardinal
Urm__OpenHierarchy(MrmCount num_files,String * name_list,MrmOsOpenParamPtr * os_ext_list,MrmHierarchy * hierarchy_id_return,MrmFlag in_memory,unsigned char * uid_buffer)144 Urm__OpenHierarchy (MrmCount			num_files,
145 		    String			*name_list,
146 		    MrmOsOpenParamPtr		*os_ext_list,
147 		    MrmHierarchy		*hierarchy_id_return,
148 		    MrmFlag			in_memory,
149 		    unsigned char		*uid_buffer)
150 {
151 
152   /*
153    *  Local variables
154    */
155   Cardinal		result ;	/* function result */
156   MrmHierarchy		hiptr ;		/* hierarchy descriptor */
157   MrmCount		list_size ;	/* # bytes for file lists */
158   int			ndx ;		/* loop index */
159   IDBFile		*idvec ;	/* current file id vector */
160   int			file_ndx ;	/* file loop index */
161   IDBFile		cur_file ;	/* current IDB file */
162   URMResourceContextPtr	class_ctx;	/* for class compression table */
163   URMResourceContextPtr	resource_ctx;	/* for resource compression table */
164   Display		*display;	/* display for XtResolvePathNames */
165   char                 	err_stg[300];
166 
167 #ifndef NO_MESSAGE_CATALOG
168   static Boolean first = True;
169 
170   /*
171    * We open the message catalog from MrmOpenHierarchy... routines.
172    * We cannot open it from MrmInitialize, since this call can be done
173    * before Xt has been initialized, so at that time the locale could
174    * be wrong.
175    */
176 
177   /* We only want to open the message catalog once. */
178 
179   if (first)
180     {
181       Mrm_catd = catopen("Mrm", NL_CAT_LOCALE);
182       first = False;
183     }
184 #endif
185 
186   if ( os_ext_list == NULL )
187     {
188       display = NULL;
189     }
190   else
191     {
192       MrmOsOpenParamPtr os_data;
193       os_data = *os_ext_list;
194       if (os_data->display == NULL)
195 	{
196 	  display = NULL;
197 	}
198       else
199 	{
200 	  display = os_data->display;
201 	}
202     }
203 
204   if (display == NULL)
205     {
206       display = _XmGetDefaultDisplay();
207     }
208 
209   if (display == NULL)
210     {
211       return Urm__UT_Error ("Urm__OpenHierarchy", _MrmMMsg_0030,
212 			    NULL, NULL, MrmDISPLAY_NOT_OPENED);
213     };
214 
215   /*
216    * If the uidPath was previously set, XtFree it so we can try any
217    * new paths that may have been setup.
218    */
219   if (uidPath != 0)
220     {
221       XtFree (uidPath);
222       uidPath = 0;
223     }
224 
225   /*
226    * Allocate a hierarchy, and allocate all file lists.
227    */
228   hiptr = (MrmHierarchy) XtMalloc (sizeof(MrmHierarchyDesc)) ;
229   if ( hiptr == NULL ) return MrmFAILURE ;
230 
231   hiptr->validation = MrmHIERARCHY_VALID;
232   hiptr->num_file = 0 ;
233 
234   list_size = num_files * sizeof(IDBFile) ;
235   hiptr->file_list = (IDBFile *) XtMalloc (list_size) ;
236   if ( hiptr->file_list == NULL ) return MrmFAILURE ;
237 
238   for ( ndx=URMgMin ; ndx<=URMgMax ; ndx++ )
239     {
240       hiptr->grp_num[ndx] = 0 ;
241       idvec = (IDBFile *) XtMalloc (list_size) ;
242       if ( idvec == NULL ) return MrmFAILURE ;
243       hiptr->grp_ids[ndx] = idvec ;
244     }
245 
246   hiptr->name_registry = NULL;
247 
248   /*
249    * Now open each file. Any failure causes an error return, with any
250    * open files closed and the descriptor and lists freed.
251    */
252   for ( file_ndx=0 ; file_ndx<num_files ; file_ndx++ )
253     {
254       if ( in_memory == TRUE )
255 	{
256 	  result = UrmIdbOpenBuffer(uid_buffer, &cur_file) ;
257 	  switch ( result )
258 	    {
259 	    case MrmSUCCESS:
260 	      break;
261 	    case MrmNOT_VALID:
262 	      sprintf (err_stg, _MrmMMsg_0113);
263 	      break;
264 	    default:
265 	      sprintf (err_stg, _MrmMMsg_0114);
266 	      break;
267 	    }
268 	}
269       else if ( os_ext_list == NULL )
270 	result = I18NOpenFile (display, name_list[file_ndx], NULL, &cur_file) ;
271       else
272         result = I18NOpenFile (display, name_list[file_ndx],
273 			       os_ext_list[file_ndx], &cur_file) ;
274       if ( result != MrmSUCCESS )
275         {
276 	  XtFree (uidPath);
277 	  uidPath = 0;
278 	  Urm__CloseHierarchy (hiptr) ;
279 	  return result;
280         }
281 
282       hiptr->file_list[hiptr->num_file] = cur_file ;
283       hiptr->num_file++ ;
284       for ( ndx=URMgMin ; ndx<=URMgMax ; ndx++ )
285         if ( cur_file->group_counts[ndx] > 0 )
286 	  {
287             idvec = hiptr->grp_ids[ndx] ;
288             idvec[hiptr->grp_num[ndx]] = cur_file ;
289             hiptr->grp_num[ndx]++ ;
290 	  }
291 
292       /*
293        * Attempt to read in compression tables for this UID file.
294        * Retain and fixup the tables if they are found.
295        */
296       cur_file->class_ctable = NULL;
297       cur_file->resource_ctable = NULL;
298       result = UrmGetResourceContext ((char *(*)())NULL, (void(*)())NULL,
299 				      0, &class_ctx);
300       if ( result != MrmSUCCESS ) return result;
301       result = UrmGetResourceContext ((char *(*)())NULL, (void(*)())NULL,
302 				      0, &resource_ctx);
303       if ( result != MrmSUCCESS ) return result;
304       result = UrmGetIndexedLiteral (cur_file, UilMrmClassTableIndex,
305 				     class_ctx);
306       if ( result != MrmSUCCESS ) continue;
307       result = UrmGetIndexedLiteral (cur_file, UilMrmResourceTableIndex,
308 				     resource_ctx);
309       if ( result != MrmSUCCESS ) continue;
310 
311       /*
312        * Retain the buffers from the contexts, but free the contexts
313        * themselves. Fixup the tables.
314        */
315       cur_file->class_ctable =  (UidCompressionTablePtr)
316 	UrmRCBuffer (class_ctx);
317       UrmRCSetBuffer (class_ctx, NULL);
318       UrmFreeResourceContext (class_ctx);
319       Urm__FixupCompressionTable (cur_file->class_ctable, TRUE,
320 				  cur_file->byte_swapped);
321       cur_file->resource_ctable = (UidCompressionTablePtr)
322 	UrmRCBuffer (resource_ctx);
323       UrmRCSetBuffer (resource_ctx, NULL);
324       UrmFreeResourceContext (resource_ctx);
325       Urm__FixupCompressionTable (cur_file->resource_ctable, FALSE,
326 				  cur_file->byte_swapped);
327     }
328 
329   /*
330    * successfully opened. Free the uidPath at this point
331    */
332   XtFree (uidPath);
333   uidPath = 0;
334   *hierarchy_id_return = hiptr ;
335   return MrmSUCCESS ;
336 
337 }
338 
339 
340 
341 /*
342  *++
343  *
344  *  PROCEDURE DESCRIPTION:
345  *
346  *	This is the internal routine which closes a URM search hierarchy
347  *
348  *  FORMAL PARAMETERS:
349  *
350  *	hierarchy_id	ID of an open URM database hierarchy
351  *
352  *  IMPLICIT INPUTS:
353  *
354  *  IMPLICIT OUTPUTS:
355  *
356  *  FUNCTION VALUE:
357  *
358  *	MrmSUCCESS	operation succeeded
359  *	MrmBAD_HIERARCHY	invalid URM hierarchy
360  *	MrmFAILURE	operation failed, no further reason
361  *
362  *  SIDE EFFECTS:
363  *
364  *--
365  */
366 
367 Cardinal
Urm__CloseHierarchy(MrmHierarchy hierarchy_id)368 Urm__CloseHierarchy (MrmHierarchy	hierarchy_id)
369 {
370 
371   /*
372    *  Local variables
373    */
374   int			ndx ;		/* loop index */
375   URMHashTableEntryPtr	cp, np;         /* for fixing 7303 */
376 
377   /*
378    * validity check the hierarchy, then close all files, deallocate all
379    * lists, and deallocate the descriptor
380    */
381   if ( hierarchy_id == NULL )
382     return Urm__UT_Error ("Urm__CloseHierarchy", _MrmMMsg_0023,
383 			  NULL, NULL, MrmBAD_HIERARCHY) ;
384   if ( ! MrmHierarchyValid(hierarchy_id) )
385     return Urm__UT_Error ("Urm__CloseHierarchy", _MrmMMsg_0024,
386 			  NULL, NULL, MrmBAD_HIERARCHY) ;
387 
388   for ( ndx=0 ; ndx<hierarchy_id->num_file ; ndx++ )
389     if (hierarchy_id->file_list[ndx]->in_memory == FALSE )
390       UrmIdbCloseFile (hierarchy_id->file_list[ndx], FALSE) ;
391 
392   /* Begin fixing DTS 7303 */
393   if(hierarchy_id->name_registry){
394     for ( ndx=0 ; ndx<k_hash_table_size; ndx++ )
395       if((cp = hierarchy_id->name_registry[ndx]) != NULL)
396 	while(cp){
397 	  np = cp->az_next_entry;
398 	  XtFree((char*)cp);
399 	  cp = np;
400 	};
401     XtFree ((char*)hierarchy_id->name_registry);
402   }
403   /* End fixing DTS 7303 */
404 
405   XtFree ((char*)hierarchy_id->file_list);
406 
407   for ( ndx=URMgMin ; ndx<=URMgMax ; ndx++ )
408     XtFree ((char*)hierarchy_id->grp_ids[ndx]) ;
409 
410   hierarchy_id->validation = 0;
411   XtFree ((char*)hierarchy_id) ;
412   return MrmSUCCESS ;
413 
414 }
415 
416 
417 
418 /*
419  *++
420  *
421  *  PROCEDURE DESCRIPTION:
422  *
423  *	UrmHGetIndexedResource attempts to retrieve a resource
424  *	from an open URM hierarchy. It functions exactly like
425  *	UrmIdbGetIndexedResource except that it queries each file
426  *	in the hierarchy in turn. It uses the optimized search lists
427  *	where possible.
428  *
429  *  FORMAL PARAMETERS:
430  *
431  *	hierarchy_id		open URM hierarchy to search
432  *	index			case-sensitive index for the entry to match
433  *	group_filter		if not null, entry found must match this group
434  *	type_filter		if not null, entry found must match this type
435  *	context_id		URM resource context to receieve data block
436  *	file_id_return		to return file in which resource was found
437  *
438  *  IMPLICIT INPUTS:
439  *
440  *  IMPLICIT OUTPUTS:
441  *
442  *  FUNCTION VALUE:
443  *
444  *	MrmSUCCESS	operation succeeded
445  *	MrmBAD_HIERARCHY	invalid URM hierarchy
446  *	MrmNOT_FOUND	entry not found
447  *	MrmWRONG_GROUP	entry didn't match group filter
448  *	MrmWRONG_TYPE	entry didn't match type filter
449  *	MrmFAILURE	operation failed, no further reason
450  *
451  *  SIDE EFFECTS:
452  *
453  *--
454  */
455 
456 Cardinal
UrmHGetIndexedResource(MrmHierarchy hierarchy_id,String index,MrmGroup group_filter,MrmType type_filter,URMResourceContextPtr context_id,IDBFile * file_id_return)457 UrmHGetIndexedResource (MrmHierarchy		hierarchy_id,
458 			String			index ,
459 			MrmGroup			group_filter,
460 			MrmType			type_filter,
461 			URMResourceContextPtr	context_id,
462 			IDBFile			*file_id_return)
463 {
464 
465   /*
466    *  Local variables
467    */
468   Cardinal		result ;	/* function results */
469   IDBFile		*file_ids ;	/* list of files to search */
470   int			num_ids ;	/* number of entries in file_ids */
471   int			ndx ;		/* loop index */
472 
473 
474   /*
475    * Validate hierarchy. Then loop through the files which define the resource,
476    * searching for the desired resource.
477    */
478   if ( hierarchy_id == NULL )
479     return Urm__UT_Error ("UrmHGetIndexedResource", _MrmMMsg_0023,
480 			  NULL, NULL, MrmBAD_HIERARCHY) ;
481   if ( ! MrmHierarchyValid(hierarchy_id) )
482     return Urm__UT_Error ("UrmHGetIndexedResource", _MrmMMsg_0024,
483 			  NULL, context_id, MrmBAD_HIERARCHY) ;
484 
485   if ( group_filter>=URMgMin && group_filter<=URMgMax)
486     {
487       file_ids = hierarchy_id->grp_ids[group_filter] ;
488       num_ids = hierarchy_id->grp_num[group_filter] ;
489     }
490   else
491     {
492       file_ids = hierarchy_id->file_list ;
493       num_ids = hierarchy_id->num_file ;
494     }
495   for ( ndx=0 ; ndx<num_ids ; ndx++ )
496     {
497       *file_id_return = file_ids[ndx] ;
498       result = UrmIdbGetIndexedResource
499         (*file_id_return, index, group_filter, type_filter, context_id) ;
500       if ( result == MrmSUCCESS ) return result ;
501     }
502 
503   /*
504    * Not found
505    */
506   return MrmNOT_FOUND ;
507 
508 }
509 
510 
511 
512 /*
513  *++
514  *
515  *  PROCEDURE DESCRIPTION:
516  *
517  *	This routine inserts the names and their associated values into
518  *	the hierarchy's name registration hash table (which is constructed
519  *	if needed). In all respects it functions like Urm__WCI_RegisterNames.
520  *
521  *  FORMAL PARAMETERS:
522  *
523  *	hierarchy_id	open URM hierarchy in which to register names.
524  *	names		A vector of case-sensitive callback routine names.
525  *	values		A vector of the corresponding routine addresses
526  *	num_cb		The number of entries in names and values.
527  *
528  *  IMPLICIT INPUTS:
529  *
530  *  IMPLICIT OUTPUTS:
531  *
532  *  FUNCTION VALUE:
533  *
534  *	MrmSUCCESS	operation succeeded
535  *
536  *  SIDE EFFECTS:
537  *
538  *--
539  */
540 
541 Cardinal
Urm__RegisterNamesInHierarchy(MrmHierarchy hierarchy_id,String * names,XtPointer * values,MrmCount num_cb)542 Urm__RegisterNamesInHierarchy (MrmHierarchy		hierarchy_id,
543 			       String			*names,
544 			       XtPointer			*values,
545 			       MrmCount			num_cb)
546 {
547 
548   URMHashTableEntryPtr	*name_table;
549   Boolean		inited = FALSE;
550   int			ndx;
551   URMHashTableEntryPtr	hash_entry;
552   char			*current_name;
553   char			*current_value;
554 
555 
556   /*
557    * Make sure the hash table is initialized
558    */
559   name_table = hierarchy_id->name_registry;
560   if ( name_table == NULL )
561     {
562       name_table = (URMHashTableEntryPtr *)
563 	XtMalloc(sizeof(URMHashTableEntryPtr)*k_hash_table_size);
564       /* Begin fixing DTS 7303 */
565       for ( ndx=0 ; ndx<k_hash_table_size; ndx++ )
566 	name_table[ndx] = NULL;
567       /* End fixing DTS 7303 */
568       hierarchy_id->name_registry = name_table;
569       hash_initialize (name_table, &inited);
570     }
571 
572   /*
573    * Store each name-value pair in the hash table.
574    */
575   for (ndx = 0 ; ndx < num_cb ; ndx++)
576     {
577       current_name = names [ndx];
578       current_value = values [ndx];
579       hash_entry = (URMHashTableEntryPtr)
580 	hash_insert_name (name_table, current_name);
581       hash_entry->az_value = current_value;
582     }
583 
584   return MrmSUCCESS;
585 
586 }
587 
588 
589 
590 /*
591  *++
592  *
593  *  PROCEDURE DESCRIPTION:
594  *
595  *	This routine returns the value registered for a name. It first
596  *	attempts to look up the name in the hierarchy's name registry.
597  *	If that fails, or their is no registry, then a global lookup is
598  *	attempted.
599  *
600  *  FORMAL PARAMETERS:
601  *
602  *	hierarchy_id	open URM hierarchy to search.
603  *	name		case-sensitive name to be matched
604  *	value_return	to return value.
605  *
606  *  IMPLICIT INPUTS:
607  *
608  *  IMPLICIT OUTPUTS:
609  *
610  *  FUNCTION VALUE:
611  *
612  *	MrmSUCCESS	operation succeeded
613  *	MrmNOT_FOUND	no match found
614  *
615  *  SIDE EFFECTS:
616  *
617  *--
618  */
619 
620 Cardinal
Urm__LookupNameInHierarchy(MrmHierarchy hierarchy_id,String name,XtPointer * value_return)621 Urm__LookupNameInHierarchy (MrmHierarchy	hierarchy_id,
622 			    String		name,
623 			    XtPointer		*value_return)
624 
625 {
626 
627   URMHashTableEntryPtr	*name_table;
628   URMHashTableEntryPtr	hash_entry;
629 
630 
631   /*
632    * Look up in hierarchy first (if there is a registry)
633    */
634   name_table = hierarchy_id->name_registry;
635   if ( name_table != NULL )
636     {
637       hash_entry = (URMHashTableEntryPtr) hash_find_name (name_table, name);
638       if (hash_entry != NULL)
639 	{
640 	  *value_return = hash_entry->az_value;
641 	  return MrmSUCCESS;
642 	}
643     }
644 
645   /*
646    * Fall back on global table
647    */
648   return Urm__WCI_LookupRegisteredName (name, value_return);
649 
650 }
651 
652 
653 
654 /*
655  *++
656  *
657  *  PROCEDURE DESCRIPTION:
658  *
659  *	This routine opens a single UID file in a platform-dependent way,
660  *	performing i18n language switching in order to do so.
661  *
662  *	Per the latest agreement on semantics, this routine does:
663  *		- first, try to open in the local directory (that is, with
664  *		  no switching).
665  *		- second, try language switching and open
666  *
667  *  FORMAL PARAMETERS:
668  *
669  *	name		A system-dependent string specifying the IDB file
670  *			to be opened.
671  *	os_ext		An operating-system specific structure which
672  *			supports using specific file system features
673  *	file_id_return	returns the IDB file id used in all other IDB routines
674  *
675  *  IMPLICIT INPUTS:
676  *
677  *  IMPLICIT OUTPUTS:
678  *
679  *  FUNCTION VALUE:
680  *
681  *  SIDE EFFECTS:
682  *
683  *--
684  */
685 
686 static Cardinal
I18NOpenFile(Display * display,String name,MrmOsOpenParamPtr os_ext,IDBFile * file_id_return)687 I18NOpenFile (Display			*display,
688 	      String			name,
689 	      MrmOsOpenParamPtr		os_ext,
690 	      IDBFile			*file_id_return)
691 {
692 
693   /*
694    *  Local variables
695    */
696   Cardinal		result;		/* function results */
697   char			dummy[300];	/* file name (unused) */
698   char			err_stg[300];
699 
700   /*
701    * Use XtResolvePathName.  If the last 4 characters of the file name
702    * are not .uid then pass in the suffix of .uid.  If a file is not
703    * found with the suffix passed in then try without the suffix.
704    */
705   char			*resolvedname; /* current resolved name */
706   Boolean		user_path ;
707 
708   uidSubs[0].substitution = name;
709 
710   if (uidPath == 0)
711     {
712       uidPath = _XmOSInitPath(name, "UIDPATH", &user_path);
713       if (user_path) uidSubs[0].match = 'U';
714       else           uidSubs[0].match = MATCH_CHAR ;
715     }
716 
717   resolvedname = 0;
718 
719   /*
720    * Check and see if the .uid suffix is already on the file. If not then try to
721    * resolve the pathname with .uid suffix first. If that fails or the suffix is
722    * already on the file then just try to resolve the pathname.
723    */
724   if ( strcmp (&name[strlen(name)-4],".uid") != 0 )
725     resolvedname = XtResolvePathname (display,
726 				      "uid",
727 				      NULL,
728 				      ".uid",
729 				      uidPath,
730 				      uidSubs,
731 				      XtNumber(uidSubs),
732 				      (XtFilePredicate)NULL);
733 
734   /*
735    * No .uid suffix or a failure to resolve the pathname with the .uid suffix
736    */
737   if (resolvedname == 0)
738     resolvedname = XtResolvePathname (display,
739 				      "uid",
740 				      NULL,
741 				      NULL,
742 				      uidPath,
743 				      uidSubs,
744 				      XtNumber(uidSubs),
745 				      (XtFilePredicate)NULL);
746 
747   if (resolvedname == 0)
748     {
749       sprintf (err_stg, _MrmMMsg_0031, name) ;
750       return Urm__UT_Error ("I18NOpenFile", err_stg, NULL, NULL, MrmNOT_FOUND);
751     }
752 
753   result = UrmIdbOpenFileRead (resolvedname, os_ext, file_id_return, dummy) ;
754   switch ( result )
755     {
756     case MrmSUCCESS:
757       break;
758     case MrmNOT_VALID:
759       sprintf (err_stg, _MrmMMsg_0032, resolvedname) ;
760       break;
761     case MrmNOT_FOUND:
762     default:
763       sprintf (err_stg, _MrmMMsg_0031, resolvedname) ;
764       break;
765     }
766 
767   XtFree(resolvedname); /* allocated in XtResolvePathName() */
768 
769   if (result == MrmSUCCESS)
770     return result;
771   else
772     return Urm__UT_Error ("I18NOpenFile", err_stg, NULL, NULL, result);
773 }
774 
775