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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * catgets.c
31 */
32
33 #pragma weak _catgets = catgets
34
35 #include "lint.h"
36 #include <sys/types.h>
37 #include <nl_types.h>
38 #include <errno.h>
39 #include "nlspath_checks.h"
40
41 char *
catgets(nl_catd catd_st,int set_id,int msg_id,const char * def_str)42 catgets(nl_catd catd_st, int set_id, int msg_id, const char *def_str)
43 {
44 int hi, lo, mid;
45 struct _cat_hdr *p;
46 struct _cat_set_hdr *q;
47 struct _cat_msg_hdr *r;
48 void *catd;
49
50 if ((catd_st == NULL) || (catd_st == (nl_catd)-1)) {
51 /* invalid message catalog descriptor */
52 errno = EBADF;
53 return ((char *)def_str);
54 }
55
56 if ((catd_st->__content == NULL) &&
57 (catd_st->__size == 0) && (catd_st->__trust == 1)) {
58 /* special message catalog descriptor for C locale */
59 return ((char *)def_str);
60 } else if ((catd_st->__content == NULL) || (catd_st->__size == 0)) {
61 /* invalid message catalog descriptor */
62 errno = EBADF;
63 return ((char *)def_str);
64 }
65
66 catd = catd_st->__content;
67 p = (struct _cat_hdr *)catd_st->__content;
68 hi = p->__nsets - 1;
69 lo = 0;
70 /*
71 * Two while loops will perform binary search.
72 * Outer loop searches the set and inner loop searches
73 * message id
74 */
75 while (hi >= lo) {
76 mid = (hi + lo) / 2;
77 q = (struct _cat_set_hdr *)
78 ((uintptr_t)catd
79 + _CAT_HDR_SIZE
80 + _CAT_SET_HDR_SIZE * mid);
81 if (q->__set_no == set_id) {
82 lo = q->__first_msg_hdr;
83 hi = lo + q->__nmsgs - 1;
84 while (hi >= lo) {
85 mid = (hi + lo) / 2;
86 r = (struct _cat_msg_hdr *)
87 ((uintptr_t)catd
88 + _CAT_HDR_SIZE
89 + p->__msg_hdr_offset
90 + _CAT_MSG_HDR_SIZE * mid);
91 if (r->__msg_no == msg_id) {
92 char *msg = (char *)catd
93 + _CAT_HDR_SIZE
94 + p->__msg_text_offset
95 + r->__msg_offset;
96
97 if (!catd_st->__trust) {
98 int errno_save = errno;
99 char *cmsg = check_format(
100 def_str, msg, 0);
101 if (cmsg == def_str) {
102 /* security */
103 return ((char *)
104 def_str);
105 } else {
106 errno = errno_save;
107 return (msg);
108 }
109 } else {
110 return (msg);
111 }
112 } else if (r->__msg_no < msg_id)
113 lo = mid + 1;
114 else
115 hi = mid - 1;
116 } /* while */
117
118 /* In case set number not found */
119 errno = ENOMSG;
120 return ((char *)def_str);
121 } else if (q->__set_no < set_id)
122 lo = mid + 1;
123 else
124 hi = mid - 1;
125 } /* while */
126
127 /* In case msg_id not found. */
128 errno = ENOMSG;
129 return ((char *)def_str);
130 }
131