Use dict_T to pass env vars to process spawning code

Co-authored-by: Matthieu Coudron <mattator@gmail.com>
This commit is contained in:
James McCoy
2020-07-31 01:17:24 -04:00
parent 55add1c1c8
commit 7f50c69268
7 changed files with 135 additions and 65 deletions

View File

@@ -20,6 +20,10 @@
# include <pty.h>
#endif
#ifdef __APPLE__
# include <crt_externs.h>
#endif
#include <uv.h>
#include "nvim/lib/klist.h"
@@ -151,31 +155,24 @@ void pty_process_teardown(Loop *loop)
uv_signal_stop(&loop->children_watcher);
}
static const char *ignored_env_vars[] = {
"COLUMNS",
"LINES",
"TERMCAP",
"COLORFGBG"
};
static void init_child(PtyProcess *ptyproc)
FUNC_ATTR_NONNULL_ALL
{
#if defined(HAVE__NSGETENVIRON)
char **environ = *_NSGetEnviron();
#else
extern char **environ;
#endif
// New session/process-group. #6530
setsid();
os_unsetenv("COLUMNS");
os_unsetenv("LINES");
os_unsetenv("TERMCAP");
os_unsetenv("COLORFGBG");
// setting COLORTERM to "truecolor" if termguicolors is set and 256
// otherwise, but only if it was set in the parent terminal at all
if (os_env_exists("COLORTERM")) {
const char *colorterm = os_getenv("COLORTERM");
if (colorterm != NULL) {
if (p_tgc) {
os_setenv("COLORTERM", "truecolor", 1);
} else {
os_setenv("COLORTERM", "256", 1);
}
} else {
os_unsetenv("COLORTERM");
}
}
signal(SIGCHLD, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGINT, SIG_DFL);
@@ -190,9 +187,49 @@ static void init_child(PtyProcess *ptyproc)
}
char *prog = ptyproc->process.argv[0];
os_setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1);
execvp(prog, ptyproc->process.argv);
if (proc->env) {
for (size_t i = 0; i < ARRAY_SIZE(ignored_env_vars); i++) {
dictitem_T *dv = tv_dict_find(proc->env, ignored_env_vars[i], -1);
if (dv) {
tv_dict_item_remove(proc->env, dv);
}
}
tv_dict_add_str(proc->env, S_LEN("TERM"), ptyproc->term_name ? ptyproc->term_name : "ansi");
// setting COLORTERM to "truecolor" if termguicolors is set and 256
// otherwise, but only if it was set in the parent terminal at all
dictitem_T *dv = tv_dict_find(proc->env, S_LEN("COLORTERM"));
if (dv) {
tv_dict_item_remove(proc->env, dv);
tv_dict_add_str(proc->env, S_LEN("COLORTERM"), p_tgc ? "truecolor" : "256");
}
environ = tv_dict_to_env(proc->env);
} else {
for (size_t i = 0; i < ARRAY_SIZE(ignored_env_vars); i++) {
os_unsetenv(ignored_env_vars[i]);
}
// setting COLORTERM to "truecolor" if termguicolors is set and 256
// otherwise, but only if it was set in the parent terminal at all
if (os_env_exists("COLORTERM")) {
const char *colorterm = os_getenv("COLORTERM");
if (colorterm != NULL) {
if (p_tgc) {
os_setenv("COLORTERM", "truecolor", 1);
} else {
os_setenv("COLORTERM", "256", 1);
}
} else {
os_unsetenv("COLORTERM");
}
}
os_setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1);
}
execvp(prog, proc->argv);
ELOG("execvp failed: %s: %s", strerror(errno), prog);
_exit(122); // 122 is EXEC_FAILED in the Vim source.
}