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