aboutsummaryrefslogtreecommitdiff
path: root/win32/env.c
blob: f30ee62f6d77d829f4b612192e9ef7de55819caa (plain)
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
#include "libbb.h"

#undef getenv
#undef putenv

char *mingw_getenv(const char *name)
{
	char *result = getenv(name);
	if (!result) {
		if (!strcmp(name, "TMPDIR")) {
			/* on Windows it is TMP and TEMP */
			result = getenv("TMP");
			if (!result)
				result = getenv("TEMP");
		} else if (!strcmp(name, "HOME")) {
			struct passwd *p = getpwuid(getuid());
			if (p)
				result = p->pw_dir;
		}
	}
	return result;
}

int setenv(const char *name, const char *value, int replace)
{
	int out;
	char *envstr;

	if (!name || !*name || strchr(name, '=') || !value) return -1;
	if (!replace) {
		if (getenv(name)) return 0;
	}

	envstr = xasprintf("%s=%s", name, value);
	out = mingw_putenv(envstr);
	free(envstr);

	return out;
}

/*
 * Removing an environment variable with WIN32 _putenv requires an argument
 * like "NAME="; glibc omits the '='.  The implementations of unsetenv and
 * clearenv allow for this.
 *
 * It isn't possible to create an environment variable with an empty value
 * using WIN32 _putenv.
 */
int unsetenv(const char *name)
{
	char *envstr;
	int ret;

	if (!name || !*name || strchr(name, '=') ) {
		return -1;
	}

	envstr = xasprintf("%s=", name);
	ret = _putenv(envstr);
	free(envstr);

	return ret;
}

int clearenv(void)
{
	char *envp, *name, *s;

	while ( environ && (envp=*environ) ) {
		if ( (s=strchr(envp, '=')) != NULL ) {
			name = xstrndup(envp, s-envp+1);
			if (_putenv(name) == -1) {
				free(name);
				return -1;
			}
			free(name);
		}
		else {
			return -1;
		}
	}
	return 0;
}

int mingw_putenv(const char *env)
{
	char *s, **envp;
	int ret = 0;

	if ( (s=strchr(env, '=')) == NULL ) {
		return unsetenv(env);
	}

	if (s[1] != '\0') {
		/* setting non-empty value is fine */
		return _putenv(env);
	}
	else {
		/* set empty value by setting a non-empty one then truncating */
		char *envstr = xasprintf("%s0", env);
		ret = _putenv(envstr);

		for (envp = environ; *envp; ++envp) {
			if (strcmp(*envp, envstr) == 0) {
				(*envp)[s - env + 1] = '\0';
				break;
			}
		}

		/* tell the OS environment about the change */
		envstr[s - env] = '\0';
		SetEnvironmentVariable(envstr, "");
		free(envstr);
	}

	return ret;
}