| /* Copyright (C) 1996-2016 Free Software Foundation, Inc. | 
 |    This file is part of the GNU C Library. | 
 |    Contributed by Ulrich Drepper, <drepper@gnu.org>. | 
 |  | 
 |    The GNU C Library is free software; you can redistribute it and/or | 
 |    modify it under the terms of the GNU Lesser General Public | 
 |    License as published by the Free Software Foundation; either | 
 |    version 2.1 of the License, or (at your option) any later version. | 
 |  | 
 |    The GNU C Library is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |    Lesser General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU Lesser General Public | 
 |    License along with the GNU C Library; if not, see | 
 |    <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include <errno.h> | 
 | #include <locale.h> | 
 | #include <nl_types.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 | #include <unistd.h> | 
 | #include <sys/mman.h> | 
 |  | 
 | #include "catgetsinfo.h" | 
 |  | 
 |  | 
 | /* Open the catalog and return a descriptor for the catalog.  */ | 
 | nl_catd | 
 | catopen (const char *cat_name, int flag) | 
 | { | 
 |   __nl_catd result; | 
 |   const char *env_var = NULL; | 
 |   const char *nlspath = NULL; | 
 |   char *tmp = NULL; | 
 |  | 
 |   if (strchr (cat_name, '/') == NULL) | 
 |     { | 
 |       if (flag == NL_CAT_LOCALE) | 
 | 	/* Use the current locale setting for LC_MESSAGES.  */ | 
 | 	env_var = setlocale (LC_MESSAGES, NULL); | 
 |       else | 
 | 	/* Use the LANG environment variable.  */ | 
 | 	env_var = getenv ("LANG"); | 
 |  | 
 |       if (env_var == NULL || *env_var == '\0' | 
 | 	  || (__libc_enable_secure && strchr (env_var, '/') != NULL)) | 
 | 	env_var = "C"; | 
 |  | 
 |       nlspath = getenv ("NLSPATH"); | 
 |       if (nlspath != NULL && *nlspath != '\0') | 
 | 	{ | 
 | 	  /* Append the system dependent directory.  */ | 
 | 	  size_t len = strlen (nlspath) + 1 + sizeof NLSPATH; | 
 | 	  tmp = malloc (len); | 
 |  | 
 | 	  if (__glibc_unlikely (tmp == NULL)) | 
 | 	    return (nl_catd) -1; | 
 |  | 
 | 	  __stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH); | 
 | 	  nlspath = tmp; | 
 | 	} | 
 |       else | 
 | 	nlspath = NLSPATH; | 
 |     } | 
 |  | 
 |   result = (__nl_catd) malloc (sizeof (*result)); | 
 |   if (result == NULL) | 
 |     { | 
 |       /* We cannot get enough memory.  */ | 
 |       result = (nl_catd) -1; | 
 |     } | 
 |   else if (__open_catalog (cat_name, nlspath, env_var, result) != 0) | 
 |     { | 
 |       /* Couldn't open the file.  */ | 
 |       free ((void *) result); | 
 |       result = (nl_catd) -1; | 
 |     } | 
 |  | 
 |   free (tmp); | 
 |   return (nl_catd) result; | 
 | } | 
 |  | 
 |  | 
 | /* Return message from message catalog.  */ | 
 | char * | 
 | catgets (nl_catd catalog_desc, int set, int message, const char *string) | 
 | { | 
 |   __nl_catd catalog; | 
 |   size_t idx; | 
 |   size_t cnt; | 
 |  | 
 |   /* Be generous if catalog which failed to be open is used.  */ | 
 |   if (catalog_desc == (nl_catd) -1 || ++set <= 0 || message < 0) | 
 |     return (char *) string; | 
 |  | 
 |   catalog = (__nl_catd) catalog_desc; | 
 |  | 
 |   idx = ((set * message) % catalog->plane_size) * 3; | 
 |   cnt = 0; | 
 |   do | 
 |     { | 
 |       if (catalog->name_ptr[idx + 0] == (u_int32_t) set | 
 | 	  && catalog->name_ptr[idx + 1] == (u_int32_t) message) | 
 | 	return (char *) &catalog->strings[catalog->name_ptr[idx + 2]]; | 
 |  | 
 |       idx += catalog->plane_size * 3; | 
 |     } | 
 |   while (++cnt < catalog->plane_depth); | 
 |  | 
 |   __set_errno (ENOMSG); | 
 |   return (char *) string; | 
 | } | 
 |  | 
 |  | 
 | /* Return resources used for loaded message catalog.  */ | 
 | int | 
 | catclose (nl_catd catalog_desc) | 
 | { | 
 |   __nl_catd catalog; | 
 |  | 
 |   /* Be generous if catalog which failed to be open is used.  */ | 
 |   if (catalog_desc == (nl_catd) -1) | 
 |     { | 
 |       __set_errno (EBADF); | 
 |       return -1; | 
 |     } | 
 |  | 
 |   catalog = (__nl_catd) catalog_desc; | 
 |  | 
 | #ifdef _POSIX_MAPPED_FILES | 
 |   if (catalog->status == mmapped) | 
 |     __munmap ((void *) catalog->file_ptr, catalog->file_size); | 
 |   else | 
 | #endif	/* _POSIX_MAPPED_FILES */ | 
 |     if (catalog->status == malloced) | 
 |       free ((void *) catalog->file_ptr); | 
 |     else | 
 |       { | 
 | 	__set_errno (EBADF); | 
 | 	return -1; | 
 |       } | 
 |  | 
 |   free ((void *) catalog); | 
 |  | 
 |   return 0; | 
 | } |