aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Hoffmann <stefan991@gmail.com>2014-03-03 20:02:32 +0100
committerThiago de Arruda <tpadilha84@gmail.com>2014-03-06 13:38:45 -0300
commitf2433aedc86db171d5616410605cf0d398d8fdc2 (patch)
tree2df40baf1dce2b9e6e6dc175f66cfff41d7bd6ad
parentfc8686640250561156913387c62924d2bdb5e1ac (diff)
downloadrneovim-f2433aedc86db171d5616410605cf0d398d8fdc2.tar.gz
rneovim-f2433aedc86db171d5616410605cf0d398d8fdc2.tar.bz2
rneovim-f2433aedc86db171d5616410605cf0d398d8fdc2.zip
cleanup environment variable handling + unit tests
* removed a putenv() implementation which isn't needed anymore * mch_getenv() and mch_setenv() are now functions in src/os/env.c * removes direct calls to getenv() and setenv() outside of src/os/env.c * refactored the logic of get_env_name into mch_getenvname_at_index * added unittests for the functions in os/env.c
-rw-r--r--src/diff.c2
-rw-r--r--src/eval.c2
-rw-r--r--src/ex_cmds2.c6
-rw-r--r--src/hangulin.c7
-rw-r--r--src/main.c3
-rw-r--r--src/mbyte.c7
-rw-r--r--src/message.c5
-rw-r--r--src/misc1.c61
-rw-r--r--src/misc2.c148
-rw-r--r--src/option.c9
-rw-r--r--src/os/env.c65
-rw-r--r--src/os/os.h3
-rw-r--r--src/os_unix.c33
-rw-r--r--src/os_unix_defs.h8
-rw-r--r--src/term.c3
-rw-r--r--test/unit/os/env.moon95
16 files changed, 207 insertions, 250 deletions
diff --git a/src/diff.c b/src/diff.c
index ff375c9296..f59ba8015a 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -737,7 +737,7 @@ static void diff_file(char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff)
cmd = alloc((unsigned)len);
if (cmd != NULL) {
/* We don't want $DIFF_OPTIONS to get in the way. */
- if (getenv("DIFF_OPTIONS"))
+ if (mch_getenv("DIFF_OPTIONS"))
vim_setenv((char_u *)"DIFF_OPTIONS", (char_u *)"");
/* Build the diff command and execute it. Always use -a, binary
diff --git a/src/eval.c b/src/eval.c
index cfcf4ce712..9630976056 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -8552,7 +8552,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv)
p = get_tv_string(&argvars[0]);
if (*p == '$') { /* environment variable */
/* first try "normal" environment variables (fast) */
- if (mch_getenv(p + 1) != NULL)
+ if (mch_getenv((char *)(p + 1)) != NULL)
n = TRUE;
else {
/* try expanding things like $VIM and ${HOME} */
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index f08aab0300..e005472695 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -3322,11 +3322,11 @@ static char_u *get_mess_env(void);
static char_u *get_mess_env(void) {
char_u *p;
- p = mch_getenv((char_u *)"LC_ALL");
+ p = (char_u *)mch_getenv("LC_ALL");
if (p == NULL || *p == NUL) {
- p = mch_getenv((char_u *)"LC_MESSAGES");
+ p = (char_u *)mch_getenv("LC_MESSAGES");
if (p == NULL || *p == NUL) {
- p = mch_getenv((char_u *)"LANG");
+ p = (char_u *)mch_getenv("LANG");
if (p != NULL && VIM_ISDIGIT(*p))
p = NULL; /* ignore something like "1043" */
# ifdef HAVE_GET_LOCALE_VAL
diff --git a/src/hangulin.c b/src/hangulin.c
index 4f84312cad..74972d23e2 100644
--- a/src/hangulin.c
+++ b/src/hangulin.c
@@ -14,6 +14,7 @@
#include "screen.h"
#include "term.h"
#include "ui.h"
+#include "os/os.h"
#ifndef HANGUL_DEFAULT_KEYBOARD
# define HANGUL_DEFAULT_KEYBOARD 3
@@ -653,12 +654,12 @@ static int hangul_automata3(char_u *buf, int_u *c)
void hangul_keyboard_set(void) {
int keyboard;
- char *s;
+ const char *s;
hangul_input_clear();
- if ((s = getenv("VIM_KEYBOARD")) == NULL)
- s = getenv("HANGUL_KEYBOARD_TYPE");
+ if ((s = mch_getenv("VIM_KEYBOARD")) == NULL)
+ s = mch_getenv("HANGUL_KEYBOARD_TYPE");
if (s) {
if (*s == '2')
diff --git a/src/main.c b/src/main.c
index 13b1179711..d6a09b504c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2114,7 +2114,8 @@ process_env (
linenr_T save_sourcing_lnum;
scid_T save_sid;
- if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL) {
+ initstr = (char_u *)mch_getenv((char *)env);
+ if (initstr != NULL && *initstr != NUL) {
if (is_viminit)
vimrc_found(NULL, NULL);
save_sourcing_name = sourcing_name;
diff --git a/src/mbyte.c b/src/mbyte.c
index 2ebf3cd98f..44f0f9d643 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -89,6 +89,7 @@
#include "screen.h"
#include "spell.h"
#include "ui.h"
+#include "os/os.h"
# define WINBYTE BYTE
@@ -3483,9 +3484,9 @@ char_u * enc_locale() {
# if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
if ((s = setlocale(LC_CTYPE, NULL)) == NULL || *s == NUL)
# endif
- if ((s = getenv("LC_ALL")) == NULL || *s == NUL)
- if ((s = getenv("LC_CTYPE")) == NULL || *s == NUL)
- s = getenv("LANG");
+ if ((s = (char *)mch_getenv("LC_ALL")) == NULL || *s == NUL)
+ if ((s = (char *)mch_getenv("LC_CTYPE")) == NULL || *s == NUL)
+ s = (char *)mch_getenv("LANG");
if (s == NULL || *s == NUL)
return FAIL;
diff --git a/src/message.c b/src/message.c
index f6e8d3d9bd..6948cefe12 100644
--- a/src/message.c
+++ b/src/message.c
@@ -30,6 +30,7 @@
#include "screen.h"
#include "term.h"
#include "ui.h"
+#include "os/os.h"
#if defined(FEAT_FLOAT) && defined(HAVE_MATH_H)
# include <math.h>
@@ -736,11 +737,11 @@ int delete_first_msg(void) {
void ex_messages(exarg_T *eap)
{
struct msg_hist *p;
- char_u *s;
+ const char *s;
msg_hist_off = TRUE;
- s = mch_getenv((char_u *)"LANG");
+ s = mch_getenv("LANG");
if (s != NULL && *s != NUL)
msg_attr((char_u *)
_("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
diff --git a/src/misc1.c b/src/misc1.c
index ab21f8d6a5..b391cb1ee4 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -45,11 +45,6 @@
#include "undo.h"
#include "window.h"
#include "os/os.h"
-
-#ifdef HAVE_CRT_EXTERNS_H
-#include <crt_externs.h>
-#endif
-
static char_u *vim_version_dir(char_u *vimdir);
static char_u *remove_tail(char_u *p, char_u *pend, char_u *name);
static void init_users(void);
@@ -2727,7 +2722,7 @@ void init_homedir(void) {
vim_free(homedir);
homedir = NULL;
- var = mch_getenv((char_u *)"HOME");
+ var = (char_u *)mch_getenv("HOME");
if (var != NULL && *var == NUL) /* empty is same as not set */
var = NULL;
@@ -3052,7 +3047,7 @@ char_u *vim_getenv(char_u *name, int *mustfree)
int vimruntime;
- p = mch_getenv(name);
+ p = (char_u *)mch_getenv((char *)name);
if (p != NULL && *p == NUL) /* empty is the same as not set */
p = NULL;
@@ -3073,7 +3068,7 @@ char_u *vim_getenv(char_u *name, int *mustfree)
&& *default_vimruntime_dir == NUL
#endif
) {
- p = mch_getenv((char_u *)"VIM");
+ p = (char_u *)mch_getenv("VIM");
if (p != NULL && *p == NUL) /* empty is the same as not set */
p = NULL;
if (p != NULL) {
@@ -3081,7 +3076,7 @@ char_u *vim_getenv(char_u *name, int *mustfree)
if (p != NULL)
*mustfree = TRUE;
else
- p = mch_getenv((char_u *)"VIM");
+ p = (char_u *)mch_getenv("VIM");
}
}
@@ -3223,21 +3218,7 @@ static char_u *remove_tail(char_u *p, char_u *pend, char_u *name)
*/
void vim_setenv(char_u *name, char_u *val)
{
-#ifdef HAVE_SETENV
mch_setenv((char *)name, (char *)val, 1);
-#else
- char_u *envbuf;
-
- /*
- * Putenv does not copy the string, it has to remain
- * valid. The allocated memory will never be freed.
- */
- envbuf = alloc((unsigned)(STRLEN(name) + STRLEN(val) + 2));
- if (envbuf != NULL) {
- sprintf((char *)envbuf, "%s=%s", name, val);
- putenv((char *)envbuf);
- }
-#endif
/*
* When setting $VIMRUNTIME adjust the directory to find message
* translations to $VIMRUNTIME/lang.
@@ -3258,35 +3239,17 @@ void vim_setenv(char_u *name, char_u *val)
*/
char_u *get_env_name(expand_T *xp, int idx)
{
-# if defined(AMIGA) || defined(__MRC__) || defined(__SC__)
- /*
- * No environ[] on the Amiga and on the Mac (using MPW).
- */
- return NULL;
-# else
-# if !defined(__WIN32__) && !defined(HAVE__NSGETENVIRON)
- /* Borland C++ 5.2 has this in a header file. */
- extern char **environ;
-# else
- char **environ = *_NSGetEnviron();
-# endif
# define ENVNAMELEN 100
+ // this static buffer is needed to avoid a memory leak in ExpandGeneric
static char_u name[ENVNAMELEN];
- char_u *str;
- int n;
-
- str = (char_u *)environ[idx];
- if (str == NULL)
+ char *envname = mch_getenvname_at_index(idx);
+ if (envname) {
+ vim_strncpy(name, (char_u *)envname, ENVNAMELEN - 1);
+ vim_free(envname);
+ return name;
+ } else {
return NULL;
-
- for (n = 0; n < ENVNAMELEN - 1; ++n) {
- if (str[n] == '=' || str[n] == NUL)
- break;
- name[n] = str[n];
}
- name[n] = NUL;
- return name;
-# endif
}
/*
@@ -3396,7 +3359,7 @@ home_replace (
if (homedir != NULL)
dirlen = STRLEN(homedir);
- homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME");
+ homedir_env_orig = homedir_env = (char_u *)mch_getenv("HOME");
/* Empty is the same as not set. */
if (homedir_env != NULL && *homedir_env == NUL)
homedir_env = NULL;
diff --git a/src/misc2.c b/src/misc2.c
index 1b1693a72a..92a6af598b 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -2250,154 +2250,6 @@ int pathcmp(const char *p, const char *q, int maxlen)
#endif
/*
- * The putenv() implementation below comes from the "screen" program.
- * Included with permission from Juergen Weigert.
- * See pty.c for the copyright notice.
- */
-
-/*
- * putenv -- put value into environment
- *
- * Usage: i = putenv (string)
- * int i;
- * char *string;
- *
- * where string is of the form <name>=<value>.
- * Putenv returns 0 normally, -1 on error (not enough core for malloc).
- *
- * Putenv may need to add a new name into the environment, or to
- * associate a value longer than the current value with a particular
- * name. So, to make life simpler, putenv() copies your entire
- * environment into the heap (i.e. malloc()) from the stack
- * (i.e. where it resides when your process is initiated) the first
- * time you call it.
- *
- * (history removed, not very interesting. See the "screen" sources.)
- */
-
-#if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV)
-
-#define EXTRASIZE 5 /* increment to add to env. size */
-
-static int envsize = -1; /* current size of environment */
-extern
-char **environ; /* the global which is your env. */
-
-static int findenv(char *name); /* look for a name in the env. */
-static int newenv(void); /* copy env. from stack to heap */
-static int moreenv(void); /* incr. size of env. */
-
-int putenv(const char *string)
-{
- int i;
- char *p;
-
- if (envsize < 0) { /* first time putenv called */
- if (newenv() < 0) /* copy env. to heap */
- return -1;
- }
-
- i = findenv((char *)string); /* look for name in environment */
-
- if (i < 0) { /* name must be added */
- for (i = 0; environ[i]; i++) ;
- if (i >= (envsize - 1)) { /* need new slot */
- if (moreenv() < 0)
- return -1;
- }
- p = (char *)alloc((unsigned)(strlen(string) + 1));
- if (p == NULL) /* not enough core */
- return -1;
- environ[i + 1] = 0; /* new end of env. */
- } else { /* name already in env. */
- p = vim_realloc(environ[i], strlen(string) + 1);
- if (p == NULL)
- return -1;
- }
- sprintf(p, "%s", string); /* copy into env. */
- environ[i] = p;
-
- return 0;
-}
-
-static int findenv(char *name)
-{
- char *namechar, *envchar;
- int i, found;
-
- found = 0;
- for (i = 0; environ[i] && !found; i++) {
- envchar = environ[i];
- namechar = name;
- while (*namechar && *namechar != '=' && (*namechar == *envchar)) {
- namechar++;
- envchar++;
- }
- found = ((*namechar == '\0' || *namechar == '=') && *envchar == '=');
- }
- return found ? i - 1 : -1;
-}
-
-static int newenv(void) {
- char **env, *elem;
- int i, esize;
-
- for (i = 0; environ[i]; i++)
- ;
- esize = i + EXTRASIZE + 1;
- env = (char **)alloc((unsigned)(esize * sizeof (elem)));
- if (env == NULL)
- return -1;
-
- for (i = 0; environ[i]; i++) {
- elem = (char *)alloc((unsigned)(strlen(environ[i]) + 1));
- if (elem == NULL)
- return -1;
- env[i] = elem;
- strcpy(elem, environ[i]);
- }
-
- env[i] = 0;
- environ = env;
- envsize = esize;
- return 0;
-}
-
-static int moreenv(void) {
- int esize;
- char **env;
-
- esize = envsize + EXTRASIZE;
- env = (char **)vim_realloc((char *)environ, esize * sizeof (*env));
- if (env == 0)
- return -1;
- environ = env;
- envsize = esize;
- return 0;
-}
-
-# ifdef USE_VIMPTY_GETENV
-char_u *vimpty_getenv(const char_u *string)
-{
- int i;
- char_u *p;
-
- if (envsize < 0)
- return NULL;
-
- i = findenv((char *)string);
-
- if (i < 0)
- return NULL;
-
- p = vim_strchr((char_u *)environ[i], '=');
- return p + 1;
-}
-# endif
-
-#endif /* !defined(HAVE_SETENV) && !defined(HAVE_PUTENV) */
-
-/*
* Return 0 for not writable, 1 for writable file, 2 for a dir which we have
* rights to write into.
*/
diff --git a/src/option.c b/src/option.c
index 8daac5b5e1..e257186cf2 100644
--- a/src/option.c
+++ b/src/option.c
@@ -67,6 +67,7 @@
#include "ui.h"
#include "undo.h"
#include "window.h"
+#include "os/os.h"
/*
* The options that are local to a window or buffer have "indir" set to one of
@@ -1961,7 +1962,7 @@ void set_init_1(void) {
p_cp = TRUE;
/* Use POSIX compatibility when $VIM_POSIX is set. */
- if (mch_getenv((char_u *)"VIM_POSIX") != NULL) {
+ if (mch_getenv("VIM_POSIX") != NULL) {
set_string_default("cpo", (char_u *)CPO_ALL);
set_string_default("shm", (char_u *)"A");
}
@@ -1970,7 +1971,7 @@ void set_init_1(void) {
* Find default value for 'shell' option.
* Don't use it if it is empty.
*/
- if (((p = mch_getenv((char_u *)"SHELL")) != NULL && *p != NUL)
+ if (((p = (char_u *)mch_getenv("SHELL")) != NULL && *p != NUL)
)
set_string_default("sh", p);
@@ -2170,7 +2171,7 @@ void set_init_1(void) {
* NOTE: mlterm's author is being asked to 'set' a variable
* instead of an environment variable due to inheritance.
*/
- if (mch_getenv((char_u *)"MLTERM") != NULL)
+ if (mch_getenv("MLTERM") != NULL)
set_option_value((char_u *)"tbidi", 1L, NULL, 0);
/* Parse default for 'fillchars'. */
@@ -2447,7 +2448,7 @@ static char_u *term_bg_default(void) {
|| STRCMP(T_NAME, "screen.linux") == 0
|| STRCMP(T_NAME, "cygwin") == 0
|| STRCMP(T_NAME, "putty") == 0
- || ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL
+ || ((p = (char_u *)mch_getenv("COLORFGBG")) != NULL
&& (p = vim_strrchr(p, ';')) != NULL
&& ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
&& p[2] == NUL))
diff --git a/src/os/env.c b/src/os/env.c
new file mode 100644
index 0000000000..9025b1c8ac
--- /dev/null
+++ b/src/os/env.c
@@ -0,0 +1,65 @@
+/* vi:set ts=2 sts=2 sw=2:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * env.c -- environment variable access
+ */
+
+#include <uv.h>
+
+#include "os.h"
+#include "../misc2.h"
+
+#ifdef HAVE_CRT_EXTERNS_H
+#include <crt_externs.h>
+#endif
+
+const char *mch_getenv(const char *name)
+{
+ return getenv(name);
+}
+
+int mch_setenv(const char *name, const char *value, int overwrite)
+{
+ return setenv(name, value, overwrite);
+}
+
+char *mch_getenvname_at_index(size_t index)
+{
+# if defined(AMIGA) || defined(__MRC__) || defined(__SC__)
+ /*
+ * No environ[] on the Amiga and on the Mac (using MPW).
+ */
+ return NULL;
+# else
+# if defined(HAVE__NSGETENVIRON)
+ char **environ = *_NSGetEnviron();
+# elif !defined(__WIN32__)
+ /* Borland C++ 5.2 has this in a header file. */
+ extern char **environ;
+# endif
+ // check if index is inside the environ array
+ for (size_t i = 0; i < index; i++) {
+ if (environ[i] == NULL) {
+ return NULL;
+ }
+ }
+ char *str = environ[index];
+ if (str == NULL) {
+ return NULL;
+ }
+ int namesize = 0;
+ while (str[namesize] != '=' && str[namesize] != NUL) {
+ namesize++;
+ }
+ char *name = (char *)vim_strnsave((char_u *)str, namesize);
+ return name;
+# endif
+}
+
diff --git a/src/os/os.h b/src/os/os.h
index bc7496ed58..266b253e86 100644
--- a/src/os/os.h
+++ b/src/os/os.h
@@ -9,5 +9,8 @@ int mch_dirname(char_u *buf, int len);
int mch_get_absolute_path(char_u *fname, char_u *buf, int len, int force);
int mch_is_absolute_path(char_u *fname);
int mch_isdir(char_u *name);
+const char *mch_getenv(const char *name);
+int mch_setenv(const char *name, const char *value, int overwrite);
+char *mch_getenvname_at_index(size_t index);
#endif
diff --git a/src/os_unix.c b/src/os_unix.c
index 40eba52da8..5a01f07c36 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1349,7 +1349,7 @@ int mch_can_exe(char_u *name)
name[2] == '/'))))
return executable_file(name);
- p = (char_u *)getenv("PATH");
+ p = (char_u *)mch_getenv("PATH");
if (p == NULL || *p == NUL)
return -1;
buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
@@ -1837,9 +1837,9 @@ int mch_get_shellsize() {
* the ioctl() values!
*/
if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL) {
- if ((p = (char_u *)getenv("LINES")))
+ if ((p = (char_u *)mch_getenv("LINES")))
rows = atoi((char *)p);
- if ((p = (char_u *)getenv("COLUMNS")))
+ if ((p = (char_u *)mch_getenv("COLUMNS")))
columns = atoi((char *)p);
}
@@ -1950,12 +1950,7 @@ int options; /* SHELL_*, see vim.h */
int fd_toshell[2]; /* for pipes */
int fd_fromshell[2];
int pipe_error = FALSE;
-# ifdef HAVE_SETENV
char envbuf[50];
-# else
- static char envbuf_Rows[20];
- static char envbuf_Columns[20];
-# endif
int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
newcmd = vim_strsave(p_sh);
@@ -2125,27 +2120,13 @@ int options; /* SHELL_*, see vim.h */
}
# endif
/* Simulate to have a dumb terminal (for now) */
-# ifdef HAVE_SETENV
- setenv("TERM", "dumb", 1);
+ mch_setenv("TERM", "dumb", 1);
sprintf((char *)envbuf, "%ld", Rows);
- setenv("ROWS", (char *)envbuf, 1);
+ mch_setenv("ROWS", (char *)envbuf, 1);
sprintf((char *)envbuf, "%ld", Rows);
- setenv("LINES", (char *)envbuf, 1);
+ mch_setenv("LINES", (char *)envbuf, 1);
sprintf((char *)envbuf, "%ld", Columns);
- setenv("COLUMNS", (char *)envbuf, 1);
-# else
- /*
- * Putenv does not copy the string, it has to remain valid.
- * Use a static array to avoid losing allocated memory.
- */
- putenv("TERM=dumb");
- sprintf(envbuf_Rows, "ROWS=%ld", Rows);
- putenv(envbuf_Rows);
- sprintf(envbuf_Rows, "LINES=%ld", Rows);
- putenv(envbuf_Rows);
- sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
- putenv(envbuf_Columns);
-# endif
+ mch_setenv("COLUMNS", (char *)envbuf, 1);
/*
* stderr is only redirected when using the GUI, so that a
diff --git a/src/os_unix_defs.h b/src/os_unix_defs.h
index 3aacac69a0..74b98ef68a 100644
--- a/src/os_unix_defs.h
+++ b/src/os_unix_defs.h
@@ -280,14 +280,6 @@
# else
int mch_rename(const char *src, const char *dest);
# endif
-# ifdef __MVS__
-/* on OS390 Unix getenv() doesn't return a pointer to persistent
- * storage -> use __getenv() */
-# define mch_getenv(x) (char_u *)__getenv((char *)(x))
-# else
-# define mch_getenv(x) (char_u *)getenv((char *)(x))
-# endif
-# define mch_setenv(name, val, x) setenv(name, val, x)
#if !defined(S_ISDIR) && defined(S_IFDIR)
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
diff --git a/src/term.c b/src/term.c
index 15a4320db4..4e405f732a 100644
--- a/src/term.c
+++ b/src/term.c
@@ -45,6 +45,7 @@
#include "syntax.h"
#include "ui.h"
#include "window.h"
+#include "os/os.h"
#ifdef HAVE_TGETENT
# ifdef HAVE_TERMIOS_H
@@ -2021,7 +2022,7 @@ void termcapinit(char_u *name)
term = name;
if (term == NULL)
- term = mch_getenv((char_u *)"TERM");
+ term = (char_u *)mch_getenv("TERM");
if (term == NULL || *term == NUL)
term = DEFAULT_TERM;
set_string_option_direct((char_u *)"term", -1, term, OPT_FREE, 0);
diff --git a/test/unit/os/env.moon b/test/unit/os/env.moon
new file mode 100644
index 0000000000..b83fcac5f1
--- /dev/null
+++ b/test/unit/os/env.moon
@@ -0,0 +1,95 @@
+{:cimport, :internalize, :eq, :ffi, :lib, :cstr} = require 'test.unit.helpers'
+require 'lfs'
+
+-- fs = cimport './src/os/os.h'
+-- remove these statements once 'cimport' is working properly for misc1.h
+env = lib
+ffi.cdef [[
+const char *mch_getenv(const char *name);
+int mch_setenv(const char *name, const char *value, int override);
+char *mch_getenvname_at_index(size_t index);
+]]
+
+str_to_charp = (str) ->
+ cstr (string.len str), str
+
+NULL = ffi.cast 'void*', 0
+
+describe 'env function', ->
+
+ mch_setenv = (name, value, override) ->
+ env.mch_setenv (str_to_charp name), (str_to_charp value), override
+
+ mch_getenv = (name) ->
+ rval = env.mch_getenv (str_to_charp name)
+ if rval != NULL
+ ffi.string rval
+ else
+ NULL
+
+ describe 'mch_setenv', ->
+
+ OK = 0
+
+ it 'sets an env variable and returns OK', ->
+ name = 'NEOVIM_UNIT_TEST_SETENV_1N'
+ value = 'NEOVIM_UNIT_TEST_SETENV_1V'
+ eq nil, os.getenv name
+ eq OK, (mch_setenv name, value, 1)
+ eq value, os.getenv name
+
+ it "dosn't overwrite an env variable if overwrite is 0", ->
+ name = 'NEOVIM_UNIT_TEST_SETENV_2N'
+ value = 'NEOVIM_UNIT_TEST_SETENV_2V'
+ value_updated = 'NEOVIM_UNIT_TEST_SETENV_2V_UPDATED'
+ eq OK, (mch_setenv name, value, 0)
+ eq value, os.getenv name
+ eq OK, (mch_setenv name, value_updated, 0)
+ eq value, os.getenv name
+
+ describe 'mch_getenv', ->
+
+ it 'reads an env variable', ->
+ name = 'NEOVIM_UNIT_TEST_GETENV_1N'
+ value = 'NEOVIM_UNIT_TEST_GETENV_1V'
+ eq NULL, mch_getenv name
+ -- need to use mch_setenv, because lua dosn't have a setenv function
+ mch_setenv name, value, 1
+ eq value, mch_getenv name
+
+ it 'returns NULL if the env variable is not found', ->
+ name = 'NEOVIM_UNIT_TEST_GETENV_NOTFOUND'
+ eq NULL, mch_getenv name
+
+ describe 'mch_getenvname_at_index', ->
+
+ it 'returns names of environment variables', ->
+ test_name = 'NEOVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1N'
+ test_value = 'NEOVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1V'
+ mch_setenv test_name, test_value, 1
+ i = 0
+ names = {}
+ found_name = false
+ name = env.mch_getenvname_at_index i
+ while name != NULL
+ table.insert names, ffi.string name
+ if (ffi.string name) == test_name
+ found_name = true
+ i += 1
+ name = env.mch_getenvname_at_index i
+
+ eq true, (table.getn names) > 0
+ eq true, found_name
+
+ it 'returns NULL if the index is out of bounds', ->
+ huge = ffi.new 'size_t', 10000
+ maxuint32 = ffi.new 'size_t', 4294967295
+ eq NULL, env.mch_getenvname_at_index huge
+ eq NULL, env.mch_getenvname_at_index maxuint32
+ if ffi.abi '64bit'
+ -- couldn't use a bigger number because it gets converted to
+ -- double somewere, should be big enough anyway
+ -- maxuint64 = ffi.new 'size_t', 18446744073709551615
+ maxuint64 = ffi.new 'size_t', 18446744073709000000
+ eq NULL, env.mch_getenvname_at_index maxuint64
+