root/source3/intl/lang_tdb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. load_msg
  2. get_lang
  3. lang_tdb_init
  4. lang_msg
  5. lang_msg_free
  6. lang_tdb_current

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    tdb based replacement for gettext 
   4    Copyright (C) Andrew Tridgell 2001
   5    
   6    This program is free software; you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 3 of the License, or
   9    (at your option) any later version.
  10    
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15    
  16    You should have received a copy of the GNU General Public License
  17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 #include "includes.h"
  21 
  22 static TDB_CONTEXT *tdb;
  23 
  24 /* the currently selected language */
  25 static char *current_lang;
  26 
  27 
  28 /* load a msg file into the tdb */
  29 static bool load_msg(const char *msg_file)
     /* [<][>][^][v][top][bottom][index][help] */
  30 {
  31         char **lines;
  32         int num_lines, i;
  33         char *msgid, *msgstr;
  34         TDB_DATA data;
  35 
  36         lines = file_lines_load(msg_file, &num_lines, 0, NULL);
  37 
  38         if (!lines) {
  39                 return False;
  40         }
  41 
  42         if (tdb_lockall(tdb) != 0) {
  43                 TALLOC_FREE(lines);
  44                 return False;
  45         }
  46 
  47         /* wipe the db */
  48         tdb_wipe_all(tdb);
  49 
  50         msgid = NULL;
  51         
  52         for (i=0;i<num_lines;i++) {
  53                 if (strncmp(lines[i], "msgid \"", 7) == 0) {
  54                         msgid = lines[i] + 7;
  55                 }
  56                 if (msgid && strncmp(lines[i], "msgstr \"", 8) == 0) {
  57                         msgstr = lines[i] + 8;
  58                         trim_char(msgid, '\0', '\"');
  59                         trim_char(msgstr, '\0', '\"');
  60                         if (*msgstr == 0) {
  61                                 msgstr = msgid;
  62                         }
  63                         all_string_sub(msgid, "\\n", "\n", 0);
  64                         all_string_sub(msgstr, "\\n", "\n", 0);
  65                         data = string_term_tdb_data(msgstr);
  66                         tdb_store_bystring(tdb, msgid, data, 0);
  67                         msgid = NULL;
  68                 }
  69         }
  70 
  71         TALLOC_FREE(lines);
  72         tdb_unlockall(tdb);
  73 
  74         return True;
  75 }
  76 
  77 
  78 /* work out what language to use from locale variables */
  79 static const char *get_lang(void)
     /* [<][>][^][v][top][bottom][index][help] */
  80 {
  81         const char *vars[] = {"LANGUAGE", "LC_ALL", "LC_LANG", "LANG", NULL};
  82         int i;
  83         char *p;
  84 
  85         for (i=0; vars[i]; i++) {
  86                 if ((p = getenv(vars[i]))) {
  87                         return p;
  88                 }
  89         }
  90 
  91         return NULL;
  92 }
  93 
  94 /* initialise the message translation subsystem. If the "lang" argument
  95    is NULL then get the language from the normal environment variables */
  96 bool lang_tdb_init(const char *lang)
     /* [<][>][^][v][top][bottom][index][help] */
  97 {
  98         char *path = NULL;
  99         char *msg_path = NULL;
 100         struct stat st;
 101         static int initialised;
 102         time_t loadtime;
 103         bool result = False;
 104 
 105         /* we only want to init once per process, unless given
 106            an override */
 107         if (initialised && !lang) 
 108                 return True;
 109 
 110         if (initialised) {
 111                 /* we are re-initialising, free up any old init */
 112                 if (tdb) {
 113                         tdb_close(tdb);
 114                         tdb = NULL;
 115                 }
 116                 SAFE_FREE(current_lang);
 117         }
 118 
 119         initialised = 1;
 120 
 121         if (!lang) {
 122                 /* no lang given, use environment */
 123                 lang = get_lang();
 124         }
 125 
 126         /* if no lang then we don't translate */
 127         if (!lang) 
 128                 return True;
 129 
 130         if (asprintf(&msg_path, "%s.msg",
 131                      data_path((const char *)lang)) == -1) {
 132                 DEBUG(0, ("asprintf failed\n"));
 133                 goto done;
 134         }
 135         if (stat(msg_path, &st) != 0) {
 136                 /* the msg file isn't available */
 137                 DEBUG(10, ("lang_tdb_init: %s: %s\n", msg_path, 
 138                            strerror(errno)));
 139                 goto done;
 140         }
 141         
 142         if (asprintf(&path, "%s%s.tdb", lock_path("lang_"), lang) == -1) {
 143                 DEBUG(0, ("asprintf failed\n"));
 144                 goto done;
 145         }
 146 
 147         DEBUG(10, ("lang_tdb_init: loading %s\n", path));
 148 
 149         tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644);
 150         if (!tdb) {
 151                 tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDONLY, 0);
 152                 if (!tdb) {
 153                         DEBUG(10, ("lang_tdb_init: %s: %s\n", path,
 154                                    strerror(errno)));
 155                         goto done;
 156                 }
 157                 current_lang = SMB_STRDUP(lang);
 158                 result = True;
 159                 goto done;
 160         }
 161 
 162         loadtime = tdb_fetch_int32(tdb, "/LOADTIME/");
 163 
 164         if (loadtime == -1 || loadtime < st.st_mtime) {
 165                 load_msg(msg_path);
 166                 tdb_store_int32(tdb, "/LOADTIME/", (int)time(NULL));
 167         }
 168 
 169         current_lang = SMB_STRDUP(lang);
 170         result = True;
 171 
 172  done:
 173         SAFE_FREE(msg_path);
 174         SAFE_FREE(path);
 175 
 176         return result;
 177 }
 178 
 179 /* translate a msgid to a message string in the current language 
 180    returns a string that must be freed by calling lang_msg_free()
 181 */
 182 const char *lang_msg(const char *msgid)
     /* [<][>][^][v][top][bottom][index][help] */
 183 {
 184         TDB_DATA data;
 185         const char *p;
 186         char *q, *msgid_quoted;
 187         int count;
 188 
 189         lang_tdb_init(NULL);
 190 
 191         if (!tdb) return msgid;
 192 
 193         /* Due to the way quotes in msgids are escaped in the msg file we
 194            must replace " with \" before doing a lookup in the tdb. */
 195 
 196         count = 0;
 197 
 198         for(p = msgid; *p; p++) {
 199                 if (*p == '\"')
 200                         count++;
 201         }
 202 
 203         if (!(msgid_quoted = (char *)SMB_MALLOC(strlen(msgid) + count + 1)))
 204                 return msgid;
 205 
 206         /* string_sub() is unsuitable here as it replaces some punctuation
 207            chars with underscores. */
 208 
 209         for(p = msgid, q = msgid_quoted; *p; p++) {
 210                 if (*p == '\"') {
 211                         *q = '\\';
 212                         q++;
 213                 }
 214                 *q = *p;
 215                 q++;
 216         }
 217 
 218         *q = 0;
 219 
 220         data = tdb_fetch_bystring(tdb, msgid_quoted);
 221 
 222         free(msgid_quoted);
 223 
 224         /* if the message isn't found then we still need to return a pointer
 225            that can be freed. Pity. */
 226         if (!data.dptr)
 227                 return SMB_STRDUP(msgid);
 228 
 229         return (const char *)data.dptr;
 230 }
 231 
 232 
 233 /* free up a string from lang_msg() */
 234 void lang_msg_free(const char *msgstr)
     /* [<][>][^][v][top][bottom][index][help] */
 235 {
 236         if (!tdb) return;
 237         free((void *)msgstr);
 238 }
 239 
 240 /* 
 241    return the current language - needed for language file mappings 
 242 */
 243 char *lang_tdb_current(void)
     /* [<][>][^][v][top][bottom][index][help] */
 244 {
 245         return current_lang;
 246 }

/* [<][>][^][v][top][bottom][index][help] */