1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
#include "lesstest.h"
extern TermInfo terminfo;
// EnvBuf has a char buffer (env_buf) which holds both the env var
// string table and also the array of pointers to individual strings (env_list).
// env_estr points to the end of the string table.
// The env_list array grows backwards from the end of env_buf.
void env_init(EnvBuf* env) {
env->env_estr = (char*) env->env_buf;
env->env_list = env->env_buf + sizeof(env->env_buf)/sizeof(char*);
*--(env->env_list) = NULL;
}
static void env_check(EnvBuf* env) {
if (env->env_estr >= (const char*) env->env_list) {
fprintf(stderr, "ENVBUF_SIZE too small!\n");
abort();
}
}
// Add a char to the string table.
static void env_addchar(EnvBuf* env, char ch) {
*(env->env_estr)++ = ch;
env_check(env);
}
// Add a delimited string to the string table.
static void env_addlstr(EnvBuf* env, const char* str, int strlen) {
while (strlen-- > 0)
env_addchar(env, *str++);
}
// Add a null-terminated string to the string table.
static void env_addstr(EnvBuf* env, const char* str) {
env_addlstr(env, str, strlen(str));
}
// Add an env variable name/value pair to an EnvBuf.
// The name is delimited and the value is null-terminated.
static void env_addlpair(EnvBuf* env, const char* name, int namelen, const char* value) {
*--(env->env_list) = env->env_estr;
env_check(env);
env_addlstr(env, name, namelen);
env_addstr(env, "=");
env_addstr(env, value);
env_addchar(env, '\0');
}
// Add an env variable name/value pair to an EnvBuf.
void env_addpair(EnvBuf* env, const char* name, const char* value) {
env_addlpair(env, name, strlen(name), value);
}
// Add an env variable name/value pair to an EnvBuf where the value is an integer.
void env_addintpair(EnvBuf* env, const char* name, int value) {
char buf[64];
snprintf(buf, sizeof(buf), "%d", value);
env_addpair(env, name, buf);
}
// Is a given env var name one which should be passed to less?
static int is_less_env(const char* name, int name_len) {
static char* const less_names[] = {
"LESS*", "COLUMNS", "LINES", "LANG", "LC_CTYPE", "MORE", NULL
};
char* const* n;
for (n = less_names; *n != NULL; ++n) {
int ln = strlen(*n);
if (ln == name_len && strncmp(*n, name, ln) == 0)
return 1;
if ((*n)[ln-1] == '*' && strncmp(*n, name, ln-1) == 0)
return 1;
}
return 0;
}
// Create a list of env vars to be given to an instance of less,
// as an EnvBuf.
static void env_setup(EnvBuf* env, char* const* prog_env, int interactive) {
char* const* envp;
struct tcvar { char const* name; char const* value; } tcvars[] = {
{ "LESS_TERMCAP_am", "1" },
{ "LESS_TERMCAP_cd", "\33S" },
{ "LESS_TERMCAP_ce", "\33L" },
{ "LESS_TERMCAP_cl", "\33A" },
{ "LESS_TERMCAP_cr", "\33<" },
{ "LESS_TERMCAP_cm", "\33%p2%d;%p1%dj" },
{ "LESS_TERMCAP_ho", "\33h" },
{ "LESS_TERMCAP_ll", "\33l" },
{ "LESS_TERMCAP_mb", "\33b" },
{ "LESS_TERMCAP_md", "\33[1m" },
{ "LESS_TERMCAP_me", "\33[m" },
{ "LESS_TERMCAP_se", "\33[m" },
{ "LESS_TERMCAP_so", "\33[7m" },
{ "LESS_TERMCAP_sr", "\33r" },
{ "LESS_TERMCAP_ue", "\33[24m" },
{ "LESS_TERMCAP_us", "\33[4m" },
{ "LESS_TERMCAP_vb", "\33g" },
{ "LESS_TERMCAP_kr", terminfo.key_right },
{ "LESS_TERMCAP_kl", terminfo.key_left },
{ "LESS_TERMCAP_ku", terminfo.key_up },
{ "LESS_TERMCAP_kd", terminfo.key_down },
{ "LESS_TERMCAP_kh", terminfo.key_home },
{ "LESS_TERMCAP_@7", terminfo.key_end },
};
if (interactive) {
int i;
for (i = 0; i < countof(tcvars); ++i) {
struct tcvar* tc = &tcvars[i];
env_addpair(env, tc->name, tc->value);
log_env(tc->name, strlen(tc->name), tc->value);
}
}
for (envp = prog_env; *envp != NULL; ++envp) {
const char* ename = *envp;
const char* eq = strchr(ename, '=');
if (eq == NULL) continue;
if (!interactive || is_less_env(ename, eq-ename)) {
env_addlpair(env, ename, eq-ename, eq+1);
log_env(ename, eq-ename, eq+1);
}
}
}
// Return the value of a named env var.
const char* get_envp(char* const* envp, const char* name) {
for (; *envp != NULL; ++envp) {
const char* ename = *envp;
const char* eq = strchr(ename, '=');
if (eq != NULL && strlen(name) == eq-ename && strncmp(name, ename, eq-ename) == 0)
return eq+1;
}
return NULL;
}
// Return a list of env vars to be given to an instance of less,
// as an array of strings.
char* const* less_envp(char* const* envp, int interactive) {
static EnvBuf less_env;
static int init = 0;
if (!init) {
env_init(&less_env);
env_setup(&less_env, envp, interactive);
init = 1;
}
return less_env.env_list;
}
|