1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME
80**
81**      cs_s_reg.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC) OSF Code Set Registry Access routines
86**
87**  ABSTRACT:
88**
89**      Code set interoperability requires a common way to recognize the
90**      supported code sets for client and server.  OSF code set registry
91**	provides that functionality.  OSF code set registry is a binary file
92**	which is produced by 'csrc' (Code set registry compiler).
93**
94*/
95
96#include <stdio.h>
97#include <stdlib.h>
98#include <dce/rpc.h>
99#include <dce/csrc.h>
100#include <unistd.h>
101#include <fcntl.h>
102#include <commonp.h>
103#include <dce/dce_cf.h>		/* Access to the backing store library */
104#include <langinfo.h>
105
106
107/*
108** Local globals for code set registry access.
109** Code set registry is pointed by rpc_g_codesets_list.
110*/
111static boolean		rpc_g_codesets_did_read;
112static dcethread_mutex	rpc_g_codesets_mutex;
113static dcethread_oncectl rpc_g_codesets_once_block = DCETHREAD_ONCE_INIT;
114static entry_t		*rpc_g_codesets_list;
115static entry_t		*rpc_g_codesets_effective_ids;
116static entry_t		**rpc_g_codesets_sort_by_priority;
117static entry_t		**rpc_g_codesets_sort_by_name;
118static entry_t		**rpc_g_codesets_sort_by_id;
119static int		rpc_g_codesets_entry_count;
120static int		rpc_g_codesets_effective_count;
121static error_status_t	rpc_g_codesets_status;
122
123/*
124**
125** Iterative Insertion Sort for code set name.
126**
127*/
128PRIVATE
129void name_sort
130(
131	entry_t		**codesets,
132	int		entry_count
133)
134{
135	int	i, j, k;
136	entry_t	*temp;
137
138	if (entry_count <= 1)
139		return;
140
141	for (i = 1; i < entry_count; i++)
142	{
143		temp = codesets[i];
144		j = i - 1;
145		while (j >= 0)
146		{
147			if ((k = strcoll(codesets[j]->code_set_name, (const char *)temp->code_set_name)) > 0)
148			{
149				codesets[j + 1] = codesets[j];
150				codesets[j] = temp;
151			}
152			j--;
153		}
154	}
155}
156
157/*
158**
159** Iterative Insertion Sort for priority
160**
161*/
162PRIVATE
163void priority_sort
164(
165	entry_t		**codesets,
166	int		entry_count
167)
168{
169	int	i, j, k;
170	entry_t	*temp;
171
172	if (entry_count <= 1)
173		return;
174
175	for (i = 1; i < entry_count; i++)
176	{
177		temp = codesets[i];
178		j = i - 1;
179		while (j >= 0)
180		{
181			if (codesets[j]->priority > temp->priority)
182			{
183				codesets[j + 1] = codesets[j];
184				codesets[j] = temp;
185			}
186			j--;
187		}
188	}
189}
190
191/*
192**
193** Binary Search for code set value
194**
195*/
196PRIVATE
197void c_binary_search
198(
199	entry_t		**codesets,
200	int		low,
201	int		high,
202	long		key_value,
203	entry_t		**code_entry
204)
205{
206	int	middle;
207	long	code1, code2;
208
209	if (key_value < 0)		/* little trick for large number */
210		code1 = key_value * -1;
211	else
212		code1 = key_value;
213
214	if (low <= high)
215	{
216		middle = (low + high) / 2;
217
218		if (codesets[middle]->code_set < 0)
219			code2 = codesets[middle]->code_set * -1;
220		else
221			code2 = codesets[middle]->code_set;
222
223		if (code1 == code2)
224		{
225			*code_entry = codesets[middle];
226			return;
227		}
228		else
229		{
230			if (code1 < code2)
231				c_binary_search(codesets, low, middle-1, key_value, code_entry);
232			else
233				c_binary_search(codesets, middle+1, high, key_value, code_entry);
234		}
235	}
236}
237
238/*
239**
240** Binary Search for code set name
241**
242*/
243PRIVATE
244void n_binary_search
245(
246	entry_t		**codesets,
247	int		low,
248	int		high,
249	char		*key_name,
250	entry_t		**code_entry
251)
252{
253	int	middle, k;
254
255	if (low <= high)
256	{
257		middle = (low + high) / 2;
258
259		if ((k = strcoll(key_name, codesets[middle]->code_set_name)) == 0)
260		{
261			*code_entry = codesets[middle];
262			return;
263		}
264		else
265		{
266			if (k < 0)
267				n_binary_search(codesets, low, middle-1, key_name, code_entry);
268			else
269				n_binary_search(codesets, middle+1, high, key_name, code_entry);
270		}
271	}
272}
273
274
275/*
276**++
277**  ROUTINE NAME:           rpc__codesets_really_read_file
278**
279**  SCOPE:                  PRIVATE
280**
281**  DESCRIPTION:
282**
283**  Internal routine to read OSF code set registry data into a memory.
284**  To avoid the unnecessary overhead, this routine only read the code set
285**  registry data once, when code set registry is first accessed.
286**  This function takes no arguments and returns no data.
287**
288**--
289*/
290PRIVATE
291rpc__codesets_really_read_file
292(
293	void
294)
295{
296	int	i, j, k;
297	entry_t	*ep;
298	entry_t	*effective_ep;
299	int	CsrFile;
300	char	*code_set_registry_file;
301
302	/*
303	** Open the code set registry file.  The default path is
304	** "/usr/lib/nls/csr/code_set_registry.db"
305	*/
306	dce_cf_get_csrgy_filename(&code_set_registry_file, &rpc_g_codesets_status);
307	if (rpc_g_codesets_status != dce_cf_st_ok)
308	{
309		return;
310	}
311
312	CsrFile = open(code_set_registry_file, O_RDONLY, 0);
313	free (code_set_registry_file);
314	if (CsrFile == -1)
315	{
316		rpc_g_codesets_status = dce_cs_c_cannot_open_file;
317		return;
318	}
319
320	if ((read (CsrFile, (char *)(&rpc_g_codesets_entry_count), sizeof(rpc_g_codesets_entry_count))) == -1)
321	{
322		rpc_g_codesets_status = dce_cs_c_cannot_read_file;
323		return;
324	}
325
326	if ((read (CsrFile, (char *)(&rpc_g_codesets_effective_count), sizeof(rpc_g_codesets_entry_count))) == -1)
327	{
328		rpc_g_codesets_status = dce_cs_c_cannot_read_file;
329		return;
330	}
331
332	if ((rpc_g_codesets_list = (entry_t *)malloc(sizeof(entry_t) * rpc_g_codesets_entry_count)) == NULL)
333	{
334		rpc_g_codesets_status = dce_cs_c_cannot_allocate_memory;
335		return;
336	}
337
338	if ((rpc_g_codesets_effective_ids = (entry_t *)malloc(sizeof(entry_t) * rpc_g_codesets_effective_count)) == NULL)
339	{
340		rpc_g_codesets_status = dce_cs_c_cannot_allocate_memory;
341		return;
342	}
343
344	ep = rpc_g_codesets_list;
345	i = rpc_g_codesets_entry_count;
346	effective_ep = rpc_g_codesets_effective_ids;
347
348	while (i--)
349	{
350		if ((read (CsrFile, (char *)(&ep->code_set), sizeof(ep->code_set))) == -1)
351		{
352			rpc_g_codesets_status = dce_cs_c_cannot_read_file;
353			return;
354		}
355
356		if ((read (CsrFile, (char *)(&ep->code_name_len), sizeof(ep->code_name_len))) == -1)
357		{
358			rpc_g_codesets_status = dce_cs_c_cannot_read_file;
359			return;
360		}
361
362		if ((ep->code_set_name = (char *)malloc(ep->code_name_len + 1)) == NULL)
363		{
364			rpc_g_codesets_status = dce_cs_c_cannot_allocate_memory;
365			return;
366		}
367
368		if ((read (CsrFile, (char *)ep->code_set_name, ep->code_name_len + 1)) == -1)
369		{
370			rpc_g_codesets_status = dce_cs_c_cannot_read_file;
371			return;
372		}
373
374		if ((read (CsrFile, (char *)(&ep->char_sets_num), sizeof(ep->char_sets_num))) == -1)
375		{
376			rpc_g_codesets_status = dce_cs_c_cannot_read_file;
377			return;
378		}
379
380		for (j = 0; j < ep->char_sets_num; j++)
381		{
382			if ((read (CsrFile, (char *)(&ep->char_sets[j]), sizeof(ep->char_sets[j]))) == -1)
383			{
384				rpc_g_codesets_status = dce_cs_c_cannot_read_file;
385				return;
386			}
387		}
388
389		if ((read (CsrFile, (char *)(&ep->max_bytes), sizeof(ep->max_bytes))) == -1)
390		{
391			rpc_g_codesets_status = dce_cs_c_cannot_read_file;
392			return;
393		}
394
395		if ((read (CsrFile, (char *)(&ep->priority), sizeof(ep->priority))) == -1)
396		{
397			rpc_g_codesets_status = dce_cs_c_cannot_read_file;
398			return;
399		}
400
401		if ((k = strcoll(ep->code_set_name, "NONE")) != 0)
402		{
403			effective_ep->code_set      =  ep->code_set;
404			effective_ep->code_name_len =  ep->code_name_len;
405			effective_ep->code_set_name =  ep->code_set_name;
406			effective_ep->char_sets_num =  ep->char_sets_num;
407			for (j = 0; j < ep->char_sets_num; j++)
408				effective_ep->char_sets[j] = ep->char_sets[j];
409			effective_ep->max_bytes     =  ep->max_bytes;
410			effective_ep->priority      =  ep->priority;
411
412			effective_ep++;
413		}
414
415		ep++;
416	}
417
418	close (CsrFile);
419
420	rpc_g_codesets_status = rpc_s_ok;
421
422	rpc_g_codesets_did_read = TRUE;
423}
424
425/*
426**++
427**  ROUTINE NAME:           rpc__codesets_read_registry_file
428**
429**  SCOPE:                  PRIVATE
430**
431**  DESCRIPTION:
432**
433**  Internal routine to allocate OSF code set registry data into a memory.
434**  rpc__codesets_really_read_file() is called to actually perform
435**  reading data from a registry file.  Code set registry is sorted by
436**  code set id and code set name.  Local global pointers point to each
437**  sorted memory.
438**
439**--
440*/
441PRIVATE
442rpc__codesets_read_registry_file
443(
444	error_status_t	*status
445)
446{
447	entry_t		**sort_name_codesets;
448	entry_t		**sort_name_save;
449	entry_t		**sort_id_codesets;
450	entry_t		**sort_id_save;
451	entry_t		**sort_priority_codesets;
452	entry_t		**sort_priority_save;
453	int		i;
454	entry_t		*ep;
455
456	if (!rpc_g_codesets_did_read)
457	{
458		dcethread_once_throw(&rpc_g_codesets_once_block,
459		(dcethread_initroutine)rpc__codesets_really_read_file);
460
461		if (rpc_g_codesets_status != rpc_s_ok)
462		{
463			*status = rpc_g_codesets_status;
464			return;
465		}
466	}
467
468	/*
469	** Sort the code set registry file by code set name
470	**/
471	if ((sort_name_save = (entry_t **)malloc(sizeof(entry_t *) * rpc_g_codesets_entry_count)) == NULL)
472	{
473		*status = dce_cs_c_cannot_allocate_memory;
474		return;
475	}
476
477	ep = rpc_g_codesets_list;
478	i = rpc_g_codesets_entry_count;
479	sort_name_codesets = sort_name_save;
480	while (i--)
481	{
482		*sort_name_codesets++ = ep++;
483	}
484	rpc_g_codesets_sort_by_name = sort_name_save;
485	sort_name_codesets = sort_name_save;
486	name_sort(sort_name_codesets, rpc_g_codesets_entry_count);
487
488	/*
489	** Sort the effective code set by priority
490	**/
491	if ((sort_priority_save = (entry_t **)malloc(sizeof(entry_t *) * rpc_g_codesets_effective_count)) == NULL)
492	{
493		*status = dce_cs_c_cannot_allocate_memory;
494		return;
495	}
496	ep = rpc_g_codesets_effective_ids;
497	i = rpc_g_codesets_effective_count;
498	sort_priority_codesets = sort_priority_save;
499	while (i--)
500	{
501		*sort_priority_codesets++ = ep++;
502	}
503	rpc_g_codesets_sort_by_priority = sort_priority_save;
504	sort_priority_codesets = sort_priority_save;
505	priority_sort(sort_priority_codesets, rpc_g_codesets_effective_count);
506
507	/*
508	** Allocate an array for pointers to entry_t.  Code set registry
509	** is already sorted by code set id value.
510	*/
511	if ((sort_id_save = (entry_t **)malloc(sizeof(entry_t *) * rpc_g_codesets_entry_count)) == NULL)
512	{
513		*status = dce_cs_c_cannot_allocate_memory;
514		return;
515	}
516	ep = rpc_g_codesets_list;
517	i = rpc_g_codesets_entry_count;
518	sort_id_codesets = sort_id_save;
519	while (i--)
520	{
521		*sort_id_codesets++ = ep++;
522	}
523	rpc_g_codesets_sort_by_id = sort_id_save;
524
525	*status = rpc_s_ok;
526
527}
528
529
530/*
531**++
532**  ROUTINE NAME:           dce_cs_loc_to_rgy
533**
534**  SCOPE:                  PUBLIC - declared in rpc.idl
535**
536**  DESCRIPTION:
537**
538**  Convert code set name (in string) to code set id (integer).
539**  When rgy_char_sets_number is NULL, no character sets values
540**  will be returned.  Character sets are mainly used to evaluate
541**  code set compatibility.
542**
543**  INPUTS:
544**
545**      local_code_set_name	OS specific name for the code set
546**
547**
548**  INPUT/OUPUTS:	    NONE
549**
550**
551**  OUTPUTS:
552**
553**	rgy_code_set_value	Registerd code set id
554**
555**	rgy_char_sets_number	Number of character sets supported by
556**				the code set
557**
558**	rgy_char_sets_value	Array of character set IDs supported by
559**				the code set
560**
561**      status              The result of the operation. One of:
562**                              dce_cs_c_ok
563**                              dce_cs_c_notfound
564**                              dce_cs_c_cannot_allocate_memory
565**				status from rpc__codesets_read_registry_file
566**
567**  IMPLICIT INPUTS:        none
568**
569**  IMPLICIT OUTPUTS:       none
570**
571**  FUNCTION VALUE:         void
572**
573**  SIDE EFFECTS:           none
574**
575**--
576*/
577
578PUBLIC
579void dce_cs_loc_to_rgy
580(
581	idl_char		*local_code_set_name,
582	unsigned32		*rgy_code_set_value,
583	unsigned16		*rgy_char_sets_number,
584	unsigned16		**rgy_char_sets_value,
585	error_status_t		*status
586)
587{
588	entry_t		**epp;
589	entry_t		*found = NULL;
590	int		i;
591	unsigned16	*char_array;
592
593	CODING_ERROR (status);
594
595	rpc__codesets_read_registry_file(status);
596	if (*status != rpc_s_ok)
597	{
598		return;
599	}
600
601	epp = rpc_g_codesets_sort_by_name;
602
603	/* binary search */
604	n_binary_search(epp, 0, rpc_g_codesets_entry_count-1, (char *)local_code_set_name, &found);
605
606	if (found == NULL)
607	{
608		*status = dce_cs_c_unknown;
609		return;
610	}
611
612	if (rgy_char_sets_number != NULL)
613	{
614		*rgy_char_sets_number = found->char_sets_num;
615	}
616
617	if (rgy_char_sets_value != NULL)
618	{
619		if ((char_array = (unsigned16 *)malloc(sizeof(unsigned16) * found->char_sets_num)) == NULL)
620		{
621			*status = dce_cs_c_cannot_allocate_memory;
622			return;
623		}
624
625		*rgy_char_sets_value = char_array;
626
627		for (i = 0; i < found->char_sets_num; i++)
628		{
629			*char_array++ = found->char_sets[i];
630		}
631	}
632	*rgy_code_set_value = (unsigned32)found->code_set;
633
634	*status = dce_cs_c_ok;
635	return;
636}
637
638
639/*
640**++
641**  ROUTINE NAME:           dce_cs_rgy_to_loc
642**
643**  SCOPE:                  PUBLIC - declared in rpc.idl
644**
645**  DESCRIPTION:
646**
647**  Convert code set id (integer) to code set name (in string).
648**  When rgy_char_sets_number is NULL, no character sets values
649**  will be returned.  Character sets are mainly used to evaluate
650**  code set compatibility.
651**
652**  INPUTS:
653**
654**	rgy_code_set_value	Registerd code set id
655**
656**
657**  INPUT/OUPUTS:	    NONE
658**
659**
660**  OUTPUTS:
661**
662**      local_code_set_name	OS specific name for the code set
663**
664**	rgy_char_sets_number	Number of character sets supported by
665**				the code set
666**
667**	rgy_char_sets_value	Array of character set IDs supported by
668**				the code set
669**
670**      status              The result of the operation. One of:
671**                              dce_cs_c_ok
672**                              dce_cs_c_notfound
673**                              dce_cs_c_cannot_allocate_memory
674**				status from rpc__codesets_read_registry_file
675**
676**  IMPLICIT INPUTS:        none
677**
678**  IMPLICIT OUTPUTS:       none
679**
680**  FUNCTION VALUE:         void
681**
682**  SIDE EFFECTS:           none
683**
684**--
685*/
686
687PUBLIC
688void dce_cs_rgy_to_loc
689(
690	unsigned32		rgy_code_set_value,
691	idl_char 		**local_code_set_name,
692	unsigned16		*rgy_char_sets_number,
693	unsigned16		**rgy_char_sets_value,
694	error_status_t		*status
695)
696{
697	entry_t		**epp;
698	entry_t		*found = NULL;
699	int		i;
700	unsigned16	*char_array;
701
702	CODING_ERROR (status);
703
704	rpc__codesets_read_registry_file(status);
705	if (*status != rpc_s_ok)
706	{
707		return;
708	}
709
710	epp = rpc_g_codesets_sort_by_id;
711	i = rpc_g_codesets_entry_count;
712
713	/* binary search */
714	c_binary_search(epp, 0, rpc_g_codesets_entry_count-1, rgy_code_set_value, &found);
715
716	if (found == NULL)
717	{
718		*status = dce_cs_c_unknown;
719		return;
720	}
721
722	if ((i = strcoll(found->code_set_name, "NONE")) == 0)
723	{
724		*status = dce_cs_c_notfound;
725		return;
726	}
727
728	if (rgy_char_sets_number != NULL)
729	{
730		*rgy_char_sets_number = found->char_sets_num;
731	}
732
733	if (rgy_char_sets_value != NULL)
734	{
735		if ((char_array = (unsigned16 *)malloc(sizeof(unsigned16) * found->char_sets_num)) == NULL)
736		{
737			*status = dce_cs_c_cannot_allocate_memory;
738			return;
739		}
740
741		*rgy_char_sets_value = char_array;
742
743		for (i = 0; i < found->char_sets_num; i++)
744		{
745			*char_array++ = found->char_sets[i];
746		}
747	}
748	*local_code_set_name = (idl_char *)found->code_set_name;
749
750	*status = dce_cs_c_ok;
751	return;
752}
753
754
755/*
756**++
757**  ROUTINE NAME:           rpc_rgy_get_max_bytes
758**
759**  SCOPE:                  PUBLIC - declared in rpc.idl
760**
761**  DESCRIPTION:
762**
763**  Search maximum number of bytes for a tag specified.  The tag
764**  is the code set id number from OSF code set registry.
765**  This routine is mainly used by a stub to calculate a size of
766**  necessary conversion buffer.
767**
768**  INPUTS:
769**
770**	tag			Registerd code set id
771**
772**
773**  INPUT/OUPUTS:	    NONE
774**
775**
776**  OUTPUTS:
777**
778**      max_bytes		Maximum number of bytes needed to encode
779**				a character in the code set
780**
781**      status              The result of the operation. One of:
782**                              rpc_s_ok
783**                              dce_cs_c_notfound
784**				status from rpc__codesets_read_registry_file
785**
786**  IMPLICIT INPUTS:        none
787**
788**  IMPLICIT OUTPUTS:       none
789**
790**  FUNCTION VALUE:         void
791**
792**  SIDE EFFECTS:           none
793**
794**--
795*/
796
797PUBLIC
798void rpc_rgy_get_max_bytes
799(
800	unsigned32		tag,
801	unsigned16		*max_bytes,
802	error_status_t		*status
803)
804{
805	entry_t		**epp;
806	entry_t		*found = NULL;
807	int		i;
808	unsigned16	*char_array;
809
810	CODING_ERROR (status);
811
812	rpc__codesets_read_registry_file(status);
813	if (*status != rpc_s_ok)
814	{
815		return;
816	}
817
818	epp = rpc_g_codesets_sort_by_id;
819	i = rpc_g_codesets_entry_count;
820
821	/* binary search */
822	c_binary_search(epp, 0, rpc_g_codesets_entry_count-1, tag, &found);
823
824	if (found == NULL)
825	{
826		*status = dce_cs_c_unknown;
827		return;
828	}
829
830	if ((i = strcoll(found->code_set_name, "NONE")) == 0)
831	{
832		*status = dce_cs_c_notfound;
833		return;
834	}
835
836	*max_bytes = found->max_bytes;
837
838	*status = rpc_s_ok;
839	return;
840}
841
842/*
843**++
844**  ROUTINE NAME:           rpc_rgy_get_codesets
845**
846**  SCOPE:                  PUBLIC - declared in rpc.idl
847**
848**  DESCRIPTION:
849**
850**  This an OS dependent routine.  It will determine which code sets
851**  are supported by a current machine, and returns a list of code sets.
852**  The first code set in a list should be a current locale's code set.
853**
854**
855**  INPUTS: none
856**
857**  INPUT/OUPUTS:
858**
859**	args 		    Actually points to 'rpc_cs_codeset_i14y_data_p'
860**			    data type.
861**
862**  OUTPUTS: none
863**
864**  IMPLICIT INPUTS:        none
865**
866**  IMPLICIT OUTPUTS:       none
867**
868**  FUNCTION VALUE:         void
869**
870**  SIDE EFFECTS:           none
871**
872**--
873*/
874
875PUBLIC
876void rpc_rgy_get_codesets
877(
878	rpc_codeset_mgmt_p_t	*codesets_p,
879	error_status_t		*status
880)
881{
882	int             i;
883	entry_t		**epp;
884	char		*current_codeset;
885	unsigned32	current_rgy_codeset;
886
887	CODING_ERROR (status);
888
889	rpc__codesets_read_registry_file(status);
890	if (*status != rpc_s_ok)
891	{
892		return;
893	}
894
895	epp = rpc_g_codesets_sort_by_priority;
896
897	RPC_MEM_ALLOC (
898		*codesets_p,
899		rpc_codeset_mgmt_p_t,
900		sizeof(rpc_codeset_mgmt_t) +
901		  (sizeof(rpc_cs_c_set_t) * (rpc_g_codesets_effective_count - 1)),
902		RPC_C_MEM_CDS_ATTR,
903		RPC_C_MEM_WAITOK);
904
905	(*codesets_p)->count = rpc_g_codesets_effective_count;
906
907	current_codeset = nl_langinfo(CODESET);
908	dce_cs_loc_to_rgy(
909		(unsigned_char_p_t)current_codeset,
910		&current_rgy_codeset,
911		NULL, NULL,
912		status);
913
914	if (*status != dce_cs_c_ok)
915	{
916		/* codeset registry error */
917		*status = rpc_s_ok;
918		return;
919	}
920
921	/*
922	 * The top of the list is current locale's code set
923	 */
924	(*codesets_p)->codesets[0].c_set = current_rgy_codeset;
925
926	for (i = 1; i < rpc_g_codesets_effective_count; i++)
927	{
928		/*
929		**  This logic assumes current locale's code set is one of
930		**  the supported code set.  It should be.
931		*/
932		if ((*epp)->code_set != (*codesets_p)->codesets[0].c_set)
933		{
934			(*codesets_p)->codesets[i].c_set = (*epp)->code_set;
935
936			(*codesets_p)->codesets[i].c_max_bytes = (*epp)->max_bytes;
937		}
938		else
939		{
940			(*codesets_p)->codesets[0].c_max_bytes = (*epp)->max_bytes;
941			i--;
942		}
943
944		epp++;
945	}
946
947	*status = rpc_s_ok;
948}
949