aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-01-08 16:23:56 +0100
committerMattias Andrée <maandree@kth.se>2023-01-08 16:23:56 +0100
commit627e5b9789c663343c74dac6535724ddc63aae1c (patch)
treeaf78890b546b774267ff82520f0756dd159f8d86
parentImprove libfonts_get_default_font_name and draft implementation of libfonts_get_default_font (diff)
downloadlibfonts-627e5b9789c663343c74dac6535724ddc63aae1c.tar.gz
libfonts-627e5b9789c663343c74dac6535724ddc63aae1c.tar.bz2
libfonts-627e5b9789c663343c74dac6535724ddc63aae1c.tar.xz
Add environment spoofing
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile12
-rw-r--r--common.h4
-rw-r--r--config.mk3
-rw-r--r--libfonts.h50
-rw-r--r--libfonts_get_default_font.c79
-rw-r--r--libfonts_getenv__.c30
-rw-r--r--libfonts_gethome__.c40
-rw-r--r--libfonts_used_environs.c34
8 files changed, 187 insertions, 65 deletions
diff --git a/Makefile b/Makefile
index 6a96f96..7790c0e 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR)
LIB_NAME = fonts
-OBJ =\
+PUBLIC_OBJ =\
libfonts_calculate_subpixel_order.o\
libfonts_decode_font_description.o\
libfonts_encode_font_description.o\
@@ -24,14 +24,20 @@ OBJ =\
libfonts_get_default_font_name.o\
libfonts_get_output_dpi.o\
libfonts_get_subpixel_order_class.o\
- libfonts_unget_subpixel_order_class.o
+ libfonts_unget_subpixel_order_class.o\
+ libfonts_used_environs.o
+
+OBJ =\
+ $(PUBLIC_OBJ)\
+ libfonts_getenv__.o\
+ libfonts_gethome__.o\
HDR =\
common.h\
libfonts.h
LOBJ = $(OBJ:.o=.lo)
-TESTS = $(OBJ:.o=.test)
+TESTS = $(PUBLIC_OBJ:.o=.test)
all: libfonts.a libfonts.$(LIBEXT) $(TESTS)
diff --git a/common.h b/common.h
index 4937a76..2451cb7 100644
--- a/common.h
+++ b/common.h
@@ -33,6 +33,10 @@ eq(double a, double b)
}
+const char *libfonts_getenv__(const char *name, struct libfonts_context *ctx);
+char *libfonts_gethome__(struct libfonts_context *ctx);
+
+
#ifdef TEST
# define ASSERT(ASSERTION)\
diff --git a/config.mk b/config.mk
index ab163d4..8e10fd8 100644
--- a/config.mk
+++ b/config.mk
@@ -6,3 +6,6 @@ CC = c99
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
CFLAGS = -Wall -g
LDFLAGS =
+
+# Add -DVALIDATE to CPPFLAGS to run extra code checks,
+# that are only useful for development, at run time
diff --git a/libfonts.h b/libfonts.h
index 25341ed..09cbb14 100644
--- a/libfonts.h
+++ b/libfonts.h
@@ -1571,11 +1571,53 @@ struct libfonts_font_description {
char _buf[256];
};
+/**
+ * Structure that can be used to spoof the
+ * environment the library is executed in
+ */
+struct libfonts_context {
+ /**
+ * Environment variables to add or override
+ *
+ * `libfonts_used_environs` can be used to
+ * enumerate the environment variables that
+ * affect the execution of the environment
+ */
+ char **environ;
+
+ /**
+ * The real user ID of the process
+ *
+ * Only used if `.use_context_uid` is non-zero
+ */
+ uid_t uid;
+
+ /**
+ * Non-zero to remove all environment
+ * variables that are not included in
+ * `.environ`
+ */
+ int ignore_process_environ;
+
+ /**
+ * Whether `.uid` is used
+ */
+ int use_context_uid;
+};
+
+
+/**
+ * `NULL`-terminated list of environment variables
+ * that affect the execution of the library
+ */
+extern const char *const libfonts_used_environs[];
+
/**
* Get the font a default font name aliases to
*
* @param font The default font
+ * @param ctx Optional `struct libfonts_context`
* @return The font the default font is an alias for
* (shall be deallocated using free(3) when no
* longer used), or `NULL` on failure; in the
@@ -1584,7 +1626,7 @@ struct libfonts_font_description {
*
* @throws EINVAL Unrecognised value on `font`
*/
-char *libfonts_get_default_font(enum libfonts_default_font);
+char *libfonts_get_default_font(enum libfonts_default_font, struct libfonts_context *);
/**
* Get the alias for a default font
@@ -1674,11 +1716,12 @@ int libfonts_do_decoded_font_descriptions_match(const struct libfonts_font_descr
* @param settings Output parameter for the rendering settings;
* `settings->dpi_x` and `settings->dpi_y` will
* have a fallback value assigned if configured to 0
+ * @param ctx Optional `struct libfonts_context`
* @return 1 if rendering settings where found,
* 0 otherwise (`*settings` will be filled with fallback values),
* -1 on failure
*/
-int libfonts_get_default_rendering_settings(struct libfonts_rendering_settings *);
+int libfonts_get_default_rendering_settings(struct libfonts_rendering_settings *, struct libfonts_context *);
/* TODO implement libfonts_get_default_rendering_settings
*
* /etc/libfonts/default-rendering.conf
@@ -1703,11 +1746,12 @@ int libfonts_get_default_rendering_settings(struct libfonts_rendering_settings *
*
* @param settings Output parameter for the rendering settings
* @param name The EDID (or other identifier) of the output
+ * @param ctx Optional `struct libfonts_context`
* @return 1 if rendering settings where found,
* 0 otherwise (`*settings` will be unmodified),
* -1 on failure
*/
-int libfonts_get_output_rendering_settings(struct libfonts_rendering_settings *, const char *);
+int libfonts_get_output_rendering_settings(struct libfonts_rendering_settings *, const char *, struct libfonts_context *);
/* TODO implement libfonts_get_output_rendering_settings
*
* /etc/libfonts/output-rendering.conf
diff --git a/libfonts_get_default_font.c b/libfonts_get_default_font.c
index d27e661..7c21b1f 100644
--- a/libfonts_get_default_font.c
+++ b/libfonts_get_default_font.c
@@ -10,43 +10,6 @@ find(const char *dir_part1, const char *dir_part2, const char *dir_part3)
}
static char *
-gethome(void)
-{
- uid_t uid = getuid();
- size_t size = 512;
- char *buf = NULL, *new;
- char *ret = NULL;
- struct passwd pw, *pwp;
- int err;
-
- goto beginning;
-
- do {
- if (size > SIZE_MAX / 2)
- goto enomem;
- size *= 2;
- beginning:
- new = realloc(buf, size);
- if (!new) {
- enomem:
- free(buf);
- errno = ENOMEM;
- return NULL;
- }
- buf = new;
- } while ((err = getpwuid_r(uid, &pw, buf, size, &pwp)) == ERANGE);
- if (err) {
- free(buf);
- return NULL;
- }
-
- if (pwp && pwp->pw_dir)
- ret = strdup(pwp->pw_dir);
- free(buf);
- return ret;
-}
-
-static char *
getn(const char *file_part1, size_t file_part1_len, const char *file_part2, const char *name)
{
size_t file_part2_len = strlen(file_part2);
@@ -82,9 +45,9 @@ get(const char *file_part1, const char *file_part2, const char *name)
}
char *
-libfonts_get_default_font(enum libfonts_default_font font)
+libfonts_get_default_font(enum libfonts_default_font font, struct libfonts_context *ctx)
{
- const char *env, *var, *next;
+ const char *env, *var, *next, *confenv, *homeenv;
char *ret, *home = NULL;
int saved_errno = errno;
size_t len;
@@ -103,28 +66,28 @@ libfonts_get_default_font(enum libfonts_default_font font)
return NULL;
}
- ret = getenv(env);
- if (ret && *ret)
- return strdup(ret);
+ env = libfonts_getenv__(env, ctx);
+ if (env && *env)
+ return strdup(env);
- env = getenv("XDG_CONFIG_HOME");
- if (env && *env) {
- ret = get(env, "/libfonts/default-fonts.conf", var);
+ confenv = libfonts_getenv__("XDG_CONFIG_HOME", ctx);
+ if (confenv && *confenv) {
+ ret = get(confenv, "/libfonts/default-fonts.conf", var);
if (ret)
goto out;
}
- env = getenv("HOME");
- if (env && *env) {
- ret = get(env, "/.config/libfonts/default-fonts.conf", var);
+ homeenv = libfonts_getenv__("HOME", ctx);
+ if (homeenv && *homeenv) {
+ ret = get(homeenv, "/.config/libfonts/default-fonts.conf", var);
if (ret)
goto out;
- ret = get(env, "/.libfonts/default-fonts.conf", var);
+ ret = get(homeenv, "/.libfonts/default-fonts.conf", var);
if (ret)
goto out;
}
- home = gethome();
+ home = libfonts_gethome__(ctx);
if (home && *home) {
ret = get(home, "/.config/libfonts/default-fonts.conf", var);
if (ret)
@@ -134,33 +97,31 @@ libfonts_get_default_font(enum libfonts_default_font font)
goto out;
}
- env = getenv("XDG_CONFIG_HOME");
- if (env && *env) {
+ if (confenv && *confenv) {
ret = find(env, "/libfonts/", var);
if (ret)
goto out;
}
- env = getenv("HOME");
- if (env && *env) {
- ret = find(env, "/.config/libfonts/", var);
+ if (homeenv && *homeenv) {
+ ret = find(homeenv, "/.config/libfonts/", var);
if (ret)
goto out;
- ret = find(env, "/.libfonts/", var);
+ ret = find(homeenv, "/.libfonts/", var);
if (ret)
goto out;
}
if (home && *home) {
- ret = find(env, "/.config/libfonts/", var);
+ ret = find(home, "/.config/libfonts/", var);
if (ret)
goto out;
- ret = find(env, "/.libfonts/", var);
+ ret = find(home, "/.libfonts/", var);
if (ret)
goto out;
}
- env = getenv("XDG_CONFIG_DIRS");
+ env = libfonts_getenv__("XDG_CONFIG_DIRS", ctx);
if (env && *env) {
do {
next = strchr(&env[1], ':');
diff --git a/libfonts_getenv__.c b/libfonts_getenv__.c
new file mode 100644
index 0000000..d998337
--- /dev/null
+++ b/libfonts_getenv__.c
@@ -0,0 +1,30 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+const char *
+libfonts_getenv__(const char *name, struct libfonts_context *ctx)
+{
+ char **envp;
+ size_t len = strlen(name);
+
+#ifdef VALIDATE
+ size_t i;
+ if (!name) {
+ fprintf(stderr, "`name` parameter in libfonts_getenv__ is NULL\n");
+ abort();
+ }
+ for (i = 0; libfonts_used_environs[i]; i++)
+ if (!strcmp(name, libfonts_used_environs[i]))
+ goto ok;
+ fprintf(stderr, "Value of `name` parameter (\"%s\") in libfonts_getenv__ is not in libfonts_used_environs\n", name);
+ abort();
+ok:
+#endif
+
+ if (ctx && ctx->environ)
+ for (envp = ctx->environ; *envp; envp++)
+ if (strncmp(*envp, name, len) && (*envp)[len] == '=')
+ return *envp;
+ return ctx->ignore_process_environ ? NULL : getenv(name);
+}
diff --git a/libfonts_gethome__.c b/libfonts_gethome__.c
new file mode 100644
index 0000000..902029f
--- /dev/null
+++ b/libfonts_gethome__.c
@@ -0,0 +1,40 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+char *
+libfonts_gethome__(struct libfonts_context *ctx)
+{
+ uid_t uid = (ctx && ctx->use_context_uid) ? ctx->uid : getuid();
+ size_t size = 512;
+ char *buf = NULL, *new;
+ char *ret = NULL;
+ struct passwd pw, *pwp;
+ int err;
+
+ goto beginning;
+
+ do {
+ if (size > SIZE_MAX / 2)
+ goto enomem;
+ size *= 2;
+ beginning:
+ new = realloc(buf, size);
+ if (!new) {
+ enomem:
+ free(buf);
+ errno = ENOMEM;
+ return NULL;
+ }
+ buf = new;
+ } while ((err = getpwuid_r(uid, &pw, buf, size, &pwp)) == ERANGE);
+ if (err) {
+ free(buf);
+ return NULL;
+ }
+
+ if (pwp && pwp->pw_dir)
+ ret = strdup(pwp->pw_dir);
+ free(buf);
+ return ret;
+}
diff --git a/libfonts_used_environs.c b/libfonts_used_environs.c
new file mode 100644
index 0000000..54232b4
--- /dev/null
+++ b/libfonts_used_environs.c
@@ -0,0 +1,34 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+const char *const libfonts_used_environs[] = {
+ "LIBFONTS_DEFAULT_SANS_SERIF",
+ "LIBFONTS_DEFAULT_SERIF",
+ "LIBFONTS_DEFAULT_MONOSPACE",
+ "XDG_CONFIG_HOME",
+ "HOME",
+ NULL
+};
+
+
+#else
+
+
+int
+main(void)
+{
+ size_t i, j, n;
+ for (n = 0; n < 100; n++)
+ if (!libfonts_used_environs[n])
+ break;
+ ASSERT(n < 100);
+ for (i = 0; i < n; i++)
+ for (j = i + 1; j < n; j++)
+ ASSERT(strcmp(libfonts_used_environs[i], libfonts_used_environs[j]));
+ return 0;
+}
+
+
+#endif