17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5e53d4db1Ssp149894 * Common Development and Distribution License (the "License").
6e53d4db1Ssp149894 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21e8031f0aSraf
227c478bd9Sstevel@tonic-gate /*
237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307257d1b4Sraf #pragma weak _gettxt = gettxt
317c478bd9Sstevel@tonic-gate
327257d1b4Sraf #include "lint.h"
33e53d4db1Ssp149894 #include "libc.h"
34e53d4db1Ssp149894 #include <mtlib.h>
357c478bd9Sstevel@tonic-gate #include <ctype.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <locale.h>
387c478bd9Sstevel@tonic-gate #include <fcntl.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <sys/file.h>
417c478bd9Sstevel@tonic-gate #include <sys/mman.h>
427c478bd9Sstevel@tonic-gate #include <sys/stat.h>
437c478bd9Sstevel@tonic-gate #include <pfmt.h>
447c478bd9Sstevel@tonic-gate #include <stdlib.h>
457c478bd9Sstevel@tonic-gate #include <unistd.h>
467c478bd9Sstevel@tonic-gate #include <limits.h>
47e53d4db1Ssp149894 #include <thread.h>
487c478bd9Sstevel@tonic-gate #include "../i18n/_locale.h"
497c478bd9Sstevel@tonic-gate #include "../i18n/_loc_path.h"
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate #define MESSAGES "/LC_MESSAGES/"
527c478bd9Sstevel@tonic-gate #define DB_NAME_LEN 15
537c478bd9Sstevel@tonic-gate
54e53d4db1Ssp149894 #define handle_return(s) \
55e53d4db1Ssp149894 ((char *)((s) != NULL && *(s) != '\0' ? (s) : not_found))
567c478bd9Sstevel@tonic-gate
57e53d4db1Ssp149894 extern char cur_cat[];
58e53d4db1Ssp149894 extern rwlock_t _rw_cur_cat;
597c478bd9Sstevel@tonic-gate
60e53d4db1Ssp149894 static mutex_t gettxt_lock = DEFAULTMUTEX;
617c478bd9Sstevel@tonic-gate static const char *not_found = "Message not found!!\n";
62e53d4db1Ssp149894 static const char *loc_C = "C";
637c478bd9Sstevel@tonic-gate
64e53d4db1Ssp149894 struct db_list {
657c478bd9Sstevel@tonic-gate char db_name[DB_NAME_LEN]; /* name of the message file */
667c478bd9Sstevel@tonic-gate uintptr_t addr; /* virtual memory address */
67e53d4db1Ssp149894 struct db_list *next;
68e53d4db1Ssp149894 };
697c478bd9Sstevel@tonic-gate
70e53d4db1Ssp149894 struct db_cache {
71e53d4db1Ssp149894 char *loc;
72e53d4db1Ssp149894 struct db_list *info;
73e53d4db1Ssp149894 struct db_cache *next;
74e53d4db1Ssp149894 };
75e53d4db1Ssp149894
76e53d4db1Ssp149894 static struct db_cache *db_cache;
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate char *
gettxt(const char * msg_id,const char * dflt_str)797c478bd9Sstevel@tonic-gate gettxt(const char *msg_id, const char *dflt_str)
807c478bd9Sstevel@tonic-gate {
81e53d4db1Ssp149894 struct db_cache *dbc;
82e53d4db1Ssp149894 struct db_list *dbl;
837c478bd9Sstevel@tonic-gate char msgfile[DB_NAME_LEN]; /* name of static shared library */
847c478bd9Sstevel@tonic-gate int msgnum; /* message number */
857c478bd9Sstevel@tonic-gate char pathname[PATH_MAX]; /* full pathname to message file */
867c478bd9Sstevel@tonic-gate int fd;
877c478bd9Sstevel@tonic-gate struct stat64 sb;
887c478bd9Sstevel@tonic-gate void *addr;
897c478bd9Sstevel@tonic-gate char *tokp;
907c478bd9Sstevel@tonic-gate size_t name_len;
917c478bd9Sstevel@tonic-gate char *curloc;
92*b599bd93SRobert Mustacchi locale_t loc;
937c478bd9Sstevel@tonic-gate
94e53d4db1Ssp149894 if ((msg_id == NULL) || (*msg_id == '\0')) {
957c478bd9Sstevel@tonic-gate return (handle_return(dflt_str));
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate /* parse msg_id */
997c478bd9Sstevel@tonic-gate if (((tokp = strchr(msg_id, ':')) == NULL) || *(tokp+1) == '\0')
1007c478bd9Sstevel@tonic-gate return (handle_return(dflt_str));
1017c478bd9Sstevel@tonic-gate if ((name_len = (tokp - msg_id)) >= DB_NAME_LEN)
1027c478bd9Sstevel@tonic-gate return (handle_return(dflt_str));
103e53d4db1Ssp149894 if (name_len > 0) {
1047c478bd9Sstevel@tonic-gate (void) strncpy(msgfile, msg_id, name_len);
1057c478bd9Sstevel@tonic-gate msgfile[name_len] = '\0';
1067c478bd9Sstevel@tonic-gate } else {
107e53d4db1Ssp149894 lrw_rdlock(&_rw_cur_cat);
108e53d4db1Ssp149894 if (cur_cat == NULL || *cur_cat == '\0') {
109e53d4db1Ssp149894 lrw_unlock(&_rw_cur_cat);
1107c478bd9Sstevel@tonic-gate return (handle_return(dflt_str));
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate /*
113e53d4db1Ssp149894 * We know the following strcpy is safe.
1147c478bd9Sstevel@tonic-gate */
115e53d4db1Ssp149894 (void) strcpy(msgfile, cur_cat);
116e53d4db1Ssp149894 lrw_unlock(&_rw_cur_cat);
1177c478bd9Sstevel@tonic-gate }
118e53d4db1Ssp149894 while (*++tokp) {
119e53d4db1Ssp149894 if (!isdigit((unsigned char)*tokp))
1207c478bd9Sstevel@tonic-gate return (handle_return(dflt_str));
121e53d4db1Ssp149894 }
122e53d4db1Ssp149894 msgnum = atoi(msg_id + name_len + 1);
123*b599bd93SRobert Mustacchi loc = uselocale(NULL);
124*b599bd93SRobert Mustacchi curloc = current_locale(loc, LC_MESSAGES);
125e53d4db1Ssp149894
126e53d4db1Ssp149894 lmutex_lock(&gettxt_lock);
127e53d4db1Ssp149894
128e53d4db1Ssp149894 try_C:
129e53d4db1Ssp149894 dbc = db_cache;
130e53d4db1Ssp149894 while (dbc) {
131e53d4db1Ssp149894 if (strcmp(curloc, dbc->loc) == 0) {
132e53d4db1Ssp149894 dbl = dbc->info;
133e53d4db1Ssp149894 while (dbl) {
134e53d4db1Ssp149894 if (strcmp(msgfile, dbl->db_name) == 0) {
135e53d4db1Ssp149894 /* msgfile found */
136e53d4db1Ssp149894 lmutex_unlock(&gettxt_lock);
137e53d4db1Ssp149894 goto msgfile_found;
138e53d4db1Ssp149894 }
139e53d4db1Ssp149894 dbl = dbl->next;
140e53d4db1Ssp149894 }
141e53d4db1Ssp149894 /* not found */
142e53d4db1Ssp149894 break;
143e53d4db1Ssp149894 }
144e53d4db1Ssp149894 dbc = dbc->next;
145e53d4db1Ssp149894 }
146e53d4db1Ssp149894 if (dbc == NULL) {
147e53d4db1Ssp149894 /* new locale */
148e53d4db1Ssp149894 if ((dbc = lmalloc(sizeof (struct db_cache))) == NULL) {
149e53d4db1Ssp149894 lmutex_unlock(&gettxt_lock);
150e53d4db1Ssp149894 return (handle_return(dflt_str));
151e53d4db1Ssp149894 }
152e53d4db1Ssp149894 if ((dbc->loc = lmalloc(strlen(curloc) + 1)) == NULL) {
153e53d4db1Ssp149894 lfree(dbc, sizeof (struct db_cache));
154e53d4db1Ssp149894 lmutex_unlock(&gettxt_lock);
155e53d4db1Ssp149894 return (handle_return(dflt_str));
156e53d4db1Ssp149894 }
157e53d4db1Ssp149894 dbc->info = NULL;
158e53d4db1Ssp149894 (void) strcpy(dbc->loc, curloc);
159e53d4db1Ssp149894 /* connect dbc to the dbc list */
160e53d4db1Ssp149894 dbc->next = db_cache;
161e53d4db1Ssp149894 db_cache = dbc;
162e53d4db1Ssp149894 }
163e53d4db1Ssp149894 if ((dbl = lmalloc(sizeof (struct db_list))) == NULL) {
164e53d4db1Ssp149894 lmutex_unlock(&gettxt_lock);
165e53d4db1Ssp149894 return (handle_return(dflt_str));
166e53d4db1Ssp149894 }
167e53d4db1Ssp149894
1687c478bd9Sstevel@tonic-gate if (snprintf(pathname, sizeof (pathname),
169e53d4db1Ssp149894 _DFLT_LOC_PATH "%s" MESSAGES "%s", dbc->loc, msgfile) >=
170e53d4db1Ssp149894 sizeof (pathname)) {
171e53d4db1Ssp149894 lfree(dbl, sizeof (struct db_list));
172e53d4db1Ssp149894 lmutex_unlock(&gettxt_lock);
1737c478bd9Sstevel@tonic-gate return (handle_return(dflt_str));
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate if ((fd = open(pathname, O_RDONLY)) == -1 ||
1767c478bd9Sstevel@tonic-gate fstat64(fd, &sb) == -1 ||
177e53d4db1Ssp149894 (addr = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_SHARED,
178e53d4db1Ssp149894 fd, 0L)) == MAP_FAILED) {
1797c478bd9Sstevel@tonic-gate if (fd != -1)
1807c478bd9Sstevel@tonic-gate (void) close(fd);
181e53d4db1Ssp149894 lfree(dbl, sizeof (struct db_list));
1827c478bd9Sstevel@tonic-gate
183e53d4db1Ssp149894 if (strcmp(dbc->loc, "C") == 0) {
184e53d4db1Ssp149894 lmutex_unlock(&gettxt_lock);
185e53d4db1Ssp149894 return (handle_return(dflt_str));
186e53d4db1Ssp149894 }
1877c478bd9Sstevel@tonic-gate /* Change locale to C */
188e53d4db1Ssp149894 curloc = (char *)loc_C;
189e53d4db1Ssp149894 goto try_C;
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate (void) close(fd);
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate /* save file name, memory address, fd and size */
194e53d4db1Ssp149894 (void) strcpy(dbl->db_name, msgfile);
195e53d4db1Ssp149894 dbl->addr = (uintptr_t)addr;
1967c478bd9Sstevel@tonic-gate
197e53d4db1Ssp149894 /* connect dbl to the dbc->info list */
198e53d4db1Ssp149894 dbl->next = dbc->info;
199e53d4db1Ssp149894 dbc->info = dbl;
200e53d4db1Ssp149894
201e53d4db1Ssp149894 lmutex_unlock(&gettxt_lock);
202e53d4db1Ssp149894
203e53d4db1Ssp149894 msgfile_found:
2047c478bd9Sstevel@tonic-gate /* check if msgnum out of domain */
205e53d4db1Ssp149894 if (msgnum <= 0 || msgnum > *(int *)dbl->addr)
2067c478bd9Sstevel@tonic-gate return (handle_return(dflt_str));
2077c478bd9Sstevel@tonic-gate /* return pointer to message */
208e53d4db1Ssp149894 return ((char *)(dbl->addr +
209e53d4db1Ssp149894 *(int *)(dbl->addr + msgnum * sizeof (int))));
2107c478bd9Sstevel@tonic-gate }
211