1 /*
   2  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   3  * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
   4  * All rights reserved.
   5  *
   6  * Copyright (c) 2011 The FreeBSD Foundation
   7  * All rights reserved.
   8  * Portions of this software were developed by David Chisnall
   9  * under sponsorship from the FreeBSD Foundation.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions and the following disclaimer.
  16  * 2. Redistributions in binary form must reproduce the above copyright
  17  *    notice, this list of conditions and the following disclaimer in the
  18  *    documentation and/or other materials provided with the distribution.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  */
  32 
  33 #include "lint.h"
  34 #include <stddef.h>
  35 #include <stdlib.h>
  36 #include "ldpart.h"
  37 #include "lmessages.h"
  38 
  39 #define LCMESSAGES_SIZE_FULL (sizeof (struct lc_messages_T) / sizeof (char *))
  40 #define LCMESSAGES_SIZE_MIN \
  41         (offsetof(struct lc_messages_T, yesstr) / sizeof (char *))
  42 
  43 struct xlocale_messages __xlocale_global_messages;
  44 
  45 static char empty[] = "";
  46 
  47 static const struct lc_messages_T _C_messages_locale = {
  48         "^[yY]",        /* yesexpr */
  49         "^[nN]",        /* noexpr */
  50         "yes",          /* yesstr */
  51         "no"            /* nostr */
  52 };
  53 
  54 static void
  55 destruct_messages(void *v)
  56 {
  57         struct xlocale_messages *l = v;
  58 
  59         if (l->buffer != NULL)
  60                 free(l->buffer);
  61 
  62         free(l);
  63 }
  64 
  65 static int
  66 messages_load_locale(struct xlocale_messages *loc, int *using_locale,
  67     const char *name)
  68 {
  69         int ret;
  70         struct lc_messages_T *l = &loc->locale;
  71 
  72         ret = __part_load_locale(name, using_locale,
  73             &loc->buffer, "LC_MESSAGES",
  74             LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN,
  75             (const char **)l);
  76         if (ret == _LDP_LOADED) {
  77                 if (l->yesstr == NULL)
  78                         l->yesstr = empty;
  79                 if (l->nostr == NULL)
  80                         l->nostr = empty;
  81         }
  82 
  83         return (ret);
  84 }
  85 
  86 int
  87 __messages_load_locale(const char *name)
  88 {
  89         return (messages_load_locale(&__xlocale_global_messages,
  90             &__xlocale_global_locale.using_messages_locale, name));
  91 }
  92 
  93 void *
  94 __messages_load(const char *name, locale_t l)
  95 {
  96         struct xlocale_messages *new;
  97 
  98         new = calloc(sizeof(struct xlocale_messages), 1);
  99         /* XXX */
 100         new->header.header.destructor = destruct_messages;
 101         if (messages_load_locale(new, &l->using_messages_locale, name) ==
 102             _LDP_ERROR) {
 103                 xlocale_release(new);
 104                 return (NULL);
 105         }
 106 
 107         return (new);
 108 }
 109 
 110 struct lc_messages_T *
 111 __get_current_messages_locale(locale_t loc)
 112 {
 113         return (loc->using_messages_locale
 114             ? &((struct xlocale_messages *)loc->components[XLC_MESSAGES])->locale
 115             : (struct lc_messages_T *)&_C_messages_locale);
 116 }