In your original code:
Code:
vars->env[i] = xmalloc(sizeof(**vars->env) * 500);
vars->env[i] = &environ[i][0];
This is a memory leak (given the sane assumption that xmalloc() is a malloc()-like function). What you're doing is assigning the result of malloc() to a variable, then immediately overwriting that value with your next assignment. Incidentally that's probably why you got the crash: you wind up doing, essentially, free(&environ[i][0]) because that's now what vars->env[i] points to.
Your current method (the "old-fashioned" way) simply makes copies of pointers; that's not necessarily wrong. If you know that the data to which the pointers point won't be freed out from under you, or that it won't be changed, etc, then you're fine.
However, if you wanted to make copies of strings into newly allocated storage, you'd do it something like this (assume all allocations succeed):
Code:
char *new_string = malloc(strlen(old_string) + 1);
strcpy(new_string, old_string);
/* or for those who think that this needs "optimization" */
char *new_string;
size_t l;
l = strlen(old_string);
new_string = malloc(l + 1);
memcpy(new_string, old_string, l + 1);