0001-01-01 02:30:17 +02:30
/*
0001-01-01 02:30:17 +02:30
Unix SMB / CIFS implementation .
0001-01-01 02:30:17 +02:30
tdb based replacement for gettext
Copyright ( C ) Andrew Tridgell 2001
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
static TDB_CONTEXT * tdb ;
0001-01-01 02:30:17 +02:30
/* the currently selected language */
static char * current_lang ;
0001-01-01 02:30:17 +02:30
/* load a msg file into the tdb */
static BOOL load_msg ( const char * msg_file )
0001-01-01 02:30:17 +02:30
{
char * * lines ;
int num_lines , i ;
char * msgid , * msgstr ;
TDB_DATA key , data ;
0001-01-01 02:30:17 +02:30
lines = file_lines_load ( msg_file , & num_lines ) ;
0001-01-01 02:30:17 +02:30
if ( ! lines ) {
return False ;
}
if ( tdb_lockall ( tdb ) ! = 0 ) return False ;
/* wipe the db */
0001-01-01 02:30:17 +02:30
tdb_traverse ( tdb , tdb_traverse_delete_fn , NULL ) ;
0001-01-01 02:30:17 +02:30
msgid = NULL ;
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < num_lines ; i + + ) {
if ( strncmp ( lines [ i ] , " msgid \" " , 7 ) = = 0 ) {
msgid = lines [ i ] + 7 ;
}
0001-01-01 02:30:17 +02:30
if ( msgid & & strncmp ( lines [ i ] , " msgstr \" " , 8 ) = = 0 ) {
0001-01-01 02:30:17 +02:30
msgstr = lines [ i ] + 8 ;
trim_string ( msgid , NULL , " \" " ) ;
trim_string ( msgstr , NULL , " \" " ) ;
if ( * msgstr = = 0 ) {
msgstr = msgid ;
}
key . dptr = msgid ;
key . dsize = strlen ( msgid ) + 1 ;
data . dptr = msgstr ;
data . dsize = strlen ( msgstr ) + 1 ;
tdb_store ( tdb , key , data , 0 ) ;
0001-01-01 02:30:17 +02:30
msgid = NULL ;
0001-01-01 02:30:17 +02:30
}
}
file_lines_free ( lines ) ;
tdb_unlockall ( tdb ) ;
return True ;
}
/* work out what language to use from locale variables */
0001-01-01 02:30:17 +02:30
static const char * get_lang ( void )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
const char * vars [ ] = { " LANGUAGE " , " LC_ALL " , " LC_LANG " , " LANG " , NULL } ;
0001-01-01 02:30:17 +02:30
int i ;
char * p ;
for ( i = 0 ; vars [ i ] ; i + + ) {
if ( ( p = getenv ( vars [ i ] ) ) ) {
return p ;
}
}
return NULL ;
}
0001-01-01 02:30:17 +02:30
/* initialise the message translation subsystem. If the "lang" argument
is NULL then get the language from the normal environment variables */
BOOL lang_tdb_init ( const char * lang )
0001-01-01 02:30:17 +02:30
{
char * path = NULL ;
0001-01-01 02:30:17 +02:30
char * msg_path = NULL ;
0001-01-01 02:30:17 +02:30
struct stat st ;
static int initialised ;
time_t loadtime ;
0001-01-01 02:30:17 +02:30
/* we only want to init once per process, unless given
an override */
if ( initialised & & ! lang ) return True ;
if ( initialised ) {
/* we are re-initialising, free up any old init */
0001-01-01 02:30:17 +02:30
if ( tdb ) {
tdb_close ( tdb ) ;
tdb = NULL ;
}
0001-01-01 02:30:17 +02:30
SAFE_FREE ( current_lang ) ;
}
0001-01-01 02:30:17 +02:30
initialised = 1 ;
0001-01-01 02:30:17 +02:30
if ( ! lang ) {
/* no lang given, use environment */
lang = get_lang ( ) ;
}
0001-01-01 02:30:17 +02:30
/* if no lang then we don't translate */
0001-01-01 02:30:17 +02:30
if ( ! lang ) return True ;
0001-01-01 02:30:17 +02:30
asprintf ( & msg_path , " %s.msg " , lib_path ( ( const char * ) lang ) ) ;
0001-01-01 02:30:17 +02:30
if ( stat ( msg_path , & st ) ! = 0 ) {
/* the msg file isn't available */
free ( msg_path ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
0001-01-01 02:30:17 +02:30
asprintf ( & path , " %s%s.tdb " , lock_path ( " lang_ " ) , lang ) ;
tdb = tdb_open_log ( path , 0 , TDB_DEFAULT , O_RDWR | O_CREAT , 0644 ) ;
if ( ! tdb ) {
tdb = tdb_open_log ( path , 0 , TDB_DEFAULT , O_RDONLY , 0 ) ;
free ( path ) ;
0001-01-01 02:30:17 +02:30
free ( msg_path ) ;
0001-01-01 02:30:17 +02:30
if ( ! tdb ) return False ;
current_lang = strdup ( lang ) ;
return True ;
0001-01-01 02:30:17 +02:30
}
free ( path ) ;
0001-01-01 02:30:17 +02:30
loadtime = tdb_fetch_int32 ( tdb , " /LOADTIME/ " ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( loadtime = = - 1 | | loadtime < st . st_mtime ) {
0001-01-01 02:30:17 +02:30
load_msg ( msg_path ) ;
0001-01-01 02:30:17 +02:30
tdb_store_int32 ( tdb , " /LOADTIME/ " , ( int ) time ( NULL ) ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
free ( msg_path ) ;
0001-01-01 02:30:17 +02:30
current_lang = strdup ( lang ) ;
return True ;
0001-01-01 02:30:17 +02:30
}
/* translate a msgid to a message string in the current language
returns a string that must be freed by calling lang_msg_free ( )
*/
const char * lang_msg ( const char * msgid )
{
TDB_DATA key , data ;
0001-01-01 02:30:17 +02:30
lang_tdb_init ( NULL ) ;
0001-01-01 02:30:17 +02:30
if ( ! tdb ) return msgid ;
key . dptr = ( char * ) msgid ;
key . dsize = strlen ( msgid ) + 1 ;
data = tdb_fetch ( tdb , key ) ;
/* if the message isn't found then we still need to return a pointer
that can be freed . Pity . */
0001-01-01 02:30:17 +02:30
if ( ! data . dptr )
return strdup ( msgid ) ;
0001-01-01 02:30:17 +02:30
return ( const char * ) data . dptr ;
}
/* free up a string from lang_msg() */
void lang_msg_free ( const char * msgstr )
{
if ( ! tdb ) return ;
free ( ( void * ) msgstr ) ;
}
/*
when the _ ( ) translation macro is used there is no obvious place to free
the resulting string and there is no easy way to give a static pointer .
All we can do is rotate between some static buffers and hope a single d_printf ( )
doesn ' t have more calls to _ ( ) than the number of buffers
*/
const char * lang_msg_rotate ( const char * msgid )
{
# define NUM_LANG_BUFS 4
char * msgstr ;
static pstring bufs [ NUM_LANG_BUFS ] ;
static int next ;
0001-01-01 02:30:17 +02:30
msgstr = ( char * ) lang_msg ( msgid ) ;
0001-01-01 02:30:17 +02:30
if ( ! msgstr ) return msgid ;
pstrcpy ( bufs [ next ] , msgstr ) ;
msgstr = bufs [ next ] ;
next = ( next + 1 ) % NUM_LANG_BUFS ;
return msgstr ;
}
0001-01-01 02:30:17 +02:30
/*
return the current language - needed for language file mappings
*/
char * lang_tdb_current ( void )
{
return current_lang ;
}