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 *
catgets(nl_catd catd_st,int set_id,int msg_id,const char * def_str)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