]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/environ.cc
Remove unneeded header files from source files throughout.
[newlib-cygwin.git] / winsup / cygwin / environ.cc
CommitLineData
1fd5e000
CF
1/* environ.cc: Cygwin-adopted functions from newlib to manipulate
2 process's environment.
3
0ae86d18 4 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
a7d2cc16 5 2006, 2007, 2008 Red Hat, Inc.
1fd5e000
CF
6
7This software is a copyrighted work licensed under the terms of the
8Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9details. */
10
4c8d72de 11#include "winsup.h"
1fd5e000 12#include <stdlib.h>
5ab0b5cf 13#include <wchar.h>
752b16ce 14#include <wctype.h>
1fd5e000 15#include <ctype.h>
12a2ef44 16#include <assert.h>
f0338f54 17#include <cygwin/version.h>
a7197550 18#include <winnls.h>
e2ebe117 19#include "pinfo.h"
95a8465b 20#include "perprocess.h"
bccd5e0d 21#include "path.h"
9e2baf8d 22#include "cygerrno.h"
169c465a 23#include "fhandler.h"
0381fec6 24#include "dtable.h"
d8242040 25#include "cygheap.h"
f4a1f8a1 26#include "cygtls.h"
752b16ce 27#include "tls_pbuf.h"
f0338f54
CF
28#include "registry.h"
29#include "environ.h"
7c02f861 30#include "child_info.h"
1fd5e000 31
01bbb24d 32extern bool dos_file_warning;
3872e9a4 33extern bool allow_glob;
95a8465b 34extern bool ignore_case_with_glob;
3872e9a4
CF
35extern bool allow_winsymlinks;
36extern bool strip_title_path;
70c370d6 37extern int pcheck_case;
3872e9a4 38bool reset_com = false;
3872e9a4 39static bool envcache = true;
4392d36c
CF
40#ifdef USE_SERVER
41extern bool allow_server;
42#endif
1fd5e000 43
08b78edf 44static char **lastenviron;
b0e82b74 45
edab6053
CV
46/* Helper functions for the below environment variables which have to
47 be converted Win32<->POSIX. */
48extern "C" ssize_t env_PATH_to_posix (const void *, void *, size_t);
49
50ssize_t
51env_plist_to_posix (const void *win32, void *posix, size_t size)
52{
53 return cygwin_conv_path_list (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, win32,
54 posix, size);
55}
56
57ssize_t
58env_plist_to_win32 (const void *posix, void *win32, size_t size)
59{
60 return cygwin_conv_path_list (CCP_POSIX_TO_WIN_A | CCP_RELATIVE, posix,
61 win32, size);
62}
63
64ssize_t
65env_path_to_posix (const void *win32, void *posix, size_t size)
66{
67 return cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, win32,
68 posix, size);
69}
70
71ssize_t
72env_path_to_win32 (const void *posix, void *win32, size_t size)
73{
74 return cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, posix,
75 win32, size);
76}
6f1d4862 77
9bc846bd
CF
78#define ENVMALLOC \
79 (CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor) \
80 <= CYGWIN_VERSION_DLL_MALLOC_ENV)
81
a05a9e01 82#define NL(x) x, (sizeof (x) - 1)
1fd5e000 83/* List of names which are converted from dos to unix
ee1d77e4 84 on the way in and back again on the way out.
94b03f23 85
ee1d77e4
CF
86 PATH needs to be here because CreateProcess uses it and gdb uses
87 CreateProcess. HOME is here because most shells use it and would be
88 confused by Windows style path names. */
ac300315 89static win_env conv_envvars[] =
1fd5e000 90 {
edab6053
CV
91 {NL ("PATH="), NULL, NULL, env_PATH_to_posix, env_plist_to_win32, true},
92 {NL ("HOME="), NULL, NULL, env_path_to_posix, env_path_to_win32, false},
93 {NL ("LD_LIBRARY_PATH="), NULL, NULL,
94 env_plist_to_posix, env_plist_to_win32, true},
95 {NL ("TMPDIR="), NULL, NULL, env_path_to_posix, env_path_to_win32, false},
96 {NL ("TMP="), NULL, NULL, env_path_to_posix, env_path_to_win32, false},
97 {NL ("TEMP="), NULL, NULL, env_path_to_posix, env_path_to_win32, false},
98 {NULL, 0, NULL, NULL, 0, 0}
1fd5e000
CF
99 };
100
6e8f36bc
DD
101static unsigned char conv_start_chars[256] = {0};
102
47dc3dec
CF
103struct win_env&
104win_env::operator = (struct win_env& x)
105{
106 name = x.name;
107 namelen = x.namelen;
108 toposix = x.toposix;
109 towin32 = x.towin32;
47dc3dec
CF
110 immediate = false;
111 return *this;
112}
113
114win_env::~win_env ()
115{
116 if (posix)
117 free (posix);
118 if (native)
119 free (native);
120}
121
1fd5e000
CF
122void
123win_env::add_cache (const char *in_posix, const char *in_native)
124{
ebd645e7 125 MALLOC_CHECK;
1fd5e000
CF
126 posix = (char *) realloc (posix, strlen (in_posix) + 1);
127 strcpy (posix, in_posix);
128 if (in_native)
129 {
130 native = (char *) realloc (native, namelen + 1 + strlen (in_native));
0c55f6ed
CF
131 strcpy (native, name);
132 strcpy (native + namelen, in_native);
1fd5e000
CF
133 }
134 else
135 {
752b16ce
CV
136 tmp_pathbuf tp;
137 char *buf = tp.c_get ();
1feea0bf 138 strcpy (buf, name + namelen);
edab6053 139 towin32 (in_posix, buf, NT_MAX_PATH);
1feea0bf 140 native = (char *) realloc (native, namelen + 1 + strlen (buf));
0c55f6ed 141 strcpy (native, name);
1feea0bf 142 strcpy (native + namelen, buf);
1fd5e000 143 }
ebd645e7 144 MALLOC_CHECK;
77ae8757 145 if (immediate && cygwin_finished_initializing)
47dc3dec
CF
146 {
147 char s[namelen];
148 size_t n = namelen - 1;
149 memcpy (s, name, n);
150 s[n] = '\0';
151 SetEnvironmentVariable (s, native + namelen);
152 }
1fd5e000
CF
153 debug_printf ("posix %s", posix);
154 debug_printf ("native %s", native);
155}
156
157
158/* Check for a "special" environment variable name. *env is the pointer
12a2ef44
CF
159 to the beginning of the environment variable name. *in_posix is any
160 known posix value for the environment variable. Returns a pointer to
161 the appropriate conversion structure. */
2b706f3f 162win_env * __stdcall
47dc3dec 163getwinenv (const char *env, const char *in_posix, win_env *temp)
1fd5e000 164{
6e8f36bc
DD
165 if (!conv_start_chars[(unsigned char)*env])
166 return NULL;
167
1fd5e000 168 for (int i = 0; conv_envvars[i].name != NULL; i++)
0381fec6 169 if (strncmp (env, conv_envvars[i].name, conv_envvars[i].namelen) == 0)
1fd5e000 170 {
47dc3dec 171 win_env *we = conv_envvars + i;
1fd5e000 172 const char *val;
12a2ef44 173 if (!cur_environ () || !(val = in_posix ?: getenv (we->name)))
1fd5e000
CF
174 debug_printf ("can't set native for %s since no environ yet",
175 we->name);
17743fbc 176 else if (!envcache || !we->posix || strcmp (val, we->posix) != 0)
47dc3dec
CF
177 {
178 if (temp)
179 {
180 *temp = *we;
181 we = temp;
182 }
183 we->add_cache (val);
184 }
1fd5e000
CF
185 return we;
186 }
187 return NULL;
188}
189
190/* Convert windows path specs to POSIX, if appropriate.
191 */
192static void __stdcall
752b16ce 193posify (char **here, const char *value, char *outenv)
1fd5e000
CF
194{
195 char *src = *here;
196 win_env *conv;
1fd5e000
CF
197
198 if (!(conv = getwinenv (src)))
199 return;
200
ac944e37
CF
201 int len = strcspn (src, "=") + 1;
202
b0e82b74
CF
203 /* Turn all the items from c:<foo>;<bar> into their
204 mounted equivalents - if there is one. */
1fd5e000 205
b0e82b74 206 memcpy (outenv, src, len);
6f1d4862 207 char *newvalue = outenv + len;
edab6053
CV
208 if (!conv->toposix (value, newvalue, NT_MAX_PATH - len)
209 || _impure_ptr->_errno != EIDRM)
6f1d4862
CF
210 conv->add_cache (newvalue, *value != '/' ? value : NULL);
211 else
212 {
213 /* The conversion routine removed elements from a path list so we have
214 to recalculate the windows path to remove elements there, too. */
215 char cleanvalue[strlen (value) + 1];
edab6053 216 conv->towin32 (newvalue, cleanvalue, sizeof cleanvalue);
6f1d4862
CF
217 conv->add_cache (newvalue, cleanvalue);
218 }
1fd5e000 219
b0e82b74 220 debug_printf ("env var converted to %s", outenv);
1feea0bf 221 *here = strdup (outenv);
b0e82b74 222 free (src);
ebd645e7 223 MALLOC_CHECK;
1fd5e000
CF
224}
225
478e8b15
CF
226/* Returns pointer to value associated with name, if any, else NULL.
227 Sets offset to be the offset of the name/value combination in the
228 environment array, for use by setenv(3) and unsetenv(3).
229 Explicitly removes '=' in argument name. */
1fd5e000
CF
230
231static char * __stdcall
232my_findenv (const char *name, int *offset)
233{
234 register int len;
235 register char **p;
236 const char *c;
237
238 c = name;
239 len = 0;
240 while (*c && *c != '=')
241 {
242 c++;
243 len++;
244 }
245
4c8d72de 246 for (p = cur_environ (); *p; ++p)
1fd5e000
CF
247 if (!strncmp (*p, name, len))
248 if (*(c = *p + len) == '=')
249 {
4c8d72de 250 *offset = p - cur_environ ();
1fd5e000
CF
251 return (char *) (++c);
252 }
ebd645e7 253 MALLOC_CHECK;
1fd5e000
CF
254 return NULL;
255}
34f5d087 256
16dc3c95 257/* Primitive getenv before the environment is built. */
33b0abd1 258
16dc3c95 259static char __stdcall *
3a83d3a8 260getearly (const char * name, int *)
33b0abd1 261{
3a83d3a8 262 char *ret;
16dc3c95 263 char **ptr;
3a83d3a8 264 int len;
16dc3c95 265
3a83d3a8
CF
266 if (spawn_info && (ptr = spawn_info->moreinfo->envp))
267 {
268 len = strlen (name);
269 for (; *ptr; ptr++)
a2649dc6 270 if (strncasematch (name, *ptr, len) && (*ptr)[len] == '=')
3a83d3a8
CF
271 return *ptr + len + 1;
272 }
5ab0b5cf 273 else if ((len = GetEnvironmentVariableA (name, NULL, 0))
ee4388c4 274 && (ret = (char *) cmalloc_abort (HEAP_2_STR, len))
5ab0b5cf 275 && GetEnvironmentVariableA (name, ret, len))
3a83d3a8 276 return ret;
33b0abd1 277
33b0abd1
CV
278 return NULL;
279}
280
281static char * (*findenv_func)(const char *, int *) = (char * (*)(const char *, int *)) getearly;
282
16dc3c95 283/* Returns ptr to value associated with name, if any, else NULL. */
1fd5e000 284
2b706f3f 285extern "C" char *
1fd5e000
CF
286getenv (const char *name)
287{
288 int offset;
33b0abd1 289 return findenv_func (name, &offset);
1fd5e000
CF
290}
291
da086d02
CF
292static int __stdcall
293envsize (const char * const *in_envp)
b0e82b74
CF
294{
295 const char * const *envp;
296 for (envp = in_envp; *envp; envp++)
da086d02 297 continue;
b0e82b74
CF
298 return (1 + envp - in_envp) * sizeof (const char *);
299}
300
2a1a9785
CF
301/* Takes similar arguments to setenv except that overwrite is
302 either -1, 0, or 1. 0 or 1 signify that the function should
303 perform similarly to setenv. Otherwise putenv is assumed. */
304static int __stdcall
305_addenv (const char *name, const char *value, int overwrite)
1fd5e000 306{
2a1a9785
CF
307 int issetenv = overwrite >= 0;
308 int offset;
309 char *p;
1fd5e000 310
2a1a9785
CF
311 unsigned int valuelen = strlen (value);
312 if ((p = my_findenv (name, &offset)))
313 { /* Already exists. */
314 if (!overwrite) /* Ok to overwrite? */
315 return 0; /* No. Wanted to add new value. FIXME: Right return value? */
1fd5e000 316
2a1a9785
CF
317 /* We've found the offset into environ. If this is a setenv call and
318 there is room in the current environment entry then just overwrite it.
319 Otherwise handle this case below. */
320 if (issetenv && strlen (p) >= valuelen)
321 {
322 strcpy (p, value);
1fd5e000
CF
323 return 0;
324 }
325 }
326 else
2a1a9785 327 { /* Create new slot. */
b0e82b74 328 int sz = envsize (cur_environ ());
ebd645e7 329 int allocsz = sz + (2 * sizeof (char *));
2a1a9785 330
b0e82b74 331 offset = (sz - 1) / sizeof (char *);
2a1a9785
CF
332
333 /* Allocate space for additional element plus terminating NULL. */
ebd645e7 334 if (cur_environ () == lastenviron)
b0e82b74
CF
335 lastenviron = __cygwin_environ = (char **) realloc (cur_environ (),
336 allocsz);
337 else if ((lastenviron = (char **) malloc (allocsz)) != NULL)
338 __cygwin_environ = (char **) memcpy ((char **) lastenviron,
339 __cygwin_environ, sz);
340
b0d5cd02 341 if (!__cygwin_environ)
ad30b4ff 342 {
64ef9db7 343#ifdef DEBUGGING
ad30b4ff 344 try_to_debug ();
ad30b4ff 345#endif
ebd645e7 346 return -1; /* Oops. No more memory. */
ad30b4ff 347 }
1fd5e000 348
2a1a9785
CF
349 __cygwin_environ[offset + 1] = NULL; /* NULL terminate. */
350 update_envptrs (); /* Update any local copies of 'environ'. */
351 }
1fd5e000 352
2a1a9785
CF
353 char *envhere;
354 if (!issetenv)
9bc846bd
CF
355 /* Not setenv. Just overwrite existing. */
356 envhere = cur_environ ()[offset] = (char *) (ENVMALLOC ? strdup (name) : name);
2a1a9785
CF
357 else
358 { /* setenv */
359 /* Look for an '=' in the name and ignore anything after that if found. */
360 for (p = (char *) name; *p && *p != '='; p++)
361 continue;
362
363 int namelen = p - name; /* Length of name. */
364 /* Allocate enough space for name + '=' + value + '\0' */
4c8d72de 365 envhere = cur_environ ()[offset] = (char *) malloc (namelen + valuelen + 2);
2a1a9785
CF
366 if (!envhere)
367 return -1; /* Oops. No more memory. */
368
369 /* Put name '=' value into current slot. */
370 strncpy (envhere, name, namelen);
371 envhere[namelen] = '=';
372 strcpy (envhere + namelen + 1, value);
373 }
1fd5e000 374
2a1a9785 375 /* Update cygwin's cache, if appropriate */
1fd5e000 376 win_env *spenv;
2a1a9785 377 if ((spenv = getwinenv (envhere)))
1fd5e000
CF
378 spenv->add_cache (value);
379
ebd645e7 380 MALLOC_CHECK;
1fd5e000
CF
381 return 0;
382}
383
16dc3c95 384/* Set an environment variable */
2a1a9785 385extern "C" int
69037299 386putenv (char *str)
2a1a9785 387{
893ac8e0
CF
388 myfault efault;
389 if (efault.faulted (EFAULT))
390 return -1;
391 if (*str)
0d4c5950 392 {
893ac8e0
CF
393 char *eq = strchr (str, '=');
394 if (eq)
395 return _addenv (str, eq + 1, -1);
2a1a9785 396
893ac8e0
CF
397 /* Remove str from the environment. */
398 unsetenv (str);
399 }
2a1a9785
CF
400 return 0;
401}
402
16dc3c95 403/* Set the value of the environment variable "name" to be
ee1d77e4 404 "value". If overwrite is set, replace any current value. */
2a1a9785
CF
405extern "C" int
406setenv (const char *name, const char *value, int overwrite)
407{
893ac8e0
CF
408 myfault efault;
409 if (efault.faulted (EFAULT))
410 return -1;
411 if (!*name)
412 return 0;
2a1a9785
CF
413 if (*value == '=')
414 value++;
415 return _addenv (name, value, !!overwrite);
416}
417
16dc3c95 418/* Delete environment variable "name". */
e5a0cf24 419extern "C" int
1fd5e000
CF
420unsetenv (const char *name)
421{
5bc584ba 422 register char **e;
1fd5e000 423 int offset;
e5a0cf24
CF
424 myfault efault;
425 if (efault.faulted () || *name == '\0' || strchr (name, '='))
426 {
427 set_errno (EINVAL);
428 return -1;
429 }
1fd5e000
CF
430
431 while (my_findenv (name, &offset)) /* if set multiple times */
5bc584ba 432 /* Move up the rest of the array */
4c8d72de 433 for (e = cur_environ () + offset; ; e++)
5bc584ba 434 if (!(*e = *(e + 1)))
1fd5e000 435 break;
e5a0cf24
CF
436
437 return 0;
1fd5e000
CF
438}
439
440/* Turn environment variable part of a=b string into uppercase. */
9cec3d45 441static __inline__ void
1fd5e000
CF
442ucenv (char *p, char *eq)
443{
444 /* Amazingly, NT has a case sensitive environment name list,
445 but only sometimes.
446 It's normal to have NT set your "Path" to something.
447 Later, you set "PATH" to something else. This alters "Path".
448 But if you try and do a naive getenv on "PATH" you'll get nothing.
449
450 So we upper case the labels here to prevent confusion later but
451 we only do it for the first process in a session group. */
452 for (; p < eq; p++)
453 if (islower (*p))
2556e737 454 *p = cyg_toupper (*p);
1fd5e000
CF
455}
456
457/* Parse CYGWIN options */
458
3872e9a4 459static NO_COPY bool export_settings = false;
1fd5e000
CF
460
461enum settings
462 {
463 justset,
464 isfunc,
465 setbit,
466 set_process_state,
467 };
468
6ccb6bcf 469/* When BUF is:
ee1d77e4
CF
470 null or empty: disables globbing
471 "ignorecase": enables case-insensitive globbing
472 anything else: enables case-sensitive globbing */
6ccb6bcf
CF
473static void
474glob_init (const char *buf)
475{
476 if (!buf || !*buf)
477 {
3872e9a4
CF
478 allow_glob = false;
479 ignore_case_with_glob = false;
6ccb6bcf 480 }
c69d873f 481 else if (ascii_strncasematch (buf, "ignorecase", 10))
6ccb6bcf 482 {
3872e9a4
CF
483 allow_glob = true;
484 ignore_case_with_glob = true;
6ccb6bcf
CF
485 }
486 else
487 {
3872e9a4
CF
488 allow_glob = true;
489 ignore_case_with_glob = false;
6ccb6bcf
CF
490 }
491}
492
70c370d6
CV
493static void
494check_case_init (const char *buf)
495{
496 if (!buf || !*buf)
497 return;
498
c69d873f 499 if (ascii_strncasematch (buf, "relax", 5))
70c370d6
CV
500 {
501 pcheck_case = PCHECK_RELAXED;
502 debug_printf ("File case checking set to RELAXED");
503 }
c69d873f 504 else if (ascii_strcasematch (buf, "adjust"))
70c370d6
CV
505 {
506 pcheck_case = PCHECK_ADJUST;
507 debug_printf ("File case checking set to ADJUST");
508 }
c69d873f 509 else if (ascii_strcasematch (buf, "strict"))
70c370d6
CV
510 {
511 pcheck_case = PCHECK_STRICT;
512 debug_printf ("File case checking set to STRICT");
513 }
514 else
515 {
516 debug_printf ("Wrong case checking name: %s", buf);
517 }
518}
519
4c15b7ab
ED
520void
521set_file_api_mode (codepage_type cp)
522{
523 if (cp == oem_cp)
524 {
525 SetFileApisToOEM ();
526 debug_printf ("File APIs set to OEM");
527 }
1597484c 528 else
4c15b7ab
ED
529 {
530 SetFileApisToANSI ();
531 debug_printf ("File APIs set to ANSI");
532 }
533}
534
a7197550 535void
077ec4cb
CF
536codepage_init (const char *buf)
537{
a7197550
CV
538 if (!buf)
539 buf = "ansi";
077ec4cb 540
c69d873f 541 if (ascii_strcasematch (buf, "oem"))
a7197550
CV
542 {
543 current_codepage = oem_cp;
544 active_codepage = GetOEMCP ();
545 }
c69d873f 546 else if (ascii_strcasematch (buf, "utf8"))
a7197550
CV
547 {
548 current_codepage = utf8_cp;
549 active_codepage = CP_UTF8;
550 }
077ec4cb 551 else
a7197550
CV
552 {
553 if (!ascii_strcasematch (buf, "ansi"))
554 debug_printf ("Wrong codepage name: %s", buf);
555 /* Fallback to ANSI */
556 current_codepage = ansi_cp;
557 active_codepage = GetACP ();
558 }
1597484c 559 set_file_api_mode (current_codepage);
077ec4cb
CF
560}
561
ba946828
CV
562static void
563set_chunksize (const char *buf)
564{
84d38174
CF
565 wincap.set_chunksize (strtoul (buf, NULL, 0));
566}
567
568static void
a9396868 569set_proc_retry (const char *buf)
84d38174 570{
a9396868 571 child_info::retry_count = strtoul (buf, NULL, 0);
ba946828
CV
572}
573
12618f5f
CV
574static void
575set_ntsec (const char *buf)
576{
c69d873f 577 allow_ntsec = (buf && ascii_strcasematch (buf, "yes"));
12618f5f
CV
578}
579
580static void
581set_smbntsec (const char *buf)
582{
c69d873f 583 allow_smbntsec = (buf && ascii_strcasematch (buf, "yes"));
12618f5f
CV
584}
585
1fd5e000 586/* The structure below is used to set up an array which is used to
ee1d77e4
CF
587 parse the CYGWIN environment variable or, if enabled, options from
588 the registry. */
57c89867 589static struct parse_thing
1fd5e000
CF
590 {
591 const char *name;
592 union parse_setting
593 {
3872e9a4 594 bool *b;
1fd5e000
CF
595 DWORD *x;
596 int *i;
597 void (*func)(const char *);
598 } setting;
599
600 enum settings disposition;
601 char *remember;
602 union parse_values
603 {
604 DWORD i;
605 const char *s;
606 } values[2];
57c89867 607 } known[] NO_COPY =
1fd5e000 608{
5a41f96d 609 {"binmode", {x: &binmode}, justset, NULL, {{O_TEXT}, {O_BINARY}}},
70c370d6 610 {"check_case", {func: &check_case_init}, isfunc, NULL, {{0}, {0}}},
ee1d77e4 611 {"codepage", {func: &codepage_init}, isfunc, NULL, {{0}, {0}}},
01bbb24d 612 {"dosfilewarning", {&dos_file_warning}, justset, NULL, {{false}, {true}}},
3872e9a4 613 {"envcache", {&envcache}, justset, NULL, {{true}, {false}}},
1fd5e000 614 {"error_start", {func: &error_start_init}, isfunc, NULL, {{0}, {0}}},
3872e9a4 615 {"export", {&export_settings}, justset, NULL, {{false}, {true}}},
ba946828 616 {"forkchunk", {func: set_chunksize}, isfunc, NULL, {{0}, {0}}},
6ccb6bcf 617 {"glob", {func: &glob_init}, isfunc, NULL, {{0}, {s: "normal"}}},
12618f5f 618 {"ntsec", {func: set_ntsec}, isfunc, NULL, {{0}, {s: "yes"}}},
01bbb24d 619 {"proc_retry", {func: set_proc_retry}, isfunc, NULL, {{0}, {5}}},
3872e9a4 620 {"reset_com", {&reset_com}, justset, NULL, {{false}, {true}}},
740760ec
CV
621#ifdef USE_SERVER
622 {"server", {&allow_server}, justset, NULL, {{false}, {true}}},
623#endif
624 {"smbntsec", {func: set_smbntsec}, isfunc, NULL, {{0}, {s: "yes"}}},
3872e9a4 625 {"strip_title", {&strip_title_path}, justset, NULL, {{false}, {true}}},
3872e9a4 626 {"title", {&display_title}, justset, NULL, {{false}, {true}}},
1fd5e000 627 {"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
3872e9a4 628 {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{false}, {true}}},
fbae2bf8 629 {"transparent_exe", {&transparent_exe}, justset, NULL, {{false}, {true}}},
1fd5e000
CF
630 {NULL, {0}, justset, 0, {{0}, {0}}}
631};
632
633/* Parse a string of the form "something=stuff somethingelse=more-stuff",
ee1d77e4 634 silently ignoring unknown "somethings". */
1fd5e000
CF
635static void __stdcall
636parse_options (char *buf)
637{
638 int istrue;
e212576d 639 char *p, *lasts;
1fd5e000
CF
640 parse_thing *k;
641
642 if (buf == NULL)
643 {
becf251f
CV
644 tmp_pathbuf tp;
645 char *newbuf = tp.c_get ();
8a2ce995 646 newbuf[0] = '\0';
1fd5e000
CF
647 for (k = known; k->name != NULL; k++)
648 if (k->remember)
649 {
650 strcat (strcat (newbuf, " "), k->remember);
651 free (k->remember);
652 k->remember = NULL;
653 }
8a2ce995
CF
654
655 if (export_settings)
656 {
657 debug_printf ("%s", newbuf + 1);
658 setenv ("CYGWIN", newbuf + 1, 1);
659 }
1fd5e000
CF
660 return;
661 }
662
663 buf = strcpy ((char *) alloca (strlen (buf) + 1), buf);
e212576d
CV
664 for (p = strtok_r (buf, " \t", &lasts);
665 p != NULL;
666 p = strtok_r (NULL, " \t", &lasts))
1fd5e000 667 {
25859d7c 668 char *keyword_here = p;
c69d873f 669 if (!(istrue = !ascii_strncasematch (p, "no", 2)))
1fd5e000
CF
670 p += 2;
671 else if (!(istrue = *p != '-'))
672 p++;
673
674 char ch, *eq;
675 if ((eq = strchr (p, '=')) != NULL || (eq = strchr (p, ':')) != NULL)
676 ch = *eq, *eq++ = '\0';
677 else
678 ch = 0;
679
680 for (parse_thing *k = known; k->name != NULL; k++)
c69d873f 681 if (ascii_strcasematch (p, k->name))
1fd5e000
CF
682 {
683 switch (k->disposition)
684 {
685 case isfunc:
686 k->setting.func ((!eq || !istrue) ?
687 k->values[istrue].s : eq);
688 debug_printf ("%s (called func)", k->name);
689 break;
690 case justset:
691 if (!istrue || !eq)
692 *k->setting.x = k->values[istrue].i;
693 else
694 *k->setting.x = strtol (eq, NULL, 0);
695 debug_printf ("%s %d", k->name, *k->setting.x);
696 break;
697 case set_process_state:
698 k->setting.x = &myself->process_state;
699 /* fall through */
700 case setbit:
701 *k->setting.x &= ~k->values[istrue].i;
702 if (istrue || (eq && strtol (eq, NULL, 0)))
703 *k->setting.x |= k->values[istrue].i;
704 debug_printf ("%s %x", k->name, *k->setting.x);
705 break;
706 }
707
708 if (eq)
709 *--eq = ch;
710
711 int n = eq - p;
25859d7c 712 p = strdup (keyword_here);
1fd5e000
CF
713 if (n > 0)
714 p[n] = ':';
715 k->remember = p;
716 break;
717 }
718 }
719 debug_printf ("returning");
1fd5e000
CF
720}
721
722/* Set options from the registry. */
8a2ce995 723static bool __stdcall
becf251f 724regopt (const char *name, char *buf)
1fd5e000 725{
8a2ce995 726 bool parsed_something = false;
f0227ea3 727 char lname[strlen (name) + 1];
1fd5e000 728 strlwr (strcpy (lname, name));
8a2ce995 729
8151e674 730 for (int i = 0; i < 2; i++)
8a2ce995 731 {
8151e674
PH
732 reg_key r (i, KEY_READ, CYGWIN_INFO_PROGRAM_OPTIONS_NAME, NULL);
733
becf251f 734 if (r.get_string (lname, buf, NT_MAX_PATH, "") == ERROR_SUCCESS)
8a2ce995
CF
735 {
736 parse_options (buf);
737 parsed_something = true;
8151e674 738 break;
8a2ce995 739 }
9e1ab0ca 740 }
8151e674 741
1fd5e000 742 MALLOC_CHECK;
8a2ce995 743 return parsed_something;
1fd5e000
CF
744}
745
746/* Initialize the environ array. Look for the CYGWIN environment
ee1d77e4 747 environment variable and set appropriate options from it. */
1fd5e000 748void
166b2571 749environ_init (char **envp, int envc)
1fd5e000 750{
5ab0b5cf 751 PWCHAR rawenv, w;
166b2571 752 int i;
2a1a9785 753 char *p;
b0e82b74 754 char *newp;
1fd5e000 755 int sawTERM = 0;
fb5956da 756 bool envp_passed_in;
8a2ce995 757 bool got_something_from_registry;
57c89867 758 static char NO_COPY cygterm[] = "TERM=cygwin";
541ea313 759 myfault efault;
752b16ce 760 tmp_pathbuf tp;
541ea313
CF
761
762 if (efault.faulted ())
763 api_fatal ("internal error reading the windows environment - too many environment variables?");
1fd5e000 764
e5aa298d
CF
765 if (!conv_start_chars[0])
766 for (int i = 0; conv_envvars[i].name != NULL; i++)
767 {
768 conv_start_chars[(int) cyg_tolower (conv_envvars[i].name[0])] = 1;
769 conv_start_chars[(int) cyg_toupper (conv_envvars[i].name[0])] = 1;
770 }
6e8f36bc 771
becf251f
CV
772 char *tmpbuf = tp.t_get ();
773 got_something_from_registry = regopt ("default", tmpbuf);
1fd5e000 774 if (myself->progname[0])
becf251f
CV
775 got_something_from_registry = regopt (myself->progname, tmpbuf)
776 || got_something_from_registry;
1fd5e000 777
fb5956da
CF
778 if (!envp)
779 envp_passed_in = 0;
780 else
b0e82b74 781 {
da086d02
CF
782 envc++;
783 envc *= sizeof (char *);
166b2571
CF
784 char **newenv = (char **) malloc (envc);
785 memcpy (newenv, envp, envc);
b0e82b74 786 cfree (envp);
9bc846bd
CF
787
788 /* Older applications relied on the fact that cygwin malloced elements of the
789 environment list. */
d8242040 790 envp = newenv;
9bc846bd
CF
791 if (ENVMALLOC)
792 for (char **e = newenv; *e; e++)
793 {
794 char *p = *e;
795 *e = strdup (p);
796 cfree (p);
797 }
fb5956da 798 envp_passed_in = 1;
b0e82b74
CF
799 goto out;
800 }
801
802 /* Allocate space for environment + trailing NULL + CYGWIN env. */
166b2571 803 lastenviron = envp = (char **) malloc ((4 + (envc = 100)) * sizeof (char *));
4dc2cfe5 804
5ab0b5cf
CV
805 /* We need the CYGWIN variable content before we can loop through
806 the whole environment, so that the wide-char to multibyte conversion
807 can be done according to the "codepage" setting. */
808 if ((i = GetEnvironmentVariableA ("CYGWIN", NULL, 0)))
809 {
810 char *buf = (char *) alloca (i);
811 GetEnvironmentVariableA ("CYGWIN", buf, i);
812 parse_options (buf);
813 }
814
815 rawenv = GetEnvironmentStringsW ();
4dc2cfe5
CF
816 if (!rawenv)
817 {
3a83d3a8
CF
818 system_printf ("GetEnvironmentStrings returned NULL, %E");
819 return;
4dc2cfe5 820 }
5ab0b5cf 821 debug_printf ("GetEnvironmentStrings returned %p", rawenv);
b0e82b74 822
1fd5e000
CF
823 /* Current directory information is recorded as variables of the
824 form "=X:=X:\foo\bar; these must be changed into something legal
825 (we could just ignore them but maybe an application will
826 eventually want to use them). */
5ab0b5cf 827 for (i = 0, w = rawenv; *w != L'\0'; w = wcschr (w, L'\0') + 1, i++)
1fd5e000 828 {
5ab0b5cf 829 sys_wcstombs_alloc (&newp, HEAP_NOTHEAP, w);
166b2571
CF
830 if (i >= envc)
831 envp = (char **) realloc (envp, (4 + (envc += 100)) * sizeof (char *));
0d4c5950
CV
832 envp[i] = newp;
833 if (*newp == '=')
834 *newp = '!';
2858de3a 835 char *eq = strechr (newp, '=');
7c02f861 836 if (!child_proc_info)
0d4c5950 837 ucenv (newp, eq);
6e8f36bc 838 if (*newp == 'T' && strncmp (newp, "TERM=", 5) == 0)
1fd5e000 839 sawTERM = 1;
f0227ea3
CF
840 if (*newp == 'C' && strncmp (newp, "CYGWIN=", sizeof ("CYGWIN=") - 1) == 0)
841 parse_options (newp + sizeof ("CYGWIN=") - 1);
6e8f36bc 842 if (*eq && conv_start_chars[(unsigned char)envp[i][0]])
752b16ce 843 posify (envp + i, *++eq ? eq : --eq, tmpbuf);
64ef9db7 844 debug_printf ("%p: %s", envp[i], envp[i]);
1fd5e000
CF
845 }
846
847 if (!sawTERM)
e9efc270 848 envp[i++] = strdup (cygterm);
1fd5e000 849 envp[i] = NULL;
5ab0b5cf 850 FreeEnvironmentStringsW (rawenv);
b0e82b74
CF
851
852out:
33b0abd1 853 findenv_func = (char * (*)(const char*, int*)) my_findenv;
0763ee9d 854 __cygwin_environ = envp;
81010d21 855 update_envptrs ();
fb5956da
CF
856 if (envp_passed_in)
857 {
858 p = getenv ("CYGWIN");
859 if (p)
860 parse_options (p);
861 }
8a2ce995
CF
862
863 if (got_something_from_registry)
864 parse_options (NULL); /* possibly export registry settings to
865 environment */
1fd5e000
CF
866 MALLOC_CHECK;
867}
868
ee1d77e4 869/* Function called by qsort to sort environment strings. */
1fd5e000
CF
870static int
871env_sort (const void *a, const void *b)
872{
873 const char **p = (const char **) a;
874 const char **q = (const char **) b;
875
876 return strcmp (*p, *q);
877}
878
094d5193
CF
879char * __stdcall
880getwinenveq (const char *name, size_t namelen, int x)
881{
5ab0b5cf
CV
882 WCHAR name0[namelen - 1];
883 WCHAR valbuf[32768]; /* Max size of an env.var including trailing '\0'. */
884
885 name0[sys_mbstowcs (name0, sizeof name0, name, namelen - 1)] = L'\0';
886 int totlen = GetEnvironmentVariableW (name0, valbuf, 32768);
094d5193
CF
887 if (totlen > 0)
888 {
5ab0b5cf 889 totlen = sys_wcstombs (NULL, 0, valbuf);
094d5193
CF
890 if (x == HEAP_1_STR)
891 totlen += namelen;
892 else
893 namelen = 0;
ee4388c4 894 char *p = (char *) cmalloc_abort ((cygheap_types) x, totlen);
094d5193
CF
895 if (namelen)
896 strcpy (p, name);
5ab0b5cf
CV
897 sys_wcstombs (p + namelen, totlen, valbuf);
898 debug_printf ("using value from GetEnvironmentVariable for '%W'", name0);
899 return p;
094d5193
CF
900 }
901
902 debug_printf ("warning: %s not present in environment", name);
903 return NULL;
904}
905
da086d02
CF
906struct spenv
907{
908 const char *name;
a05a9e01 909 size_t namelen;
1bbf1ac6 910 bool force_into_environment; /* If true, always add to env if missing */
f0b14f14 911 bool add_if_exists; /* if true, retrieve value from cache */
094d5193 912 const char * (cygheap_user::*from_cygheap) (const char *, size_t);
60cb120f 913
a05a9e01 914 char *retrieve (bool, const char * const = NULL)
6ea3e429 915 __attribute__ ((regparm (3)));
da086d02
CF
916};
917
179cae11 918#define env_dontadd almost_null
e40670ee 919
723190cf 920/* Keep this list in upper case and sorted */
da086d02
CF
921static NO_COPY spenv spenvs[] =
922{
1bbf1ac6 923#ifdef DEBUGGING
72733445 924 {NL ("CYGWIN_DEBUG="), false, true, NULL},
1bbf1ac6 925#endif
47dc3dec
CF
926 {NL ("HOMEDRIVE="), false, false, &cygheap_user::env_homedrive},
927 {NL ("HOMEPATH="), false, false, &cygheap_user::env_homepath},
928 {NL ("LOGONSERVER="), false, false, &cygheap_user::env_logsrv},
929 {NL ("PATH="), false, true, NULL},
1f99dd3e 930 {NL ("SYSTEMDRIVE="), false, true, NULL},
4e6c0729 931 {NL ("SYSTEMROOT="), true, true, &cygheap_user::env_systemroot},
47dc3dec
CF
932 {NL ("USERDOMAIN="), false, false, &cygheap_user::env_domain},
933 {NL ("USERNAME="), false, false, &cygheap_user::env_name},
9fc0d144 934 {NL ("USERPROFILE="), false, false, &cygheap_user::env_userprofile},
3e45d281 935 {NL ("WINDIR="), true, true, &cygheap_user::env_systemroot}
da086d02
CF
936};
937
938char *
47dc3dec 939spenv::retrieve (bool no_envblock, const char *const env)
da086d02 940{
c69d873f 941 if (env && !ascii_strncasematch (env, name, namelen))
da086d02 942 return NULL;
03a2ce9a
CF
943
944 debug_printf ("no_envblock %d", no_envblock);
945
da086d02
CF
946 if (from_cygheap)
947 {
948 const char *p;
47dc3dec 949 if (env && !cygheap->user.issetuid ())
e40670ee 950 {
094d5193 951 debug_printf ("duping existing value for '%s'", name);
47dc3dec 952 /* Don't really care what it's set to if we're calling a cygwin program */
6829b6e9 953 return cstrdup1 (env);
e40670ee 954 }
da086d02 955
e40670ee 956 /* Calculate (potentially) value for given environment variable. */
094d5193 957 p = (cygheap->user.*from_cygheap) (name, namelen);
6829b6e9 958 if (!p || (no_envblock && !env) || (p == env_dontadd))
7c02f861 959 return env_dontadd;
ee4388c4 960 char *s = (char *) cmalloc_abort (HEAP_1_STR, namelen + strlen (p) + 1);
da086d02 961 strcpy (s, name);
0c55f6ed 962 strcpy (s + namelen, p);
03a2ce9a 963 debug_printf ("using computed value for '%s'", name);
da086d02
CF
964 return s;
965 }
966
47dc3dec
CF
967 if (env)
968 return cstrdup1 (env);
da086d02 969
094d5193 970 return getwinenveq (name, namelen, HEAP_1_STR);
da086d02 971}
723190cf 972
da086d02 973#define SPENVS_SIZE (sizeof (spenvs) / sizeof (spenvs[0]))
723190cf 974
1fd5e000 975/* Create a Windows-style environment block, i.e. a typical character buffer
ee1d77e4
CF
976 filled with null terminated strings, terminated by double null characters.
977 Converts environment variables noted in conv_envvars into win32 form
978 prior to placing them in the string. */
da086d02 979char ** __stdcall
752b16ce 980build_env (const char * const *envp, PWCHAR &envblock, int &envc,
da086d02 981 bool no_envblock)
1fd5e000 982{
12a2ef44 983 int len, n;
1fd5e000 984 const char * const *srcp;
da086d02
CF
985 char **dstp;
986 bool saw_spenv[SPENVS_SIZE] = {0};
723190cf 987
da086d02 988 debug_printf ("envp %p", envp);
723190cf 989
12a2ef44 990 /* How many elements? */
1fd5e000
CF
991 for (n = 0; envp[n]; n++)
992 continue;
993
12a2ef44 994 /* Allocate a new "argv-style" environ list with room for extra stuff. */
ee4388c4 995 char **newenv = (char **) cmalloc_abort (HEAP_1_ARGV, sizeof (char *) *
6829b6e9 996 (n + SPENVS_SIZE + 1));
1fd5e000 997
12a2ef44 998 int tl = 0;
6829b6e9
CF
999 char **pass_dstp;
1000 char **pass_env = (char **) alloca (sizeof (char *) * (n + SPENVS_SIZE + 1));
12a2ef44
CF
1001 /* Iterate over input list, generating a new environment list and refreshing
1002 "special" entries, if necessary. */
6829b6e9 1003 for (srcp = envp, dstp = newenv, pass_dstp = pass_env; *srcp; srcp++)
1fd5e000 1004 {
6829b6e9 1005 bool calc_tl = !no_envblock;
12a2ef44 1006 /* Look for entries that require special attention */
da086d02 1007 for (unsigned i = 0; i < SPENVS_SIZE; i++)
a05a9e01 1008 if (!saw_spenv[i] && (*dstp = spenvs[i].retrieve (no_envblock, *srcp)))
da086d02
CF
1009 {
1010 saw_spenv[i] = 1;
6829b6e9
CF
1011 if (*dstp == env_dontadd)
1012 goto next1;
f0b14f14 1013 if (spenvs[i].add_if_exists)
6829b6e9
CF
1014 calc_tl = true;
1015 goto next0;
da086d02 1016 }
1fd5e000 1017
a05a9e01 1018 /* Add entry to new environment */
12a2ef44 1019 *dstp = cstrdup1 (*srcp);
723190cf 1020
e40670ee 1021 next0:
6829b6e9
CF
1022 if (calc_tl)
1023 {
1024 *pass_dstp++ = *dstp;
1025 tl += strlen (*dstp) + 1;
1026 }
e40670ee
CF
1027 dstp++;
1028 next1:
1029 continue;
1fd5e000
CF
1030 }
1031
8a2ce995 1032 assert ((srcp - envp) == n);
12a2ef44 1033 /* Fill in any required-but-missing environment variables. */
60cb120f 1034 for (unsigned i = 0; i < SPENVS_SIZE; i++)
1bbf1ac6 1035 if (!saw_spenv[i] && (spenvs[i].force_into_environment || cygheap->user.issetuid ()))
e3778517 1036 {
f0b14f14
CF
1037 *dstp = spenvs[i].retrieve (false);
1038 if (*dstp && *dstp != env_dontadd)
94f29ccd 1039 {
dd991a75 1040 *pass_dstp++ = *dstp;
94f29ccd
PH
1041 tl += strlen (*dstp) + 1;
1042 dstp++;
1043 }
1044 }
e3778517 1045
a05a9e01 1046 envc = dstp - newenv; /* Number of entries in newenv */
8a2ce995 1047 assert ((size_t) envc <= (n + SPENVS_SIZE));
da086d02 1048 *dstp = NULL; /* Terminate */
1fd5e000 1049
6829b6e9
CF
1050 size_t pass_envc = pass_dstp - pass_env;
1051 if (!pass_envc)
da086d02
CF
1052 envblock = NULL;
1053 else
1054 {
6829b6e9
CF
1055 *pass_dstp = NULL;
1056 debug_printf ("env count %d, bytes %d", pass_envc, tl);
47dc3dec
CF
1057 win_env temp;
1058 temp.reset ();
1fd5e000 1059
da086d02 1060 /* Windows programs expect the environment block to be sorted. */
6829b6e9 1061 qsort (pass_env, pass_envc, sizeof (char *), env_sort);
1fd5e000 1062
da086d02 1063 /* Create an environment block suitable for passing to CreateProcess. */
752b16ce
CV
1064 PWCHAR s;
1065 envblock = (PWCHAR) malloc ((2 + tl) * sizeof (WCHAR));
12a2ef44 1066 int new_tl = 0;
6829b6e9 1067 for (srcp = pass_env, s = envblock; *srcp; srcp++)
da086d02 1068 {
12a2ef44
CF
1069 const char *p;
1070 win_env *conv;
1071 len = strcspn (*srcp, "=") + 1;
d6b1ac7f 1072 const char *rest = *srcp + len;
12a2ef44 1073
d1ce9364
CV
1074 /* Check for a bad entry. This is necessary to get rid of empty
1075 strings, induced by putenv and changing the string afterwards.
1076 Note that this doesn't stop invalid strings without '=' in it
1077 etc., but we're opting for speed here for now. Adding complete
1078 checking would be pretty expensive. */
d6b1ac7f 1079 if (len == 1 || !*rest)
d1ce9364
CV
1080 continue;
1081
12a2ef44 1082 /* See if this entry requires posix->win32 conversion. */
d6b1ac7f 1083 conv = getwinenv (*srcp, rest, &temp);
12a2ef44
CF
1084 if (conv)
1085 p = conv->native; /* Use win32 path */
1086 else
1087 p = *srcp; /* Don't worry about it */
1088
d6b1ac7f 1089 len = strlen (p) + 1;
d6b1ac7f 1090 new_tl += len; /* Keep running total of block length so far */
12a2ef44
CF
1091
1092 /* See if we need to increase the size of the block. */
1093 if (new_tl > tl)
470e8c46 1094 {
638180f5 1095 tl = new_tl + 100;
752b16ce
CV
1096 PWCHAR new_envblock =
1097 (PWCHAR) realloc (envblock, (2 + tl) * sizeof (WCHAR));
470e8c46
CV
1098 /* If realloc moves the block, move `s' with it. */
1099 if (new_envblock != envblock)
5bf785a0 1100 {
470e8c46
CV
1101 s += new_envblock - envblock;
1102 envblock = new_envblock;
1103 }
1104 }
12a2ef44 1105
752b16ce 1106 int slen = sys_mbstowcs (s, len, p, len);
12a2ef44
CF
1107
1108 /* See if environment variable is "special" in a Windows sense.
1109 Under NT, the current directories for visited drives are stored
1110 as =C:=\bar. Cygwin converts the '=' to '!' for hopefully obvious
1111 reasons. We need to convert it back when building the envblock */
752b16ce
CV
1112 if (s[0] == L'!' && (iswdrive (s + 1) || (s[1] == L':' && s[2] == L':'))
1113 && s[3] == L'=')
1114 *s = L'=';
1115 s += slen + 1;
da086d02 1116 }
752b16ce 1117 *s = L'\0'; /* Two null bytes at the end */
12a2ef44
CF
1118 assert ((s - envblock) <= tl); /* Detect if we somehow ran over end
1119 of buffer */
1fd5e000 1120 }
1fd5e000 1121
6d171b44 1122 debug_printf ("envp %p, envc %d", newenv, envc);
da086d02 1123 return newenv;
1fd5e000 1124}
0763ee9d
CF
1125
1126/* This idiocy is necessary because the early implementers of cygwin
1127 did not seem to know about importing data variables from the DLL.
1128 So, we have to synchronize cygwin's idea of the environment with the
1129 main program's with each reference to the environment. */
84c7d409 1130extern "C" char ** __stdcall
0763ee9d
CF
1131cur_environ ()
1132{
1133 if (*main_environ != __cygwin_environ)
1134 {
1135 __cygwin_environ = *main_environ;
1136 update_envptrs ();
1137 }
1138
1139 return __cygwin_environ;
1140}
This page took 0.429282 seconds and 5 git commands to generate.