rktio: environment variables

This commit is contained in:
Matthew Flatt 2017-06-12 14:38:56 -06:00
parent a767ea38fc
commit b5e88e70c2
3 changed files with 417 additions and 12 deletions

View File

@ -723,13 +723,13 @@ int main()
rktio_status_t *status;
rktio_process_result_t *result;
char *argv[1] = { "/bin/cat" };
rktio_envvars_t *envvars = NULL;
rktio_envvars_t *envvars = rktio_envvars(rktio);
rktio_fd_t *err_fd = rktio_system_fd(rktio, 2, RKTIO_OPEN_WRITE);
int i;
result = rktio_process(rktio, "/bin/cat", 1, argv,
result = rktio_process(rktio, argv[0], 1, argv,
NULL, NULL, err_fd,
rktio_get_current_directory(rktio), envvars,
pwd, envvars,
0,
NULL);
check_valid(result);
@ -757,13 +757,11 @@ int main()
rktio_process_forget(rktio, result->process);
free(result);
check_valid(rktio_close(rktio, err_fd));
/* Run and then break or kill "/bin/cat" */
/* Run and then break or kill `cat` */
for (i = 0; i < 2; i++) {
result = rktio_process(rktio, "/bin/cat", 1, argv,
result = rktio_process(rktio, argv[0], 1, argv,
NULL, NULL, err_fd,
rktio_get_current_directory(rktio), envvars,
pwd, envvars,
0,
NULL);
check_valid(result);
@ -802,7 +800,49 @@ int main()
rktio_process_forget(rktio, result->process);
free(result);
}
{
char *argv[2] = { "/usr/bin/printenv", "RKTIO_EXAMPLE" };
check_valid(!rktio_envvars_get(rktio, envvars, "RKTIO_EXAMPLE"));
rktio_envvars_set(rktio, envvars, "RKTIO_EXAMPLE", "howdy");
s = rktio_envvars_get(rktio, envvars, "RKTIO_EXAMPLE");
check_valid(s);
check_valid(!strcmp(s, "howdy"));
free(s);
result = rktio_process(rktio, argv[0], 2, argv,
NULL, NULL, err_fd,
pwd, envvars,
0,
NULL);
check_valid(result);
/* Assume that a pipe can buffer the minimal output from `printenv`: */
pause_for_process(rktio, result->process);
wait_read(rktio, result->stdout_fd);
{
char buffer[32];
intptr_t amt;
amt = rktio_read(rktio, result->stdout_fd, buffer, sizeof(buffer));
check_valid(amt == 6);
check_valid(!strncmp(buffer, "howdy\n", 6));
}
check_valid(rktio_close(rktio, result->stdin_fd));
check_valid(rktio_close(rktio, result->stdout_fd));
rktio_process_forget(rktio, result->process);
free(result);
}
rktio_ennvars_free(rktio, envvars);
rktio_forget(rktio, err_fd);
}
free(pwd);
return 0;
}

View File

@ -145,6 +145,21 @@ int rktio_udp_change_multicast_group(rktio_t *rktio, rktio_fd_t *rfd,
typedef struct rktio_envvars_t rktio_envvars_t;
char *rktio_getenv(rktio_t *rktio, char *name);
int rktio_setenv(rktio_t *rktio, const char *name, const char *val);
rktio_envvars_t *rktio_envvars(rktio_t *rktio);
rktio_envvars_t *rktio_empty_envvars(rktio_t *rktio);
rktio_envvars_t *rktio_envvars_copy(rktio_t *rktio, rktio_envvars_t *envvars);
void rktio_ennvars_free(rktio_t *rktio, rktio_envvars_t *envvars);
char *rktio_envvars_get(rktio_t *rktio, rktio_envvars_t *envvars, char *name);
void rktio_envvars_set(rktio_t *rktio, rktio_envvars_t *envvars, char *name, char *value);
intptr_t rktio_envvars_count(rktio_t *rktio, rktio_envvars_t *envvars);
char *rktio_envvars_name_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i);
char *rktio_envvars_value_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i);
/*************************************************/
/* Processes */

View File

@ -3,10 +3,360 @@
#include <stdlib.h>
#include <string.h>
struct rktio_envvars_t {
intptr_t count, size;
char **names;
char **vals;
};
#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
char *rktio_getenv(rktio_t *rktio, char *name)
{
#ifdef RKTIO_SYSTEM_UNIX
char *s;
s = getenv(name);
if (s)
return strdup(s);
else
return NULL;
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
intptr_t value_size;
value_size = GetEnvironmentVariableW(WIDE_PATH_temp(name), 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;
}
return NULL;
#endif
}
int rktio_setenv(rktio_t *rktio, const char *name, const char *val)
{
#ifdef RKTIO_SYSTEM_UNIX
if (val) {
char *buffer;
intptr_t total_length, r, varlen, vallen;
varlen = strlen(name);
vallen = strlen(val);
total_length = varlen + vallen + 2;
buffer = malloc(total_length);
memcpy(buffer, name, varlen);
buffer[varlen] = '=';
memcpy(buffer + varlen + 1, val, vallen + 1);
r = putenv(buffer);
if (r)
get_posix_error();
free(buffer);
return (r ? 0 : 1);
} else {
/* on some platforms, unsetenv() returns void */
unsetenv(name);
return 1;
}
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
int rc;
char *val_w;
if (val)
val_w = WIDE_PATH_copy(val);
else
val_w = NULL;
rc = SetEnvironmentVariableW(WIDE_PATH_temp(var), val_w);
if (val_w)
free(val_w);
if (rc)
return 1;
set_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;
while (e[i]) {
count++;
for (i = 0; e[i]; ) {
}
i++;
}
ennvars = 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;
for (i = 0; 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;
envvars->names[count] = strdup(p);
envvars->vals[count] = strdup(p+j+1);
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] = strndup(p, j);
envvars->vals[i] = 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] = strdup(envvars->names[i]);
new_envvars->vals[i] = strdup(envvars->vals[i]);
}
return new_envvars;
}
void rktio_ennvars_free(rktio_t *rktio, rktio_envvars_t *envvars)
{
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->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 strdup(envvars->names[i]);
}
char *rktio_envvars_value_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i)
{
return strdup(envvars->vals[i]);
}
char *rktio_envvars_get(rktio_t *rktio, rktio_envvars_t *envvars, char *name)
{
intptr_t i;
for (i = 0; i < envvars->count; i++) {
if (!strcmp(envvars->names[i], name))
return strdup(envvars->vals[i]);
}
return NULL;
}
void rktio_envvars_set(rktio_t *rktio, rktio_envvars_t *envvars, char *name, 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] = 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] = name;
envvars->vals[envvars->count] = value;
envvars->count++;
}
void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars)
{
void *p;
p = malloc(sizeof(char *));
*(char **)p = NULL;
return p;
#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++) {
len += wc_strlen(WIDE_PATH_temp(envvars->names[i]));
len += wc_strlen(WIDE_PATH_temp(envvars->vals[i]));
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]);
slen = wc_strlen(s);
memcpy(r XFORM_OK_PLUS len, s, slen * sizeof(wchar_t));
len += slen;
r[len++] = '=';
s = WIDE_PATH(envvars->vals[i]);
slen = wc_strlen(s);
memcpy(r XFORM_OK_PLUS len, s, slen * sizeof(wchar_t));
len += slen;
r[len++] = 0;
}
r[len] = 0;
return r;
#endif
}