X-Git-Url: https://git.dlugolecki.net.pl/?a=blobdiff_plain;f=gedcom%2Fencoding.c;h=d97f63c99aec7a971be936f73b92dd45125d4003;hb=ed06b5a50e066bc87bd5e795ab3555bf86e520d9;hp=23e65bdf3324cab0badaa554d85178a540e2cfb9;hpb=4fe12100984a41d439dc9b4138d6cd8df36285f8;p=gedcom-parse.git diff --git a/gedcom/encoding.c b/gedcom/encoding.c index 23e65bd..d97f63c 100644 --- a/gedcom/encoding.c +++ b/gedcom/encoding.c @@ -99,6 +99,54 @@ void cleanup_encodings() hash_free(encodings); } +/* Let function be called before main() */ +void update_gconv_search_path() __attribute__ ((constructor)); + +/* Note: + + The environment variable GCONV_PATH has to be adjusted before the very + first call of iconv_open. For the most general case, it means that we + have to make our own constructor here (in case some of the other library + constructors would use iconv_open). + + However, it looks like a change of an environment variable in a constructor + doesn't always survive until the main() function. This is the case if + the environment variable is a new one, for which there was no room yet + in the initial environment. The initial environment is located on the + stack, but when variables are added, it is moved to the heap (to be able + to grow). Now, the main function takes again the one from the stack, not + from the heap, so changes are lost. + + For this, the function below will also be called in gedcom_init(), which + needs to be called as early as possible in the program. + */ + +void update_gconv_search_path() +{ + char *gconv_path; + /* Add gedcom data directory to gconv search path */ + gconv_path = getenv(GCONV_SEARCH_PATH); + if (gconv_path == NULL || strstr(gconv_path, PKGDATADIR) == NULL) { + char *new_gconv_path; + if (gconv_path == NULL) { + new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH) + + strlen(PKGDATADIR) + + 2); + sprintf(new_gconv_path, "%s=%s", GCONV_SEARCH_PATH, PKGDATADIR); + } + else { + new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH) + + strlen(gconv_path) + + strlen(PKGDATADIR) + + 3); + sprintf(new_gconv_path, "%s=%s:%s", + GCONV_SEARCH_PATH, gconv_path, PKGDATADIR); + } + /* Ignore failures of putenv (can't do anything about it anyway) */ + putenv(new_gconv_path); + } +} + void init_encodings() { if (encodings == NULL) { @@ -107,33 +155,9 @@ void init_encodings() char gedcom_n[MAXBUF + 1]; char charwidth[MAXBUF + 1]; char iconv_n[MAXBUF + 1]; - char *gconv_path; atexit(cleanup_encodings); - /* Add gedcom data directory to gconv search path */ - gconv_path = getenv(GCONV_SEARCH_PATH); - if (gconv_path == NULL || strstr(gconv_path, PKGDATADIR) == NULL) { - char *new_gconv_path; - if (gconv_path == NULL) { - new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH) - + strlen(PKGDATADIR) - + 2); - sprintf(new_gconv_path, "%s=%s", GCONV_SEARCH_PATH, PKGDATADIR); - } - else { - new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH) - + strlen(gconv_path) - + strlen(PKGDATADIR) - + 3); - sprintf(new_gconv_path, "%s=%s:%s", - GCONV_SEARCH_PATH, gconv_path, PKGDATADIR); - } - if (putenv(new_gconv_path) != 0) { - gedcom_warning(_("Failed updating conversion module path")); - } - } - encodings = hash_create(HASHCOUNT_T_MAX, NULL, NULL); hash_set_allocator(encodings, node_alloc, node_free, NULL);