1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
10
* Sun Industry Standards Source License Version 1.2
11
* =================================================
12
* The contents of this file are subject to the Sun Industry Standards
13
* Source License Version 1.2 (the "License"); You may not use this file
14
* except in compliance with the License. You may obtain a copy of the
15
* License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
17
* Software provided under this License is provided on an "AS IS" basis,
18
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
19
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
20
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
21
* See the License for the specific provisions governing your rights and
22
* obligations concerning the Software.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
39
#include "sge_mtutil.h"
40
#include "basis_types.h"
41
#include "sge_language.h"
44
#include "sge_htable.h"
46
#ifdef __SGE_COMPILE_WITH_GETTEXT__
48
/* MT-NOTE: language_mutex guards all language module function calls */
49
static pthread_mutex_t language_mutex = PTHREAD_MUTEX_INITIALIZER;
51
# define LANGUAGE_LOCK() sge_mutex_lock("language_mutex", SGE_FUNC, __LINE__, &language_mutex)
52
# define LANGUAGE_UNLOCK() sge_mutex_unlock("language_mutex", SGE_FUNC, __LINE__, &language_mutex)
55
* environment variable "SGE_ENABLE_MSG_ID"
56
* supported values: 0 - off
57
* 1 - on for error messages
58
* 2 - on for every message
60
#define SGE_ENABLE_MSG_ID "SGE_ENABLE_MSG_ID"
61
#define PACKAGE "GRIDPACKAGE"
62
#define LOCALEDIR "GRIDLOCALEDIR"
63
#define SGE_DEFAULT_PACKAGE "gridengine"
64
#define SGE_DEFAULT_LOCALEDIR "locale"
67
/* this is to define the functions for the internationalization
70
gettext_func_type gettext_func ;
71
setlocale_func_type setlocale_func ;
72
bindtextdomain_func_type bindtextdomain_func ;
73
textdomain_func_type textdomain_func ;
74
} language_functions_struct;
77
int id; /* message identification number */
78
int category; /* message category: 0 = common */
79
u_long32 counter; /* number of calls */
80
const char* message; /* message string */
81
const char* local_message; /* local translated message */
82
} sge_error_message_t;
84
static pthread_once_t message_id_once = { PTHREAD_ONCE_INIT };
85
static void message_id_once_init(void);
87
static pthread_key_t message_id_key;
88
static void message_id_destroy(void* theState);
90
static language_functions_struct sge_language_functions;
91
static int sge_enable_msg_id = 0; /* used to enable/disable message ids */
92
static int sge_enable_msg_id_to_every_message = 0;
93
static htable sge_message_hash_table = NULL;
95
/* this is to find out if the sge_init_language_func() was called */
96
static bool sge_are_language_functions_installed = false;
98
static int sge_get_message_id_output_implementation(void);
100
/****** uti/language/sge_init_language() **************************************
102
* sge_init_language() -- initialize language package for gettext()
105
* int sge_init_language(char* package, char* localeDir)
109
* starts up the language initialization for gettext(). This
110
* function should be called nearly after the main() function.
112
* sge_init_language_func() must be called first to install the
113
* correct function pointers for gettext() setlocale() etc. etc.
116
* char* package - package name like "gridengine" of binary
118
* (if package is NULL sge_init_language tries
119
* to get the package name from the invironment
120
* variable "GRIDPACKAGE").
121
* char* localeDir - path to the localisazion directory
122
* (if localeDir is NULL sge_init_language
123
* tries to get the localization directory path
124
* from the invironment variable
128
* int state - true for seccess, false on error.
131
* MT-NOTE: sge_init_languagefunc() is guarded by language_mutex
134
* uti/language/sge_init_language()
135
* uti/language/sge_init_language_func()
136
* uti/language/sge_gettext()
137
* uti/language/sge_gettext_()
138
* uti/language/sge_gettext__()
139
* uti/language/sge_get_message_id_output()
140
* uti/language/sge_set_message_id_output()
141
******************************************************************************/
142
int sge_init_languagefunc(char *package, char *localeDir)
144
char* packName = NULL;
146
char* language = NULL;
147
char* language_var = NULL;
148
char* pathName = NULL;
149
char* sge_enable_msg_id_string = NULL;
154
DENTER_(TOP_LAYER, "sge_init_language");
158
DPRINTF_(("****** starting localization procedure ... **********\n"));
161
while ( stop <= 2 ) {
163
/* free memory for evt. second run */
164
if (packName != NULL) {
168
if (locDir != NULL) {
172
if (language != NULL) {
176
if (language_var != NULL) {
181
if (pathName != NULL) {
186
/* try to get the package name */
187
if (package != NULL) {
188
packName = strdup(package);
189
} else if (getenv(PACKAGE) != NULL) {
190
packName = strdup(getenv(PACKAGE));
191
DPRINTF_(("try to get language package name from environment "SFQ"\n",PACKAGE));
193
DPRINTF_(("could not get environment variable "SFQ"\n", PACKAGE));
196
/* no package name given, using default one */
197
if (packName == NULL) {
198
packName = malloc(sizeof(char)*(strlen(SGE_DEFAULT_PACKAGE)+strlen(sge_get_arch()) + 2));
199
sprintf(packName, "%s/%s", sge_get_arch(), SGE_DEFAULT_PACKAGE);
202
/* try to get the localization directory */
203
if (localeDir != NULL) {
204
locDir = strdup(localeDir);
205
} else if ( getenv(LOCALEDIR) != NULL ) {
207
DPRINTF_(("ignoring environment "SFQ"\n",LOCALEDIR ));
209
locDir = strdup(getenv(LOCALEDIR)); /* only the first time */
211
DPRINTF_(("try to get language package directory path from environment "SFQ"\n",LOCALEDIR));
214
DPRINTF_(("could not get environment variable "SFQ"\n", LOCALEDIR));
217
/* no directory given, using default one */
218
if (locDir == NULL) {
219
const char *sge_root = sge_get_root_dir(0, NULL, 0, 0);
222
if (sge_root != NULL) {
223
root = strdup(sge_root);
226
if ( root == NULL ) {
227
locDir = strdup("/usr/lib/locale");
229
locDir = malloc(sizeof(char)*(strlen(root)+strlen(SGE_DEFAULT_LOCALEDIR) + 100));
230
sprintf(locDir, "%s/%s", root, SGE_DEFAULT_LOCALEDIR);
236
/* try to get a language stylename (only for output of package path) */
238
if (getenv("LANGUAGE") != NULL) {
239
language_var = strdup(getenv("LANGUAGE"));
241
if (getenv("LANG") != NULL) {
242
language_var = strdup(getenv("LANG"));
246
if (language_var == NULL) {
247
DPRINTF_(("environment LANGUAGE or LANG is not set; no language selected - using defaults\n"));
248
language_var = strdup("C");
251
/* get correct language value */
252
if ( sge_language_functions.setlocale_func != NULL ) {
254
help1 = sge_language_functions.setlocale_func(LC_MESSAGES, "");
256
char* slash_pos = NULL;
257
DPRINTF_(("setlocale() returns \"%s\"\n",help1));
258
slash_pos = strstr(help1,"_");
259
if (slash_pos != NULL) {
260
char* tmp_lang = NULL;
261
DPRINTF_(("cutting of language string after \"_\":\n"));
262
tmp_lang = strdup(help1);
263
slash_pos = strstr(tmp_lang,"_");
264
*slash_pos = 0; /* cut off "_" */
265
language = strdup(tmp_lang);
270
language = strdup(help1);
273
DPRINTF_(("setlocale() returns NULL"));
274
language = strdup(language_var);
278
/* packName, locDir and language strings are now surely not NULL,
279
so we can now try to setup the choosen language package (*.mo - file) */
280
pathName = malloc(sizeof(char)*(strlen(locDir)+strlen(language)+strlen(packName)+100));
281
sprintf(pathName,"%s/%s/LC_MESSAGES/%s.mo",locDir,language,packName);
282
DPRINTF_(("locale directory: >%s<\n",locDir));
283
DPRINTF_(("package file: >%s.mo<\n",packName));
284
DPRINTF_(("language (LANG): >%s<\n",language));
285
DPRINTF_(("loading message file: %s\n",pathName ));
287
/* is the package file allright */
288
back = open (pathName, O_RDONLY);
290
DPRINTF_(("found message file - ok\n"));
295
DPRINTF_(("could not open message file - error\n"));
299
stop = 2; /* only when stop = 1: Try to repeat without LOCALEDIR environment variable */
305
/* now startup the language package for gettext */
306
/* setlocale(LC_ALL, ""); */
308
if ( (sge_language_functions.setlocale_func != NULL ) &&
309
(sge_language_functions.bindtextdomain_func != NULL) &&
310
(sge_language_functions.textdomain_func != NULL ) &&
311
(sge_are_language_functions_installed == true ) ) {
313
help1 = sge_language_functions.setlocale_func(LC_MESSAGES, "");
315
DPRINTF_(("setlocale() returns \"%s\"\n",help1));
317
DPRINTF_(("setlocale() returns NULL\n"));
319
help1 = sge_language_functions.bindtextdomain_func(packName, locDir );
321
DPRINTF_(("bindtextdomain() returns \"%s\"\n",help1));
323
DPRINTF_(("bindtextdomain() returns NULL\n"));
325
help1 = sge_language_functions.textdomain_func(packName);
327
DPRINTF_(("textdomain() returns \"%s\"\n",help1));
329
DPRINTF_(("textdomain() returns NULL\n"));
332
DPRINTF_(("sge_init_language() called without valid sge_language_functions pointer!\n"));
347
if (success == true) {
348
sge_enable_msg_id = 1;
351
sge_enable_msg_id_string = getenv(SGE_ENABLE_MSG_ID);
352
if (sge_enable_msg_id_string != NULL) {
354
DPRINTF_(("SGE_ENABLE_MSG_ID is set to \"%s\"\n", sge_enable_msg_id_string));
355
env_value = atoi(sge_enable_msg_id_string);
356
if (env_value == 0) {
357
sge_enable_msg_id = 0;
359
sge_enable_msg_id = 1;
361
if (env_value == 2) {
362
sge_enable_msg_id_to_every_message = 1;
367
if (sge_enable_msg_id == 0) {
368
DPRINTF_(("error id output : disabled\n"));
370
DPRINTF_(("error id output : enabled\n"));
373
if (success == true) {
374
DPRINTF_(("****** starting localization procedure ... success **\n"));
376
DPRINTF_(("****** starting localization procedure ... failed **\n"));
384
/****** uti/language/sge_init_language_func() **********************************
386
* sge_init_language() -- install language functions
389
* void sge_init_language_func(gettext_func_type new_gettext,
390
* setlocale_func_type new_setlocale,
391
* bindtextdomain_func_type new_bindtextdomain,
392
* textdomain_func_type new_textdomain);
395
* set the function pointer for the gettext(), setlocale(),
396
* bindtextdomain() and textdomain() function calls. This function
397
* must called before any call to sge_init_language() and
401
* gettext_func_type - pointer for gettext()
402
* setlocale_func_type - pointer for setlocale()
403
* bindtextdomain_func_type - pointer for bindtextdomain()
404
* textdomain_func_type - pointer for textdomain()
407
* MT-NOTE: sge_init_language_func() is guarded by language_mutex
410
* uti/language/sge_init_language()
411
* uti/language/sge_init_language_func()
412
* uti/language/sge_gettext()
413
* uti/language/sge_gettext_()
414
* uti/language/sge_gettext__()
415
* uti/language/sge_get_message_id_output()
416
* uti/language/sge_set_message_id_output()
417
******************************************************************************/
418
void sge_init_language_func(gettext_func_type new_gettext,
419
setlocale_func_type new_setlocale,
420
bindtextdomain_func_type new_bindtextdomain,
421
textdomain_func_type new_textdomain)
423
DENTER_(TOP_LAYER, "sge_init_language_func");
427
/* initialize the functions pointer to NULL */
428
sge_language_functions.gettext_func = NULL;
429
sge_language_functions.setlocale_func = NULL;
430
sge_language_functions.bindtextdomain_func = NULL;
431
sge_language_functions.textdomain_func = NULL;
433
/* ok, the functions have now NULL pointer */
434
sge_are_language_functions_installed = true;
436
/* set the new functions */
437
if (new_gettext != NULL) {
438
sge_language_functions.gettext_func = new_gettext;
441
if (new_setlocale != NULL) {
442
sge_language_functions.setlocale_func = new_setlocale;
445
if (new_bindtextdomain != NULL) {
446
sge_language_functions.bindtextdomain_func = new_bindtextdomain;
449
if (new_textdomain != NULL) {
450
sge_language_functions.textdomain_func = new_textdomain;
458
/****** uti/language/sge_set_message_id_output() *******************************
460
* sge_set_message_id_output() -- enable message id number adding
463
* void sge_set_message_id_output(int flag)
466
* This procedure is used to enable the adding of message id's when
467
* showing error messages. This function is used in the macro
468
* SGE_ADD_MSG_ID(x) to enable the message id for errors.
471
* int flag - 0 = off ; 1 = on
474
* MT-NOTE: sge_set_message_id_output() is guarded by language_mutex
477
* uti/language/sge_init_language()
478
* uti/language/sge_init_language_func()
479
* uti/language/sge_gettext()
480
* uti/language/sge_gettext_()
481
* uti/language/sge_gettext__()
482
* uti/language/sge_get_message_id_output()
483
* uti/language/sge_set_message_id_output()
484
*******************************************************************************/
485
void sge_set_message_id_output(int flag) {
488
DENTER_(CULL_LAYER, "sge_set_message_id_output");
490
pthread_once(&message_id_once, message_id_once_init);
492
buf = (int*) pthread_getspecific(message_id_key);
501
/****** uti/language/sge_get_message_id_output() *******************************
503
* sge_get_message_id_output() -- check if message id should be added
506
* int sge_get_message_id_output(void)
509
* This function returns the value stored in the static global
510
* variable sge_message_id_view_flag.
513
* int - value of sge_message_id_view_flag
516
* MT-NOTE: sge_get_message_id_output() is guarded by language_mutex
519
* uti/language/sge_init_language()
520
* uti/language/sge_init_language_func()
521
* uti/language/sge_gettext()
522
* uti/language/sge_gettext_()
523
* uti/language/sge_gettext__()
524
* uti/language/sge_get_message_id_output()
525
* uti/language/sge_set_message_id_output()
526
* uti/language/sge_get_message_id_output_implementation()
527
*******************************************************************************/
528
int sge_get_message_id_output(void)
532
DENTER_(TOP_LAYER, "sge_get_message_id_output");
535
ret = sge_get_message_id_output_implementation();
541
/****** uti/language/sge_get_message_id_output_implementation() ***************
543
* sge_get_message_id_output_implementation() -- pure implementation of
544
* sge_get_message_id_output_implementation() that does not lock
548
* int sge_get_message_id_output_implementation(void)
551
* When the sge_get_message_id_output() functionality is needed from within
552
* the language modules the language_mutex may not be obtained because this
553
* mutex is already owned by the same thread.
556
* int - value of sge_message_id_view_flag
559
* MT-NOTE: The caller of sge_get_message_id_output_implementation() must
560
* MT-NOTE: have obtained the language_mutex mutex due to access to
561
* MT-NOTE: 'sge_enable_msg_id' and 'sge_enable_msg_id_to_every_message'.
564
* uti/language/sge_init_language()
565
* uti/language/sge_init_language_func()
566
* uti/language/sge_gettext()
567
* uti/language/sge_gettext_()
568
* uti/language/sge_gettext__()
569
* uti/language/sge_get_message_id_output()
570
* uti/language/sge_set_message_id_output()
571
*******************************************************************************/
572
static int sge_get_message_id_output_implementation(void)
575
DENTER_(CULL_LAYER, "sge_get_message_id_output_implementation");
577
if (sge_enable_msg_id_to_every_message == 1) {
581
if (sge_enable_msg_id == 0) {
585
pthread_once(&message_id_once, message_id_once_init);
587
buf = (int*) pthread_getspecific(message_id_key);
596
/****** uti/language/sge_gettext() *********************************************
598
* sge_gettext() -- dummy gettext() function
601
* const char* sge_gettext(char *x)
604
* This function returns the given argument
610
* const char* - input string
613
* uti/language/sge_init_language()
614
* uti/language/sge_init_language_func()
615
* uti/language/sge_gettext()
616
* uti/language/sge_gettext_()
617
* uti/language/sge_gettext__()
618
* uti/language/sge_get_message_id_output()
619
* uti/language/sge_set_message_id_output()
620
*******************************************************************************/
621
const char *sge_gettext(char *x) {
625
/****** uti/language/sge_gettext_() ********************************************
627
* sge_gettext_() -- add error id to message
630
* const char* sge_gettext_(int msg_id, const char *msg_str)
633
* This function is used for adding the message id to the translated
634
* gettext message string. The message id is only added when the
635
* function sge_get_message_id_output() returns not "0" and the
636
* message string contains at least one SPACE character.
639
* int msg_id - message id
640
* const char *msg_str - message to translate
643
* const char* - translated (L10N) message with message id
646
* uti/language/sge_init_language()
647
* uti/language/sge_init_language_func()
648
* uti/language/sge_gettext()
649
* uti/language/sge_gettext_()
650
* uti/language/sge_gettext__()
651
* uti/language/sge_get_message_id_output()
652
* uti/language/sge_set_message_id_output()
653
*******************************************************************************/
654
const char *sge_gettext_(int msg_id, const char *msg_str)
657
#ifndef __SGE_COMPILE_WITH_GETTEXT__
661
sge_error_message_t *l;
666
DENTER_(CULL_LAYER, "sge_gettext_");
670
if (msg_str == NULL) {
675
/* check if message is not just one word (strstr) */
676
if ( (sge_get_message_id_output_implementation() != 0) &&
677
(strstr(msg_str, " ") != NULL) ) {
679
if (sge_message_hash_table == NULL) {
680
sge_message_hash_table = sge_htable_create(8, /* 2^8 = 256 table start size */
685
if (sge_htable_lookup(sge_message_hash_table, &key, (const void**)&message_p.p) == False) {
687
sge_error_message_t* new_mp = NULL;
688
char* org_message = NULL;
689
char* trans_message = NULL;
690
const char* gettext_return_string = NULL;
693
gettext_return_string = sge_gettext__((char*)msg_str);
695
org_message = malloc(strlen(msg_str)+1);
696
trans_message = malloc(strlen(gettext_return_string)+1+8); /* max "(99999) "*/
697
new_mp = malloc(sizeof(sge_error_message_t));
698
if (new_mp != NULL && org_message != NULL && trans_message != NULL) {
699
DPRINTF_(("add new hash table entry for message id: %d\n",msg_id));
701
new_mp->category = 0;
703
strcpy(org_message, msg_str);
704
new_mp->message = org_message;
705
if (msg_id <= 99999) {
706
sprintf( trans_message , "[%d] %s", msg_id, gettext_return_string);
708
sprintf( trans_message , "%s", gettext_return_string);
710
new_mp->local_message = trans_message;
712
sge_htable_store(sge_message_hash_table, &key, new_mp);
713
DRETURN_(new_mp->local_message);
717
DPRINTF_(("using old hash entry for message id: %d\n",msg_id));
718
if (strcmp(msg_str,message_p.l->message) != 0) {
719
DPRINTF_(("duplicate message id error: returning gettext() message"));
720
DPRINTF_(("msg in : \"%s\"\n",msg_str));
721
DPRINTF_(("msg out: \"%s\"\n",message_p.l->message));
722
DRETURN_(sge_gettext__((char*)msg_str));
724
message_p.l->counter = (message_p.l->counter) + 1;
725
DPRINTF_(("message count: "sge_U32CFormat"\n", sge_u32c(message_p.l->counter)));
726
DRETURN_(message_p.l->local_message);
730
DRETURN_(sge_gettext__((char*)msg_str));
734
/****** uti/language/sge_gettext__() *******************************************
736
* sge_gettext__() -- get translated message from message file
739
* char *sge_gettext__(char *x)
742
* makes a call to sge_language_functions.gettext_func(x) if
743
* gettext_func is not NULL, otherwise it returns the input
747
* char *x - pointer to message which should be internationalizied
750
* char* - pointer internationalized message
753
* MT-NOTE: not guarded b/c sge_gettext__() is used only in infotext utility
756
* uti/language/sge_init_language()
757
* uti/language/sge_init_language_func()
758
* uti/language/sge_gettext()
759
* uti/language/sge_gettext_()
760
* uti/language/sge_gettext__()
761
* uti/language/sge_get_message_id_output()
762
* uti/language/sge_set_message_id_output()
763
*******************************************************************************/
764
const char *sge_gettext__(char *x)
767
DENTER_(BASIS_LAYER, "sge_gettext__");
769
if ( (sge_language_functions.gettext_func != NULL) &&
770
(sge_are_language_functions_installed == true) ) {
771
z = sge_language_functions.gettext_func(x);
774
DPRINTF_(("sge_gettext() called without valid gettext function pointer!\n"));
779
/*DPRINTF_(("gettext: '%s' -> '%s'\n", x ? x : "", z ? z : ""));*/
784
static void message_id_destroy(void* theState)
786
if (theState != NULL) {
791
static void message_id_once_init(void)
795
pthread_key_create(&message_id_key, &message_id_destroy);
797
buf = (int*) sge_malloc(sizeof(int));
800
res = pthread_setspecific(message_id_key, (const void*)buf);
803
fprintf(stderr, "pthread_set_specific(%s) failed: %s\n", "log_buffer_getspecific", strerror(res));