Last active
January 25, 2020 18:51
-
-
Save unxmaal/bc996e78e9f422d6e277e0b4a0003cf5 to your computer and use it in GitHub Desktop.
Racket
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "rktio.h" | |
#include "rktio_private.h" | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <errno.h> | |
struct rktio_envvars_t { | |
intptr_t count, size; | |
char **names; | |
char **vals; | |
}; | |
int | |
unsetenv(const char *name) | |
{ | |
extern char **environ; | |
char **ep, **sp; | |
size_t len; | |
if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL) { | |
errno = EINVAL; | |
return -1; | |
} | |
len = strlen(name); | |
for (ep = environ; *ep != NULL; ) | |
if (strncmp(*ep, name, len) == 0 && (*ep)[len] == '=') { | |
/* Remove found entry by shifting all successive entries | |
back one element */ | |
for (sp = ep; *sp != NULL; sp++) | |
*sp = *(sp + 1); | |
/* Continue around the loop to further instances of 'name' */ | |
} else { | |
ep++; | |
} | |
return 0; | |
} | |
int | |
setenv(const char *name, const char *value, int overwrite) | |
{ | |
char *es; | |
if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL || | |
value == NULL) { | |
errno = EINVAL; | |
return -1; | |
} | |
if (getenv(name) != NULL && overwrite == 0) | |
return 0; | |
unsetenv(name); /* Remove all occurrences */ | |
es = malloc(strlen(name) + strlen(value) + 2); | |
/* +2 for '=' and null terminator */ | |
if (es == NULL) | |
return -1; | |
strcpy(es, name); | |
strcat(es, "="); | |
strcat(es, value); | |
return (putenv(es) != 0) ? -1 : 0; | |
} | |
#ifdef OS_X | |
# define SETENV_DROPS_LEADING_EQUAL_SIGN | |
#endif | |
#if defined(OS_X) && !TARGET_OS_IPHONE | |
# include <crt_externs.h> | |
# define GET_ENVIRON_ARRAY *_NSGetEnviron() | |
#endif | |
#if defined(RKTIO_SYSTEM_UNIX) && !defined(GET_ENVIRON_ARRAY) | |
extern char **environ; | |
# define GET_ENVIRON_ARRAY environ | |
#endif | |
#ifdef RKTIO_SYSTEM_UNIX | |
char **rktio_get_environ_array(void) | |
{ | |
return GET_ENVIRON_ARRAY; | |
} | |
#endif | |
int rktio_is_ok_envvar_name(rktio_t *rktio, const char *s) | |
{ | |
intptr_t i = strlen(s); | |
#ifdef RKTIO_SYSTEM_WINDOWS | |
if (!s[0]) return 0; | |
#endif | |
while (i--) { | |
if (s[i] == '=') | |
return 0; | |
} | |
return 1; | |
} | |
int rktio_are_envvar_names_case_insensitive(rktio_t *rktio) | |
{ | |
#ifdef RKTIO_SYSTEM_WINDOWS | |
return 1; | |
#else | |
return 0; | |
#endif | |
} | |
char *rktio_getenv(rktio_t *rktio, const char *name) | |
{ | |
#ifdef RKTIO_SYSTEM_UNIX | |
char *s; | |
s = getenv(name); | |
if (s) | |
return MSC_IZE(strdup)(s); | |
else { | |
set_racket_error(RKTIO_ERROR_NO_SUCH_ENVVAR); | |
return NULL; | |
} | |
#endif | |
#ifdef RKTIO_SYSTEM_WINDOWS | |
intptr_t value_size; | |
wchar_t *wp; | |
wp = WIDE_PATH_temp(name); | |
if (!wp) return NULL; | |
value_size = GetEnvironmentVariableW(wp, NULL, 0); | |
if (value_size) { | |
wchar_t *value_w; | |
char *value; | |
intptr_t got; | |
value_w = malloc(sizeof(wchar_t) * value_size); | |
got = GetEnvironmentVariableW(WIDE_PATH_temp(name), value_w, value_size); | |
if (got < value_size) | |
value_w[got] = 0; | |
value = NARROW_PATH_copy(value_w); | |
free(value_w); | |
return value; | |
} | |
set_racket_error(RKTIO_ERROR_NO_SUCH_ENVVAR); | |
return NULL; | |
#endif | |
} | |
int rktio_setenv(rktio_t *rktio, const char *name, const char *val) | |
{ | |
#ifdef RKTIO_SYSTEM_UNIX | |
if (val) { | |
int r; | |
#ifdef SETENV_DROPS_LEADING_EQUAL_SIGN | |
char *tmp = NULL; | |
if (rktio->macos_kernel_version < 16) { | |
if (val[0] == '=') { | |
intptr_t len = strlen(val); | |
tmp = malloc(len + 2); | |
memcpy(tmp + 1, val, len + 1); | |
tmp[0] = '='; | |
val = tmp; | |
} | |
} | |
#endif | |
r = setenv(name, val, 1); | |
#ifdef SETENV_DROPS_LEADING_EQUAL_SIGN | |
if (tmp) | |
free(tmp); | |
#endif | |
if (r) | |
get_posix_error(); | |
return (r ? 0 : 1); | |
} else { | |
/* on some platforms, unsetenv() returns void */ | |
unsetenv(name); | |
return 1; | |
} | |
#endif | |
#ifdef RKTIO_SYSTEM_WINDOWS | |
int rc; | |
wchar_t *val_w, *name_w; | |
name_w = WIDE_PATH_temp(name); | |
if (!name_w) return 0; | |
if (val) { | |
val_w = WIDE_PATH_copy(val); | |
if (!val_w) return 0; | |
} else | |
val_w = NULL; | |
rc = SetEnvironmentVariableW(name_w, val_w); | |
if (val_w) | |
free(val_w); | |
if (rc) | |
return 1; | |
get_windows_error(); | |
return 0; | |
#endif | |
} | |
rktio_envvars_t *rktio_envvars(rktio_t *rktio) | |
{ | |
#ifdef RKTIO_SYSTEM_WINDOWS | |
{ | |
char *p; | |
wchar_t *e; | |
intptr_t i, start, j, count; | |
rktio_envvars_t *envvars; | |
e = GetEnvironmentStringsW(); | |
if (!e) { | |
get_windows_error(); | |
return NULL; | |
} | |
count = 0; | |
i = 0; | |
while (e[i]) { | |
if (e[i] != '=') | |
count++; | |
while (e[i]) i++; | |
i++; | |
} | |
envvars = malloc(sizeof(rktio_envvars_t)); | |
envvars->size = count; | |
envvars->count = count; | |
envvars->names = malloc(count * sizeof(char *)); | |
envvars->vals = malloc(count * sizeof(char *)); | |
count = 0; | |
i = 0; | |
while (e[i]) { | |
start = i; | |
while (e[i]) { i++; } | |
p = NARROW_PATH_copy(e + start); | |
for (j = 0; p[j] && p[j] != '='; j++) { | |
} | |
p[j] = 0; | |
if (p[0] != 0) { | |
envvars->names[count] = MSC_IZE(strdup)(p); | |
envvars->vals[count] = MSC_IZE(strdup)(p+j+1); | |
count++; | |
} | |
free(p); | |
i++; | |
} | |
FreeEnvironmentStringsW(e); | |
return envvars; | |
} | |
#else | |
{ | |
intptr_t i, j; | |
char **ea, *p; | |
rktio_envvars_t *envvars; | |
ea = GET_ENVIRON_ARRAY; | |
for (i = 0; ea[i]; i++) { | |
} | |
envvars = malloc(sizeof(rktio_envvars_t)); | |
envvars->size = i; | |
envvars->count = i; | |
envvars->names = malloc(i * sizeof(char *)); | |
envvars->vals = malloc(i * sizeof(char *)); | |
for (i = 0; ea[i]; i++) { | |
p = ea[i]; | |
for (j = 0; p[j] && p[j] != '='; j++) { | |
} | |
envvars->names[i] = rktio_strndup(p, j); | |
envvars->vals[i] = MSC_IZE(strdup)(p+j+1); | |
} | |
return envvars; | |
} | |
#endif | |
} | |
rktio_envvars_t *rktio_empty_envvars(rktio_t *rktio) | |
{ | |
rktio_envvars_t *envvars; | |
envvars = malloc(sizeof(rktio_envvars_t)); | |
envvars->size = 2; | |
envvars->count = 0; | |
envvars->names = malloc(envvars->size * sizeof(char *)); | |
envvars->vals = malloc(envvars->size * sizeof(char *)); | |
return envvars; | |
} | |
rktio_envvars_t *rktio_envvars_copy(rktio_t *rktio, rktio_envvars_t *envvars) | |
{ | |
rktio_envvars_t *new_envvars; | |
intptr_t i; | |
new_envvars = malloc(sizeof(rktio_envvars_t)); | |
new_envvars->size = envvars->count; | |
new_envvars->count = envvars->count; | |
new_envvars->names = malloc(envvars->count * sizeof(char *)); | |
new_envvars->vals = malloc(envvars->count * sizeof(char *)); | |
for (i = 0; i < envvars->count; i++) { | |
new_envvars->names[i] = MSC_IZE(strdup)(envvars->names[i]); | |
new_envvars->vals[i] = MSC_IZE(strdup)(envvars->vals[i]); | |
} | |
return new_envvars; | |
} | |
void rktio_envvars_free(rktio_t *rktio, rktio_envvars_t *envvars) | |
{ | |
int i; | |
for (i = 0; i < envvars->count; i++) { | |
free(envvars->names[i]); | |
free(envvars->vals[i]); | |
} | |
free(envvars->names); | |
free(envvars->vals); | |
free(envvars); | |
} | |
static void envvars_resize(rktio_envvars_t *envvars, intptr_t new_size) | |
{ | |
char **new_names; | |
char **new_vals; | |
new_names = malloc(sizeof(char *) * new_size); | |
new_vals = malloc(sizeof(char *) * new_size); | |
memcpy(new_names, envvars->names, sizeof(char*) * envvars->count); | |
memcpy(new_vals, envvars->vals, sizeof(char*) * envvars->count); | |
free(envvars->names); | |
free(envvars->vals); | |
envvars->size = new_size; | |
envvars->names = new_names; | |
envvars->vals = new_vals; | |
} | |
intptr_t rktio_envvars_count(rktio_t *rktio, rktio_envvars_t *envvars) | |
{ | |
return envvars->count; | |
} | |
char *rktio_envvars_name_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i) | |
{ | |
return MSC_IZE(strdup)(envvars->names[i]); | |
} | |
char *rktio_envvars_value_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i) | |
{ | |
return MSC_IZE(strdup)(envvars->vals[i]); | |
} | |
char *rktio_envvars_get(rktio_t *rktio, rktio_envvars_t *envvars, const char *name) | |
{ | |
intptr_t i; | |
for (i = 0; i < envvars->count; i++) { | |
if (!strcmp(envvars->names[i], name)) | |
return MSC_IZE(strdup)(envvars->vals[i]); | |
} | |
return NULL; | |
} | |
void rktio_envvars_set(rktio_t *rktio, rktio_envvars_t *envvars, const char *name, const char *value) | |
{ | |
intptr_t i, j; | |
for (i = 0; i < envvars->count; i++) { | |
if (!strcmp(envvars->names[i], name)) { | |
if (value) { | |
free(envvars->vals[i]); | |
envvars->vals[i] = MSC_IZE(strdup)(value); | |
} else { | |
free(envvars->names[i]); | |
free(envvars->vals[i]); | |
for (j = i + 1; j < envvars->count; j++) { | |
envvars->names[j-1] = envvars->names[j]; | |
envvars->vals[j-1] = envvars->vals[j]; | |
} | |
if ((envvars->size > 4) | |
&& (envvars->count <= (envvars->size >> 2))) { | |
envvars_resize(envvars, envvars->size >> 1); | |
} | |
return; | |
} | |
} | |
} | |
if (!value) | |
return; | |
if (envvars->count == envvars->size) | |
envvars_resize(envvars, envvars->size * 2); | |
envvars->names[envvars->count] = MSC_IZE(strdup)(name); | |
envvars->vals[envvars->count] = MSC_IZE(strdup)(value); | |
envvars->count++; | |
} | |
void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars) | |
{ | |
#ifdef RKTIO_SYSTEM_UNIX | |
char **r, *s; | |
intptr_t i; | |
intptr_t len = 0, slen, c; | |
for (i = 0; i < envvars->count; i++) { | |
len += strlen(envvars->names[i]); | |
len += strlen(envvars->vals[i]); | |
len += 2; | |
} | |
r = (char **)malloc((envvars->count+1) * sizeof(char*) + len); | |
s = (char *)(r + (envvars->count+1)); | |
c = 0; | |
for (i = 0; i < envvars->count; i++) { | |
r[c++] = s; | |
slen = strlen(envvars->names[i]); | |
memcpy(s, envvars->names[i], slen); | |
s[slen] = '='; | |
s = s + (slen + 1); | |
slen = strlen(envvars->vals[i]); | |
memcpy(s, envvars->vals[i], slen); | |
s[slen] = 0; | |
s = s + (slen + 1); | |
} | |
r[c] = NULL; | |
return r; | |
#endif | |
#ifdef RKTIO_SYSTEM_WINDOWS | |
intptr_t i; | |
intptr_t len = 0, slen; | |
wchar_t *r, *s; | |
for (i = 0; i < envvars->count; i++) { | |
s = WIDE_PATH_temp(envvars->names[i]); | |
if (s) { | |
len += wcslen(s); | |
s = WIDE_PATH_temp(envvars->vals[i]); | |
if (s) | |
len += wcslen(s); | |
len += 2; | |
} | |
} | |
r = (wchar_t *)malloc((len + 1) * sizeof(wchar_t)); | |
len = 0; | |
for (i = 0; i < envvars->count; i++) { | |
s = WIDE_PATH_temp(envvars->names[i]); | |
if (s) { | |
slen = wcslen(s); | |
memcpy(r + len, s, slen * sizeof(wchar_t)); | |
len += slen; | |
r[len++] = '='; | |
s = WIDE_PATH_temp(envvars->vals[i]); | |
if (!s) s = L""; | |
slen = wcslen(s); | |
memcpy(r + len, s, slen * sizeof(wchar_t)); | |
len += slen; | |
r[len++] = 0; | |
} | |
} | |
r[len] = 0; | |
return r; | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment