15bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Implementation of the textdomain(3) function.
2b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o   Copyright (C) 1995-1998, 2000-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.
135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore 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.  */
185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef HAVE_CONFIG_H
205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <config.h>
215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
23a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <stdlib.h>
24a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <string.h>
255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
26a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#ifdef _LIBC
27a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# include <libintl.h>
285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else
29a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# include "libgnuintl.h"
305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
31a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include "gettextP.h"
325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC
34a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* We have to handle multi-threaded applications.  */
35a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# include <bits/libc-lock.h>
365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else
37a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* Provide dummy implementation if this is outside glibc.  */
38a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define __libc_rwlock_define(CLASS, NAME)
39a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define __libc_rwlock_wrlock(NAME)
40a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define __libc_rwlock_unlock(NAME)
41a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#endif
42a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
43a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* The internal variables in the standalone libintl.a must have different
44a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   names than the internal variables in GNU libc, otherwise programs
45a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   using libintl.a cannot be linked statically.  */
46a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#if !defined _LIBC
47a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define _nl_default_default_domain libintl_nl_default_default_domain
48a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define _nl_current_default_domain libintl_nl_current_default_domain
495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
505bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
515bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* @@ end of prolog @@ */
525bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Name of the default text domain.  */
54a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'oextern const char _nl_default_default_domain[] attribute_hidden;
555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Default text domain in which entries for gettext(3) are to be found.  */
57a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'oextern const char *_nl_current_default_domain attribute_hidden;
585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Names for the libintl functions are a problem.  They must not clash
615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   with existing names and they should follow ANSI C.  But this source
625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   code is also used in GNU C Library where the names have a __
635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   prefix.  So we have to make a difference here.  */
645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC
655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# define TEXTDOMAIN __textdomain
665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# ifndef strdup
675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#  define strdup(str) __strdup (str)
685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# endif
695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else
70a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# define TEXTDOMAIN libintl_textdomain
715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
73a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o/* Lock variable to protect the global data in the gettext implementation.  */
74a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
75a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Set the current default message catalog to DOMAINNAME.
775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   If DOMAINNAME is null, return the current default.
785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   If DOMAINNAME is "", reset to the default of "messages".  */
795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ochar *
80b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'oTEXTDOMAIN (const char *domainname)
815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
82a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  char *new_domain;
83a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  char *old_domain;
845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* A NULL pointer requests the current setting.  */
865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (domainname == NULL)
875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    return (char *) _nl_current_default_domain;
885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
89a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  __libc_rwlock_wrlock (_nl_state_lock);
90a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
91a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  old_domain = (char *) _nl_current_default_domain;
925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* If domain name is the null string set to default domain "messages".  */
945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (domainname[0] == '\0'
955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      || strcmp (domainname, _nl_default_default_domain) == 0)
96a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    {
97a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      _nl_current_default_domain = _nl_default_default_domain;
98a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      new_domain = (char *) _nl_current_default_domain;
99a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    }
100a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  else if (strcmp (domainname, old_domain) == 0)
101a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    /* This can happen and people will use it to signal that some
102a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o       environment variable changed.  */
103a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    new_domain = old_domain;
1045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  else
1055bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      /* If the following malloc fails `_nl_current_default_domain'
1075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	 will be NULL.  This value will be returned and so signals we
1085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	 are out of core.  */
1095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if defined _LIBC || defined HAVE_STRDUP
110a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      new_domain = strdup (domainname);
1115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else
1125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      size_t len = strlen (domainname) + 1;
113a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      new_domain = (char *) malloc (len);
114a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      if (new_domain != NULL)
115a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	memcpy (new_domain, domainname, len);
1165bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
117a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
118a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      if (new_domain != NULL)
119a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	_nl_current_default_domain = new_domain;
120a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    }
121a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
122a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* We use this possibility to signal a change of the loaded catalogs
123a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     since this is most likely the case and there is no other easy we
124a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o     to do it.  Do it only when the call was successful.  */
125a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  if (new_domain != NULL)
126a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    {
127a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      ++_nl_msg_cat_cntr;
128a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
129a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      if (old_domain != new_domain && old_domain != _nl_default_default_domain)
130a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	free (old_domain);
1315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
133a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  __libc_rwlock_unlock (_nl_state_lock);
1345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
135a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  return new_domain;
1365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
1375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC
1395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Alias for function name in GNU C Library.  */
1405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'oweak_alias (__textdomain, textdomain);
1415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
142