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