15bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Handle aliases for locale names. 2b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc. 35bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 4a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o This program is free software; you can redistribute it and/or modify it 5a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o under the terms of the GNU Library General Public License as published 6a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o by the Free Software Foundation; either version 2, or (at your option) 75bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o any later version. 85bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 95bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o This program is distributed in the hope that it will be useful, 105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o but WITHOUT ANY WARRANTY; without even the implied warranty of 11a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o Library General Public License for more details. 13a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 14a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o You should have received a copy of the GNU Library General Public 15a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o License along with this program; if not, write to the Free Software 16a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 17a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o USA. */ 18a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 19a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* Tell glibc's <string.h> to provide a prototype for mempcpy(). 20a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o This must come before <config.h> because <config.h> may include 21a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o <features.h>, and once <features.h> has been included, it's too late. */ 22a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#ifndef _GNU_SOURCE 23a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define _GNU_SOURCE 1 24a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef HAVE_CONFIG_H 275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <config.h> 285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif 295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <ctype.h> 315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <stdio.h> 32a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#if defined _LIBC || defined HAVE___FSETLOCKING 33a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# include <stdio_ext.h> 34a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <sys/types.h> 365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef __GNUC__ 38b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# undef alloca 395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define alloca __builtin_alloca 405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define HAVE_ALLOCA 1 415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else 42b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# ifdef _MSC_VER 43b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# include <malloc.h> 44b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# define alloca _alloca 455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# else 46b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# if defined HAVE_ALLOCA_H || defined _LIBC 47b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# include <alloca.h> 485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# else 49b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# ifdef _AIX 50b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o #pragma alloca 51b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# else 52b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# ifndef alloca 535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ochar *alloca (); 54b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# endif 555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif 565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif 575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif 585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif 595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 60a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <stdlib.h> 61a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <string.h> 625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include "gettextP.h" 645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 65b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o#if ENABLE_RELOCATABLE 66b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# include "relocatable.h" 67b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o#else 68b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# define relocate(pathname) (pathname) 69b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o#endif 70b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o 715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* @@ end of prolog @@ */ 725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC 745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Rename the non ANSI C functions. This is required by the standard 755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o because some ANSI C functions will require linking with this object 765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o file and the name space must not be polluted. */ 775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define strcasecmp __strcasecmp 785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 79a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# ifndef mempcpy 80a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define mempcpy __mempcpy 81a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# endif 825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define HAVE_MEMPCPY 1 83a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define HAVE___FSETLOCKING 1 845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* We need locking here since we can be called from different places. */ 865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <bits/libc-lock.h> 875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o__libc_lock_define_initialized (static, lock); 895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif 905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 91a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#ifndef internal_function 92a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define internal_function 93a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 95a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* Some optimizations for glibc. */ 96a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#ifdef _LIBC 97a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define FEOF(fp) feof_unlocked (fp) 98a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp) 99a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#else 100a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define FEOF(fp) feof (fp) 101a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define FGETS(buf, n, fp) fgets (buf, n, fp) 102a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 103a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 104a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* For those losing systems which don't have `alloca' we have to add 1055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o some additional code emulating it. */ 1065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef HAVE_ALLOCA 107a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define freea(p) /* nothing */ 1085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else 109a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define alloca(n) malloc (n) 110a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define freea(p) free (p) 111a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 112a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 113b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o#if defined _LIBC_REENTRANT || HAVE_DECL_FGETS_UNLOCKED 114a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# undef fgets 115a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define fgets(buf, len, s) fgets_unlocked (buf, len, s) 116a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 117b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o#if defined _LIBC_REENTRANT || HAVE_DECL_FEOF_UNLOCKED 118a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# undef feof 119a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define feof(s) feof_unlocked (s) 120a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 1215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostruct alias_map 1245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{ 1255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o const char *alias; 1265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o const char *value; 1275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}; 1285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 130b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o#ifndef _LIBC 131b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o# define libc_freeres_ptr(decl) decl 132b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o#endif 133b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o 134b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'olibc_freeres_ptr (static char *string_space); 135a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'ostatic size_t string_space_act; 136a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'ostatic size_t string_space_max; 137b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'olibc_freeres_ptr (static struct alias_map *map); 138a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'ostatic size_t nmap; 139a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'ostatic size_t maxmap; 1405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Prototypes for local functions. */ 143b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'ostatic size_t read_alias_file (const char *fname, int fname_len) 1445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o internal_function; 145b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'ostatic int extend_alias_table (void); 146b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'ostatic int alias_compare (const struct alias_map *map1, 147b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o const struct alias_map *map2); 1485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1505bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oconst char * 151b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o_nl_expand_alias (const char *name) 1525bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{ 153a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o static const char *locale_alias_path; 1545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o struct alias_map *retval; 1555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o const char *result = NULL; 1565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o size_t added; 1575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC 1595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o __libc_lock_lock (lock); 1605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif 1615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 162a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o if (locale_alias_path == NULL) 163a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o locale_alias_path = LOCALE_ALIAS_PATH; 164a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 1655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o do 1665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 1675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o struct alias_map item; 1685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o item.alias = name; 1705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (nmap > 0) 1725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o retval = (struct alias_map *) bsearch (&item, map, nmap, 1735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o sizeof (struct alias_map), 174b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o (int (*) (const void *, 175b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o const void *) 1765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ) alias_compare); 1775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o else 1785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o retval = NULL; 1795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* We really found an alias. Return the value. */ 1815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (retval != NULL) 1825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 1835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o result = retval->value; 1845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o break; 1855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 1865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 1875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Perhaps we can find another alias file. */ 1885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o added = 0; 1895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o while (added == 0 && locale_alias_path[0] != '\0') 1905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 1915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o const char *start; 1925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 193a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o while (locale_alias_path[0] == PATH_SEPARATOR) 1945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++locale_alias_path; 1955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o start = locale_alias_path; 1965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 197a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o while (locale_alias_path[0] != '\0' 198a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o && locale_alias_path[0] != PATH_SEPARATOR) 1995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++locale_alias_path; 2005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (start < locale_alias_path) 2025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o added = read_alias_file (start, locale_alias_path - start); 2035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 2045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 2055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o while (added != 0); 2065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC 2085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o __libc_lock_unlock (lock); 2095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif 2105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o return result; 2125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o} 2135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2155bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic size_t 2165bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ointernal_function 217b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'oread_alias_file (const char *fname, int fname_len) 2185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{ 2195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o FILE *fp; 2205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o char *full_fname; 2215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o size_t added; 2225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o static const char aliasfile[] = "/locale.alias"; 2235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o full_fname = (char *) alloca (fname_len + sizeof aliasfile); 2255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef HAVE_MEMPCPY 2265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o mempcpy (mempcpy (full_fname, fname, fname_len), 2275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o aliasfile, sizeof aliasfile); 2285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else 2295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o memcpy (full_fname, fname, fname_len); 2305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); 2315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif 2325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 233b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o fp = fopen (relocate (full_fname), "r"); 234a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o freea (full_fname); 2355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (fp == NULL) 236a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o return 0; 237a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 238a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#ifdef HAVE___FSETLOCKING 239a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o /* No threads present. */ 240a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o __fsetlocking (fp, FSETLOCKING_BYCALLER); 241a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif 2425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o added = 0; 244a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o while (!FEOF (fp)) 2455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 2465bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* It is a reasonable approach to use a fix buffer here because 2475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o a) we are only interested in the first two fields 2485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o b) these fields must be usable as file names and so must not 2495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o be that long 250b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o We avoid a multi-kilobyte buffer here since this would use up 251b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o stack space which we might not have if the program ran out of 252b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o memory. */ 253b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o char buf[400]; 254a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o char *alias; 255a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o char *value; 256a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o char *cp; 2575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 258a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o if (FGETS (buf, sizeof buf, fp) == NULL) 2595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* EOF reached. */ 2605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o break; 2615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o cp = buf; 2635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Ignore leading white space. */ 264a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o while (isspace ((unsigned char) cp[0])) 2655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++cp; 2665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* A leading '#' signals a comment line. */ 2685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (cp[0] != '\0' && cp[0] != '#') 2695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 2705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o alias = cp++; 271a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) 2725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++cp; 2735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Terminate alias name. */ 2745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (cp[0] != '\0') 2755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o *cp++ = '\0'; 2765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Now look for the beginning of the value. */ 278a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o while (isspace ((unsigned char) cp[0])) 2795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++cp; 2805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (cp[0] != '\0') 2825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 2835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o size_t alias_len; 2845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o size_t value_len; 2855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 2865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o value = cp++; 287a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) 2885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++cp; 2895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Terminate value. */ 2905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (cp[0] == '\n') 2915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 2925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* This has to be done to make the following test 2935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o for the end of line possible. We are looking for 2945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o the terminating '\n' which do not overwrite here. */ 2955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o *cp++ = '\0'; 2965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o *cp = '\n'; 2975bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 2985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o else if (cp[0] != '\0') 2995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o *cp++ = '\0'; 3005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (nmap >= maxmap) 302a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o if (__builtin_expect (extend_alias_table (), 0)) 303a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o return added; 3045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o alias_len = strlen (alias) + 1; 3065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o value_len = strlen (value) + 1; 3075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (string_space_act + alias_len + value_len > string_space_max) 3095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 3105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Increase size of memory pool. */ 3115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o size_t new_size = (string_space_max 3125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o + (alias_len + value_len > 1024 3135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ? alias_len + value_len : 1024)); 3145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o char *new_pool = (char *) realloc (string_space, new_size); 3155bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (new_pool == NULL) 316a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o return added; 317a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 318a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o if (__builtin_expect (string_space != new_pool, 0)) 3195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 320a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o size_t i; 321a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 322a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o for (i = 0; i < nmap; i++) 323a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o { 324a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o map[i].alias += new_pool - string_space; 325a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o map[i].value += new_pool - string_space; 326a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o } 3275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 328a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o 3295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o string_space = new_pool; 3305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o string_space_max = new_size; 3315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 3325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o map[nmap].alias = memcpy (&string_space[string_space_act], 3345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o alias, alias_len); 3355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o string_space_act += alias_len; 3365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o map[nmap].value = memcpy (&string_space[string_space_act], 3385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o value, value_len); 3395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o string_space_act += value_len; 3405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++nmap; 3425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++added; 3435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 3445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 345b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o 346b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o /* Possibly not the whole line fits into the buffer. Ignore 347b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o the rest of the line. */ 348b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o while (strchr (buf, '\n') == NULL) 349b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o if (FGETS (buf, sizeof buf, fp) == NULL) 350b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o /* Make sure the inner loop will be left. The outer loop 351b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o will exit at the `feof' test. */ 352b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o break; 3535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 3545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Should we test for ferror()? I think we have to silently ignore 3565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o errors. --drepper */ 3575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o fclose (fp); 3585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (added > 0) 3605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o qsort (map, nmap, sizeof (struct alias_map), 361b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o (int (*) (const void *, const void *)) alias_compare); 3625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o return added; 3645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o} 3655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 367a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'ostatic int 3685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oextend_alias_table () 3695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{ 3705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o size_t new_size; 3715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o struct alias_map *new_map; 3725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o new_size = maxmap == 0 ? 100 : 2 * maxmap; 3745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o new_map = (struct alias_map *) realloc (map, (new_size 3755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o * sizeof (struct alias_map))); 3765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (new_map == NULL) 3775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* Simply don't extend: we don't have any more core. */ 378a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o return -1; 3795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o map = new_map; 3815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o maxmap = new_size; 382a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o return 0; 3835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o} 3845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic int 387b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'oalias_compare (const struct alias_map *map1, const struct alias_map *map2) 3885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{ 3895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if defined _LIBC || defined HAVE_STRCASECMP 3905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o return strcasecmp (map1->alias, map2->alias); 3915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else 3925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o const unsigned char *p1 = (const unsigned char *) map1->alias; 3935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o const unsigned char *p2 = (const unsigned char *) map2->alias; 3945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o unsigned char c1, c2; 3955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (p1 == p2) 3975bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o return 0; 3985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 3995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o do 4005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o { 4015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o /* I know this seems to be odd but the tolower() function in 4025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o some systems libc cannot handle nonalpha characters. */ 4035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o c1 = isupper (*p1) ? tolower (*p1) : *p1; 4045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o c2 = isupper (*p2) ? tolower (*p2) : *p2; 4055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o if (c1 == '\0') 4065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o break; 4075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++p1; 4085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o ++p2; 4095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o } 4105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o while (c1 == c2); 4115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o 4125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o return c1 - c2; 4135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif 4145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o} 415