xref: /illumos-gate/usr/src/lib/libc/port/gen/catgets.c (revision 374858d291554c199353841e2900bc130463934a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * catgets.c
29  */
30 
31 #pragma weak _catgets = catgets
32 
33 #include "lint.h"
34 #include <sys/types.h>
35 #include <nl_types.h>
36 #include <errno.h>
37 #include "nlspath_checks.h"
38 
39 char *
40 catgets(nl_catd catd_st, int set_id, int msg_id, const char *def_str)
41 {
42 	int			hi, lo, mid;
43 	struct	_cat_hdr 	*p;
44 	struct	_cat_set_hdr	*q;
45 	struct	_cat_msg_hdr	*r;
46 	void			*catd;
47 
48 	if ((catd_st == NULL) || (catd_st == (nl_catd)-1)) {
49 		/* invalid message catalog descriptor */
50 		errno = EBADF;
51 		return ((char *)def_str);
52 	}
53 
54 	if ((catd_st->__content == NULL) &&
55 	    (catd_st->__size == 0) && (catd_st->__trust == 1)) {
56 		/* special message catalog descriptor for C locale */
57 		return ((char *)def_str);
58 	} else if ((catd_st->__content == NULL) || (catd_st->__size == 0)) {
59 		/* invalid message catalog descriptor */
60 		errno = EBADF;
61 		return ((char *)def_str);
62 	}
63 
64 	catd = catd_st->__content;
65 	p = (struct _cat_hdr *)catd_st->__content;
66 	hi = p->__nsets - 1;
67 	lo = 0;
68 	/*
69 	 * Two while loops will perform binary search.
70 	 * Outer loop searches the set and inner loop searches
71 	 * message id
72 	 */
73 	while (hi >= lo) {
74 		mid = (hi + lo) / 2;
75 		q = (struct _cat_set_hdr *)
76 		    ((uintptr_t)catd
77 		    + _CAT_HDR_SIZE
78 		    + _CAT_SET_HDR_SIZE * mid);
79 		if (q->__set_no == set_id) {
80 			lo = q->__first_msg_hdr;
81 			hi = lo + q->__nmsgs - 1;
82 			while (hi >= lo) {
83 				mid = (hi + lo) / 2;
84 				r = (struct _cat_msg_hdr *)
85 				    ((uintptr_t)catd
86 				    + _CAT_HDR_SIZE
87 				    + p->__msg_hdr_offset
88 				    + _CAT_MSG_HDR_SIZE * mid);
89 				if (r->__msg_no == msg_id) {
90 					char *msg = (char *)catd
91 					    + _CAT_HDR_SIZE
92 					    + p->__msg_text_offset
93 					    + r->__msg_offset;
94 
95 					if (!catd_st->__trust) {
96 						int errno_save = errno;
97 						char *cmsg = check_format(
98 						    def_str, msg, 0);
99 						if (cmsg == def_str) {
100 							/* security */
101 							return ((char *)
102 							    def_str);
103 						} else {
104 							errno = errno_save;
105 							return (msg);
106 						}
107 					} else {
108 						return (msg);
109 					}
110 				} else if (r->__msg_no < msg_id)
111 					lo = mid + 1;
112 				else
113 					hi = mid - 1;
114 			} /* while */
115 
116 			/* In case set number not found */
117 			errno = ENOMSG;
118 			return ((char *)def_str);
119 		} else if (q->__set_no < set_id)
120 			lo = mid + 1;
121 		else
122 			hi = mid - 1;
123 	} /* while */
124 
125 	/* In case msg_id not found. */
126 	errno = ENOMSG;
127 	return ((char *)def_str);
128 }
129