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 * 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