summaryrefslogtreecommitdiffstats
path: root/osdep
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-18 17:49:10 +0200
committerwm4 <wm4@nowhere>2013-09-18 19:08:51 +0200
commit12372298a2a5fd7cd2274fcb2427581f35a6a2c1 (patch)
treed6198570a800c56d4284ace70d3fa2eefdce04b2 /osdep
parentb97d10a839aee875ac8157a84bb008d82f53219a (diff)
downloadmpv-12372298a2a5fd7cd2274fcb2427581f35a6a2c1.tar.bz2
mpv-12372298a2a5fd7cd2274fcb2427581f35a6a2c1.tar.xz
win32: add getenv() UTF-8 variant
This is a bit "hard", because getenv() returns a static string, and we can't just return an allocated string. We also want getenv() to be thread-safe if possible. (If the mpv core is going to be more threaded, we sure do want the lower layers to be thread-safe as well.)
Diffstat (limited to 'osdep')
-rw-r--r--osdep/io.c60
-rw-r--r--osdep/io.h2
2 files changed, 62 insertions, 0 deletions
diff --git a/osdep/io.c b/osdep/io.c
index f6ccbb4f74..b618c76747 100644
--- a/osdep/io.c
+++ b/osdep/io.c
@@ -58,6 +58,12 @@ char *mp_to_utf8(void *talloc_ctx, const wchar_t *s)
#include <io.h>
#include <fcntl.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include "mpvcore/mp_talloc.h"
+
//http://git.libav.org/?p=libav.git;a=blob;f=cmdutils.c;h=ade3f10ce2fc030e32e375a85fbd06c26d43a433#l161
static char** win32_argv_utf8;
@@ -255,4 +261,58 @@ int mp_mkdir(const char *path, int mode)
return res;
}
+static char **utf8_environ;
+static void *utf8_environ_ctx;
+
+static void free_env(void)
+{
+ talloc_free(utf8_environ_ctx);
+ utf8_environ_ctx = NULL;
+ utf8_environ = NULL;
+}
+
+// Note: UNIX getenv() returns static strings, and we try to do the same. Since
+// using putenv() is not multithreading safe, we don't expect env vars to change
+// at runtime, and converting/allocating them in advance is ok.
+static void init_getenv(void)
+{
+ if (utf8_environ_ctx)
+ return;
+ wchar_t *wenv = GetEnvironmentStringsW();
+ if (!wenv)
+ return;
+ utf8_environ_ctx = talloc_new(NULL);
+ int num_env = 0;
+ while (1) {
+ size_t len = wcslen(wenv);
+ if (!len)
+ break;
+ char *s = mp_to_utf8(utf8_environ_ctx, wenv);
+ MP_TARRAY_APPEND(utf8_environ_ctx, utf8_environ, num_env, s);
+ wenv += len + 1;
+ }
+ MP_TARRAY_APPEND(utf8_environ_ctx, utf8_environ, num_env, NULL);
+ // Avoid showing up in leak detectors etc.
+ atexit(free_env);
+}
+
+char *mp_getenv(const char *name)
+{
+#ifdef HAVE_PTHREADS
+ static pthread_once_t once_init_getenv = PTHREAD_ONCE_INIT;
+ pthread_once(&once_init_getenv, init_getenv);
+#else
+ init_getenv();
+#endif
+ // Copied from musl, http://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+ // Copyright © 2005-2013 Rich Felker, standard MIT license
+ int i;
+ size_t l = strlen(name);
+ if (!utf8_environ || !*name || strchr(name, '=')) return NULL;
+ for (i=0; utf8_environ[i] && (strncmp(name, utf8_environ[i], l)
+ || utf8_environ[i][l] != '='); i++) {}
+ if (utf8_environ[i]) return utf8_environ[i] + l+1;
+ return NULL;
+}
+
#endif // __MINGW32__
diff --git a/osdep/io.h b/osdep/io.h
index 7554b402d4..5dd93a79a1 100644
--- a/osdep/io.h
+++ b/osdep/io.h
@@ -59,6 +59,7 @@ DIR *mp_opendir(const char *path);
struct dirent *mp_readdir(DIR *dir);
int mp_closedir(DIR *dir);
int mp_mkdir(const char *path, int mode);
+char *mp_getenv(const char *name);
// NOTE: stat is not overridden with mp_stat, because MinGW-w64 defines it as
// macro.
@@ -72,6 +73,7 @@ int mp_mkdir(const char *path, int mode);
#define readdir(...) mp_readdir(__VA_ARGS__)
#define closedir(...) mp_closedir(__VA_ARGS__)
#define mkdir(...) mp_mkdir(__VA_ARGS__)
+#define getenv(...) mp_getenv(__VA_ARGS__)
#else /* __MINGW32__ */