tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

environ.c
Go to the documentation of this file.
1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 
21 #include <fnmatch.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include "tmux.h"
27 
28 /*
29  * Environment - manipulate a set of environment variables.
30  */
31 
33 static int environ_cmp(struct environ_entry *, struct environ_entry *);
35 
36 static int
37 environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
38 {
39  return (strcmp(envent1->name, envent2->name));
40 }
41 
42 /* Initialise the environment. */
43 struct environ *
45 {
46  struct environ *env;
47 
48  env = xcalloc(1, sizeof *env);
49  RB_INIT(env);
50 
51  return (env);
52 }
53 
54 /* Free an environment. */
55 void
56 environ_free(struct environ *env)
57 {
58  struct environ_entry *envent, *envent1;
59 
60  RB_FOREACH_SAFE(envent, environ, env, envent1) {
61  RB_REMOVE(environ, env, envent);
62  free(envent->name);
63  free(envent->value);
64  free(envent);
65  }
66  free(env);
67 }
68 
69 struct environ_entry *
70 environ_first(struct environ *env)
71 {
72  return (RB_MIN(environ, env));
73 }
74 
75 struct environ_entry *
76 environ_next(struct environ_entry *envent)
77 {
78  return (RB_NEXT(environ, env, envent));
79 }
80 
81 /* Copy one environment into another. */
82 void
83 environ_copy(struct environ *srcenv, struct environ *dstenv)
84 {
85  struct environ_entry *envent;
86 
87  RB_FOREACH(envent, environ, srcenv) {
88  if (envent->value == NULL)
89  environ_clear(dstenv, envent->name);
90  else {
91  environ_set(dstenv, envent->name, envent->flags,
92  "%s", envent->value);
93  }
94  }
95 }
96 
97 /* Find an environment variable. */
98 struct environ_entry *
99 environ_find(struct environ *env, const char *name)
100 {
101  struct environ_entry envent;
102 
103  envent.name = (char *) name;
104  return (RB_FIND(environ, env, &envent));
105 }
106 
107 /* Set an environment variable. */
108 void
109 environ_set(struct environ *env, const char *name, int flags, const char *fmt,
110  ...)
111 {
112  struct environ_entry *envent;
113  va_list ap;
114 
115  va_start(ap, fmt);
116  if ((envent = environ_find(env, name)) != NULL) {
117  envent->flags = flags;
118  free(envent->value);
119  xvasprintf(&envent->value, fmt, ap);
120  } else {
121  envent = xmalloc(sizeof *envent);
122  envent->name = xstrdup(name);
123  envent->flags = flags;
124  xvasprintf(&envent->value, fmt, ap);
125  RB_INSERT(environ, env, envent);
126  }
127  va_end(ap);
128 }
129 
130 /* Clear an environment variable. */
131 void
132 environ_clear(struct environ *env, const char *name)
133 {
134  struct environ_entry *envent;
135 
136  if ((envent = environ_find(env, name)) != NULL) {
137  free(envent->value);
138  envent->value = NULL;
139  } else {
140  envent = xmalloc(sizeof *envent);
141  envent->name = xstrdup(name);
142  envent->flags = 0;
143  envent->value = NULL;
144  RB_INSERT(environ, env, envent);
145  }
146 }
147 
148 /* Set an environment variable from a NAME=VALUE string. */
149 void
150 environ_put(struct environ *env, const char *var, int flags)
151 {
152  char *name, *value;
153 
154  value = strchr(var, '=');
155  if (value == NULL)
156  return;
157  value++;
158 
159  name = xstrdup(var);
160  name[strcspn(name, "=")] = '\0';
161 
162  environ_set(env, name, flags, "%s", value);
163  free(name);
164 }
165 
166 /* Unset an environment variable. */
167 void
168 environ_unset(struct environ *env, const char *name)
169 {
170  struct environ_entry *envent;
171 
172  if ((envent = environ_find(env, name)) == NULL)
173  return;
174  RB_REMOVE(environ, env, envent);
175  free(envent->name);
176  free(envent->value);
177  free(envent);
178 }
179 
180 /* Copy variables from a destination into a source environment. */
181 void
182 environ_update(struct options *oo, struct environ *src, struct environ *dst)
183 {
184  struct environ_entry *envent;
185  struct options_entry *o;
186  struct options_array_item *a;
187  union options_value *ov;
188 
189  o = options_get(oo, "update-environment");
190  if (o == NULL)
191  return;
192  a = options_array_first(o);
193  while (a != NULL) {
194  ov = options_array_item_value(a);
195  RB_FOREACH(envent, environ, src) {
196  if (fnmatch(ov->string, envent->name, 0) == 0)
197  break;
198  }
199  if (envent == NULL)
200  environ_clear(dst, ov->string);
201  else
202  environ_set(dst, envent->name, 0, "%s", envent->value);
203  a = options_array_next(a);
204  }
205 }
206 
207 /* Push environment into the real environment - use after fork(). */
208 void
209 environ_push(struct environ *env)
210 {
211  struct environ_entry *envent;
212 
213  environ = xcalloc(1, sizeof *environ);
214  RB_FOREACH(envent, environ, env) {
215  if (envent->value != NULL &&
216  *envent->name != '\0' &&
217  (~envent->flags & ENVIRON_HIDDEN))
218  setenv(envent->name, envent->value, 1);
219  }
220 }
221 
222 /* Log the environment. */
223 void
224 environ_log(struct environ *env, const char *fmt, ...)
225 {
226  struct environ_entry *envent;
227  va_list ap;
228  char *prefix;
229 
230  va_start(ap, fmt);
231  vasprintf(&prefix, fmt, ap);
232  va_end(ap);
233 
234  RB_FOREACH(envent, environ, env) {
235  if (envent->value != NULL && *envent->name != '\0') {
236  log_debug("%s%s=%s", prefix, envent->name,
237  envent->value);
238  }
239  }
240 
241  free(prefix);
242 }
243 
244 /* Create initial environment for new child. */
245 struct environ *
246 environ_for_session(struct session *s, int no_TERM)
247 {
248  struct environ *env;
249  const char *value;
250  int idx;
251 
252  env = environ_create();
254  if (s != NULL)
255  environ_copy(s->environ, env);
256 
257  if (!no_TERM) {
258  value = options_get_string(global_options, "default-terminal");
259  environ_set(env, "TERM", 0, "%s", value);
260  environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
261  environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
262  }
263 
264  if (s != NULL)
265  idx = s->id;
266  else
267  idx = -1;
268  environ_set(env, "TMUX", 0, "%s,%ld,%d", socket_path, (long)getpid(),
269  idx);
270 
271  return (env);
272 }
int vasprintf(char **, const char *, va_list)
int setenv(const char *, const char *, int)
void environ_unset(struct environ *env, const char *name)
Definition: environ.c:168
RB_HEAD(environ, environ_entry)
static int environ_cmp(struct environ_entry *, struct environ_entry *)
Definition: environ.c:37
void environ_clear(struct environ *env, const char *name)
Definition: environ.c:132
struct environ * environ_create(void)
Definition: environ.c:44
RB_GENERATE_STATIC(environ, environ_entry, entry, environ_cmp)
void environ_put(struct environ *env, const char *var, int flags)
Definition: environ.c:150
struct environ_entry * environ_find(struct environ *env, const char *name)
Definition: environ.c:99
void environ_push(struct environ *env)
Definition: environ.c:209
void environ_update(struct options *oo, struct environ *src, struct environ *dst)
Definition: environ.c:182
struct environ * environ_for_session(struct session *s, int no_TERM)
Definition: environ.c:246
void environ_set(struct environ *env, const char *name, int flags, const char *fmt,...)
Definition: environ.c:109
struct environ_entry * environ_next(struct environ_entry *envent)
Definition: environ.c:76
void environ_copy(struct environ *srcenv, struct environ *dstenv)
Definition: environ.c:83
void environ_log(struct environ *env, const char *fmt,...)
Definition: environ.c:224
struct environ_entry * environ_first(struct environ *env)
Definition: environ.c:70
void environ_free(struct environ *env)
Definition: environ.c:56
const char * name
Definition: layout-set.c:38
void log_debug(const char *msg,...)
Definition: log.c:130
union options_value * options_array_item_value(struct options_array_item *a)
Definition: options.c:549
const char * options_get_string(struct options *oo, const char *name)
Definition: options.c:686
struct options_array_item * options_array_first(struct options_entry *o)
Definition: options.c:529
struct options_array_item * options_array_next(struct options_array_item *a)
Definition: options.c:537
struct options_entry * options_get(struct options *oo, const char *name)
Definition: options.c:229
Definition: tmux.h:1160
char * value
Definition: tmux.h:1162
char * name
Definition: tmux.h:1161
int flags
Definition: tmux.h:1164
Definition: options.c:50
Definition: tmux.h:1179
u_int id
Definition: tmux.h:1180
struct environ * environ
Definition: tmux.h:1209
struct environ * global_environ
Definition: tmux.c:39
const char * socket_path
Definition: tmux.c:42
const char * getversion(void)
Definition: tmux.c:320
struct options * global_options
Definition: tmux.c:36
#define ENVIRON_HIDDEN
Definition: tmux.h:1165
char ** environ
char * string
Definition: tmux.h:1802
void * xmalloc(size_t size)
Definition: xmalloc.c:27
void * xcalloc(size_t nmemb, size_t size)
Definition: xmalloc.c:41
char * xstrdup(const char *str)
Definition: xmalloc.c:89
int xvasprintf(char **ret, const char *fmt, va_list ap)
Definition: xmalloc.c:122