summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2015-12-09 16:21:09 +0100
committerJosé Bollo <jose.bollo@iot.bzh>2015-12-09 16:21:09 +0100
commit63f8720a3e610c0dc37bda3138d2e8de98ec1a78 (patch)
tree3842354238d7fca759cfb74cc95d7b497df41b78
parentec5ef9fdf2e608149c6ad308c5184820c51c39a6 (diff)
refactoring widget library
Change-Id: I9662573ed677d34daa393f0e207a4cd4a822f8ad Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--src/Makefile.am11
-rw-r--r--src/secmgr-wrap.c6
-rw-r--r--src/wgt-config.c (renamed from src/wgt-config-xml.c)90
-rw-r--r--src/wgt-config.h44
-rw-r--r--src/wgt-rootdir.c97
-rw-r--r--src/wgt-strings.c31
-rw-r--r--src/wgt.c268
-rw-r--r--src/wgt.h60
8 files changed, 389 insertions, 218 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6c76395..0f35ac4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,10 +11,11 @@ COMMONSRCS = \
wgtpkg-zip.c
WGTSRCS = \
- wgt-config-xml.c \
- wgt-locales.c \
- wgt-rootdir.c \
- wgt-strings.c
+ wgt-config.c \
+ wgt.c
+
+SECWRP = \
+ secmgr-wrap.c
AM_CFLAGS = -Wall -Wno-pointer-sign
AM_CFLAGS += -ffunction-sections -fdata-sections
@@ -24,7 +25,7 @@ AM_LDFLAGS = -Wl,--gc-sections
LDADD = ${ZIP_LIBS} ${XML2_LIBS} ${OPENSSL_LIBS} ${XMLSEC_LIBS}
-wgtpkg_install_SOURCES = wgtpkg-install.c ${WGTSRCS} ${COMMONSRCS}
+wgtpkg_install_SOURCES = wgtpkg-install.c ${COMMONSRCS} ${WGTSRCS} ${SECWRP}
wgtpkg_sign_SOURCES = wgtpkg-sign.c ${COMMONSRCS}
diff --git a/src/secmgr-wrap.c b/src/secmgr-wrap.c
index 1fcec58..f63ad29 100644
--- a/src/secmgr-wrap.c
+++ b/src/secmgr-wrap.c
@@ -1,8 +1,12 @@
+#include <string.h>
#include <errno.h>
+
#if 0
#include <security-manager.h>
#else
+#include <stdio.h>
+#include <stdint.h>
enum lib_retcode {
SECURITY_MANAGER_SUCCESS,
SECURITY_MANAGER_ERROR_INPUT_PARAM,
@@ -22,7 +26,7 @@ static int diese = 0;
(printf("security_manager_app_inst_req_free(%p)\n",r),(void)0)
#define security_manager_app_inst_req_new(pr) \
- (*(pr)=(void*)(++diese), printf("security_manager_app_inst_req_new(%p)\n",*pr), SECURITY_MANAGER_SUCCESS)
+ (*(pr)=(void*)(intptr_t)(++diese), printf("security_manager_app_inst_req_new(%p)\n",*pr), SECURITY_MANAGER_SUCCESS)
#define security_manager_app_inst_req_set_pkg_id(r,i) \
(printf("security_manager_app_inst_req_set_pkg_id(%p,\"%s\")\n",r,i), SECURITY_MANAGER_SUCCESS)
diff --git a/src/wgt-config-xml.c b/src/wgt-config.c
index f92ae3a..77358fd 100644
--- a/src/wgt-config-xml.c
+++ b/src/wgt-config.c
@@ -24,9 +24,23 @@
#include <libxml/tree.h>
#include <libxml/uri.h>
-
#include "wgt.h"
-
+#include "wgt-config.h"
+
+const char wgt_config_string_xml_file[] = "config.xml";
+const char wgt_config_string_name[] = "name";
+const char wgt_config_string_description[] = "description";
+const char wgt_config_string_author[] = "author";
+const char wgt_config_string_license[] = "license";
+const char wgt_config_string_icon[] = "icon";
+const char wgt_config_string_content[] = "content";
+const char wgt_config_string_feature[] = "feature";
+const char wgt_config_string_preference[] = "preference";
+const char wgt_config_string_width[] = "width";
+const char wgt_config_string_height[] = "height";
+
+
+static struct wgt *configwgt = NULL;
static xmlDocPtr configxml = NULL;
static xmlNodePtr next(xmlNodePtr node, const char *type)
@@ -50,7 +64,7 @@ static xmlNodePtr first(const char *type)
static int scorelang(xmlNodePtr node)
{
char *lang = xmlNodeGetLang(node);
- int score = locales_score(lang);
+ int score = wgt_locales_score(configwgt, lang);
xmlFree(lang);
return score;
}
@@ -76,89 +90,91 @@ static xmlNodePtr element_based_localisation(const char *type)
return resu;
}
-void confixml_close()
+void wgt_config_close()
{
if (configxml) {
xmlFreeDoc(configxml);
configxml = NULL;
+ configwgt = NULL;
}
}
-int confixml_open()
+int wgt_config_open(struct wgt *wgt)
{
int fd;
assert(!configxml);
- fd = widget_open_read(_config_xml_);
+ fd = wgt_open_read(wgt, wgt_config_string_xml_file);
if (fd < 0) {
- syslog(LOG_ERR, "can't open config file %s", _config_xml_);
+ syslog(LOG_ERR, "can't open config file %s", wgt_config_string_xml_file);
return fd;
}
- configxml = xmlReadFd(fd, "_config_xml_", NULL, 0);
+ configxml = xmlReadFd(fd, wgt_config_string_xml_file, NULL, 0);
close(fd);
if (configxml == NULL) {
- syslog(LOG_ERR, "xml parse of config file %s failed", _config_xml_);
+ syslog(LOG_ERR, "xml parse of config file %s failed", wgt_config_string_xml_file);
return -1;
}
+ configwgt = wgt;
return 0;
}
/* elements based on localisation */
-xmlNodePtr confixml_name()
+xmlNodePtr wgt_config_name()
{
- return element_based_localisation(_name_);
+ return element_based_localisation(wgt_config_string_name);
}
-xmlNodePtr confixml_description()
+xmlNodePtr wgt_config_description()
{
- return element_based_localisation(_description_);
+ return element_based_localisation(wgt_config_string_description);
}
-xmlNodePtr confixml_license()
+xmlNodePtr wgt_config_license()
{
- return element_based_localisation(_license_);
+ return element_based_localisation(wgt_config_string_license);
}
/* elements based on path localisation */
-xmlNodePtr confixml_author()
+xmlNodePtr wgt_config_author()
{
- return first(_author_);
+ return first(wgt_config_string_author);
}
-xmlNodePtr confixml_content()
+xmlNodePtr wgt_config_content()
{
- return first(_content_);
+ return first(wgt_config_string_content);
}
/* element multiple */
-xmlNodePtr confixml_first_feature()
+xmlNodePtr wgt_config_first_feature()
{
- return first(_feature_);
+ return first(wgt_config_string_feature);
}
-xmlNodePtr confixml_next_feature(xmlNodePtr node)
+xmlNodePtr wgt_config_next_feature(xmlNodePtr node)
{
- return next(node->next, _feature_);
+ return next(node->next, wgt_config_string_feature);
}
-xmlNodePtr confixml_first_preference()
+xmlNodePtr wgt_config_first_preference()
{
- return first(_preference_);
+ return first(wgt_config_string_preference);
}
-xmlNodePtr confixml_next_preference(xmlNodePtr node)
+xmlNodePtr wgt_config_next_preference(xmlNodePtr node)
{
- return next(node->next, _preference_);
+ return next(node->next, wgt_config_string_preference);
}
-xmlNodePtr confixml_first_icon()
+xmlNodePtr wgt_config_first_icon()
{
- return first(_icon_);
+ return first(wgt_config_string_icon);
}
-xmlNodePtr confixml_next_icon(xmlNodePtr node)
+xmlNodePtr wgt_config_next_icon(xmlNodePtr node)
{
- return next(node->next, _icon_);
+ return next(node->next, wgt_config_string_icon);
}
/* best sized icon */
@@ -215,21 +231,21 @@ static int score_dim(xmlNodePtr ref, xmlNodePtr x, const char *dim, int request)
static int better_icon(xmlNodePtr ref, xmlNodePtr x, int width, int height)
{
- int sw = score_dim(ref, x, _width_, width);
- int sh = score_dim(ref, x, _height_, height);
+ int sw = score_dim(ref, x, wgt_config_string_width, width);
+ int sh = score_dim(ref, x, wgt_config_string_height, height);
return sw+sh < 0;
}
-xmlNodePtr confixml_icon(int width, int height)
+xmlNodePtr wgt_config_icon(int width, int height)
{
xmlNodePtr resu, icon;
- resu = confixml_first_icon();
- icon = confixml_next_icon(resu);
+ resu = wgt_config_first_icon();
+ icon = wgt_config_next_icon(resu);
while (icon) {
if (better_icon(resu, icon, width, height))
resu = icon;
- icon = confixml_next_icon(icon);
+ icon = wgt_config_next_icon(icon);
}
return resu;
}
diff --git a/src/wgt-config.h b/src/wgt-config.h
new file mode 100644
index 0000000..07a5c4a
--- /dev/null
+++ b/src/wgt-config.h
@@ -0,0 +1,44 @@
+/*
+ Copyright 2015 IoT.bzh
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+extern const char wgt_config_string_xml_file[];
+extern const char wgt_config_string_name[];
+extern const char wgt_config_string_description[];
+extern const char wgt_config_string_author[];
+extern const char wgt_config_string_license[];
+extern const char wgt_config_string_icon[];
+extern const char wgt_config_string_content[];
+extern const char wgt_config_string_feature[];
+extern const char wgt_config_string_preference[];
+extern const char wgt_config_string_width[];
+extern const char wgt_config_string_height[];
+
+struct wgt;
+extern int wgt_config_open(struct wgt *wgt);
+extern void wgt_config_close();
+extern xmlNodePtr wgt_config_name();
+extern xmlNodePtr wgt_config_description();
+extern xmlNodePtr wgt_config_license();
+extern xmlNodePtr wgt_config_author();
+extern xmlNodePtr wgt_config_content();
+extern xmlNodePtr wgt_config_icon(int width, int height);
+extern xmlNodePtr wgt_config_first_feature();
+extern xmlNodePtr wgt_config_next_feature(xmlNodePtr node);
+extern xmlNodePtr wgt_config_first_preference();
+extern xmlNodePtr wgt_config_next_preference(xmlNodePtr node);
+extern xmlNodePtr wgt_config_first_icon();
+extern xmlNodePtr wgt_config_next_icon(xmlNodePtr node);
+
diff --git a/src/wgt-rootdir.c b/src/wgt-rootdir.c
deleted file mode 100644
index 4df1705..0000000
--- a/src/wgt-rootdir.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- Copyright 2015 IoT.bzh
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-#define _GNU_SOURCE
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "wgt.h"
-
-
-static int rootfd = AT_FDCWD;
-
-int widget_set_rootdir(const char *pathname)
-{
- int rfd;
-
- if (!pathname)
- rfd = AT_FDCWD;
- else {
- rfd = openat(AT_FDCWD, pathname, O_PATH|O_DIRECTORY);
- if (rfd < 0)
- return rfd;
- }
- if (rootfd >= 0)
- close(rootfd);
- rootfd = AT_FDCWD;
- return 0;
-}
-
-static int validsubpath(const char *subpath)
-{
- int l = 0, i = 0;
- if (subpath[i] == '/')
- return 0;
- while(subpath[i]) {
- switch(subpath[i++]) {
- case '.':
- if (!subpath[i])
- break;
- if (subpath[i] == '/') {
- i++;
- break;
- }
- if (subpath[i++] == '.') {
- if (!subpath[i]) {
- l--;
- break;
- }
- if (subpath[i++] == '/') {
- l--;
- break;
- }
- }
- default:
- while(subpath[i] && subpath[i] != '/')
- i++;
- l++;
- case '/':
- break;
- }
- }
- return l >= 0;
-}
-
-int widget_has(const char *filename)
-{
- if (!validsubpath(filename)) {
- errno = EINVAL;
- return -1;
- }
- return 0 == faccessat(rootfd, filename, F_OK, 0);
-}
-
-int widget_open_read(const char *filename)
-{
- if (!validsubpath(filename)) {
- errno = EINVAL;
- return -1;
- }
- return openat(rootfd, filename, O_RDONLY);
-}
-
diff --git a/src/wgt-strings.c b/src/wgt-strings.c
deleted file mode 100644
index a2fff39..0000000
--- a/src/wgt-strings.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- Copyright 2015 IoT.bzh
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-#include "wgt.h"
-
-const char _config_xml_[] = "config.xml";
-const char _name_[] = "name";
-const char _description_[] = "description";
-const char _author_[] = "author";
-const char _license_[] = "license";
-const char _icon_[] = "icon";
-const char _content_[] = "content";
-const char _feature_[] = "feature";
-const char _preference_[] = "preference";
-const char _width_[] = "width";
-const char _height_[] = "height";
-
-
diff --git a/src/wgt.c b/src/wgt.c
new file mode 100644
index 0000000..dd889d5
--- /dev/null
+++ b/src/wgt.c
@@ -0,0 +1,268 @@
+/*
+ Copyright 2015 IoT.bzh
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+
+
+#include "wgt.h"
+
+struct wgt {
+ int rootfd;
+ int nrlocales;
+ char **locales;
+};
+
+static int validsubpath(const char *subpath)
+{
+ int l = 0, i = 0;
+ if (subpath[i] == '/')
+ return 0;
+ while(subpath[i]) {
+ switch(subpath[i++]) {
+ case '.':
+ if (!subpath[i])
+ break;
+ if (subpath[i] == '/') {
+ i++;
+ break;
+ }
+ if (subpath[i++] == '.') {
+ if (!subpath[i]) {
+ l--;
+ break;
+ }
+ if (subpath[i++] == '/') {
+ l--;
+ break;
+ }
+ }
+ default:
+ while(subpath[i] && subpath[i] != '/')
+ i++;
+ l++;
+ case '/':
+ break;
+ }
+ }
+ return l >= 0;
+}
+
+struct wgt *wgt_create()
+{
+ struct wgt *wgt = malloc(sizeof * wgt);
+ if (wgt) {
+ wgt->rootfd = -1;
+ wgt->nrlocales = 0;
+ wgt->locales = NULL;
+ }
+ return wgt;
+}
+
+void wgt_disconnect(struct wgt *wgt)
+{
+ assert(wgt);
+ if (wgt->rootfd >= 0)
+ close(wgt->rootfd);
+ wgt->rootfd = -1;
+}
+
+void wgt_locales_reset(struct wgt *wgt)
+{
+ assert(wgt);
+ while(wgt->nrlocales)
+ free(wgt->locales[--wgt->nrlocales]);
+}
+
+void wgt_destroy(struct wgt *wgt)
+{
+ if (wgt) {
+ wgt_disconnect(wgt);
+ wgt_locales_reset(wgt);
+ free(wgt->locales);
+ free(wgt);
+ }
+}
+
+int wgt_connect(struct wgt *wgt, const char *pathname)
+{
+ int rfd;
+
+ assert(wgt);
+
+ rfd = AT_FDCWD;
+ if (pathname) {
+ rfd = openat(rfd, pathname, O_PATH|O_DIRECTORY);
+ if (rfd < 0)
+ return rfd;
+ }
+ if (wgt->rootfd >= 0)
+ close(wgt->rootfd);
+ wgt->rootfd = rfd;
+ return 0;
+}
+
+int wgt_is_connected(struct wgt *wgt)
+{
+ assert(wgt);
+ return wgt->rootfd != -1;
+}
+
+int wgt_has(struct wgt *wgt, const char *filename)
+{
+ assert(wgt);
+ assert(wgt_is_connected(wgt));
+ if (!validsubpath(filename)) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0 == faccessat(wgt->rootfd, filename, F_OK, 0);
+}
+
+int wgt_open_read(struct wgt *wgt, const char *filename)
+{
+ assert(wgt);
+ assert(wgt_is_connected(wgt));
+ if (!validsubpath(filename)) {
+ errno = EINVAL;
+ return -1;
+ }
+ return openat(wgt->rootfd, filename, O_RDONLY);
+}
+
+static int locadd(struct wgt *wgt, const char *locstr, int length)
+{
+ int i;
+ char *item, **ptr;
+
+ item = strndup(locstr, length);
+ if (item != NULL) {
+ for (i = 0 ; item[i] ; i++)
+ item[i] = tolower(item[i]);
+ for (i = 0 ; i < wgt->nrlocales ; i++)
+ if (!strcmp(item, wgt->locales[i])) {
+ free(item);
+ return 0;
+ }
+
+ ptr = realloc(wgt->locales, (1 + wgt->nrlocales) * sizeof(wgt->locales[0]));
+ if (ptr) {
+ wgt->locales = ptr;
+ wgt->locales[wgt->nrlocales++] = item;
+ return 0;
+ }
+ free(item);
+ }
+ errno = ENOMEM;
+ return -1;
+}
+
+int wgt_locales_add(struct wgt *wgt, const char *locstr)
+{
+ const char *stop, *next;
+ assert(wgt);
+ while (*locstr) {
+ stop = strchrnul(locstr, ',');
+ next = stop + !!*stop;
+ while (locstr != stop) {
+ if (locadd(wgt, locstr, stop - locstr))
+ return -1;
+ do { stop--; } while(stop > locstr && *stop != '-');
+ }
+ locstr = next;
+ }
+ return 0;
+}
+
+int wgt_locales_score(struct wgt *wgt, const char *lang)
+{
+ int i;
+
+ assert(wgt);
+ if (lang)
+ for (i = 0 ; i < wgt->nrlocales ; i++)
+ if (!strcasecmp(lang, wgt->locales[i]))
+ return i;
+
+ return INT_MAX;
+}
+
+static const char *localize(struct wgt *wgt, const char *filename, char path[PATH_MAX])
+{
+ int i;
+
+ if (!validsubpath(filename)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ for (i = 0 ; i < wgt->nrlocales ; i++) {
+ if (snprintf(path, PATH_MAX, "locales/%s/%s", wgt->locales[i], filename) >= PATH_MAX) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (0 == faccessat(wgt->rootfd, path, F_OK, 0))
+ return path;
+ }
+ if (0 == faccessat(wgt->rootfd, filename, F_OK, 0))
+ return filename;
+ errno = ENOENT;
+ return NULL;
+}
+
+char *wgt_locales_locate(struct wgt *wgt, const char *filename)
+{
+ char path[PATH_MAX];
+ char * result;
+ const char * loc;
+
+ assert(wgt);
+ assert(wgt_is_connected(wgt));
+ loc = localize(wgt, filename, path);
+ if (!loc)
+ result = NULL;
+ else {
+ result = strdup(loc);
+ if (!result)
+ errno = ENOMEM;
+ }
+ return result;
+}
+
+
+int wgt_locales_open_read(struct wgt *wgt, const char *filename)
+{
+ char path[PATH_MAX];
+ const char *loc;
+
+ assert(wgt);
+ assert(wgt_is_connected(wgt));
+ loc = localize(wgt, filename, path);
+ if (!loc)
+ return -1;
+
+ return openat(wgt->rootfd, loc, O_RDONLY);
+}
+
+
diff --git a/src/wgt.h b/src/wgt.h
index d95e65b..81aea1e 100644
--- a/src/wgt.h
+++ b/src/wgt.h
@@ -14,56 +14,22 @@
limitations under the License.
*/
+struct wgt;
-#include <libxml/tree.h>
-#include "config.h"
+extern struct wgt *wgt_create();
+extern void wgt_destroy(struct wgt *wgt);
+extern int wgt_connect(struct wgt *wgt, const char *pathname);
+extern void wgt_disconnect(struct wgt *wgt);
+extern int wgt_is_connected(struct wgt *wgt);
-/**************************************************************/
-/* from wgt-config-xml */
+extern int wgt_has(struct wgt *wgt, const char *filename);
+extern int wgt_open_read(struct wgt *wgt, const char *filename);
-extern int confixml_open();
-extern void confixml_close();
-extern xmlNodePtr confixml_name();
-extern xmlNodePtr confixml_description();
-extern xmlNodePtr confixml_license();
-extern xmlNodePtr confixml_author();
-extern xmlNodePtr confixml_content();
-extern xmlNodePtr confixml_icon(int width, int height);
-extern xmlNodePtr confixml_first_feature();
-extern xmlNodePtr confixml_next_feature(xmlNodePtr node);
-extern xmlNodePtr confixml_first_preference();
-extern xmlNodePtr confixml_next_preference(xmlNodePtr node);
-extern xmlNodePtr confixml_first_icon();
-extern xmlNodePtr confixml_next_icon(xmlNodePtr node);
+extern void wgt_locales_reset(struct wgt *wgt);
+extern int wgt_locales_add(struct wgt *wgt, const char *locstr);
+extern int wgt_locales_score(struct wgt *wgt, const char *lang);
-/**************************************************************/
-/* from wgt-locales */
-
-extern void locales_reset();
-extern int locales_add(const char *locstr);
-extern int locales_score(const char *lang);
-extern char *locales_locate_file(const char *filename);
-
-/**************************************************************/
-/* from wgt-rootdir */
-
-extern int widget_set_rootdir(const char *pathname);
-extern int widget_has(const char *filename);
-extern int widget_open_read(const char *filename);
-
-/**************************************************************/
-/* from wgt-strings */
-
-extern const char _config_xml_[];
-extern const char _name_[];
-extern const char _description_[];
-extern const char _author_[];
-extern const char _license_[];
-extern const char _icon_[];
-extern const char _content_[];
-extern const char _feature_[];
-extern const char _preference_[];
-extern const char _width_[];
-extern const char _height_[];
+extern char *wgt_locales_locate(struct wgt *wgt, const char *filename);
+extern int wgt_locales_open_read(struct wgt *wgt, const char *filename);