Implemented setenv(3), putenv(3), getenv(3), clearenv(3), sortix_getenv(3),
unsetenv(3), envlength(3), getenvindexed(3), and environ(7). This provides the user-space foundation for environmental variables. Note that this works over fork(2), but not execve(2) yet.
This commit is contained in:
parent
5d59f0ed03
commit
dd5157da6a
|
@ -50,6 +50,7 @@ start.o \
|
||||||
time.o \
|
time.o \
|
||||||
random.o \
|
random.o \
|
||||||
abs.o \
|
abs.o \
|
||||||
|
env.o \
|
||||||
integer.o \
|
integer.o \
|
||||||
c++.o \
|
c++.o \
|
||||||
memory.o \
|
memory.o \
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2012.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
env.cpp
|
||||||
|
Environmental variables utilities.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* Since legacy applications rely on being able to modify the environ variable,
|
||||||
|
we have to keep track of whether it is what we expect and whether we know the
|
||||||
|
size of it. If it changed, we need to recount, as well as malloc a copy of it
|
||||||
|
if we wish to make changes. */
|
||||||
|
extern "C" { char** environ = NULL; }
|
||||||
|
static char** environ_malloced = NULL;
|
||||||
|
static char** environ_counted = NULL;
|
||||||
|
size_t environlen = 0;
|
||||||
|
size_t environroom = 0;
|
||||||
|
|
||||||
|
static inline bool environismalloced()
|
||||||
|
{
|
||||||
|
return environ && environ == environ_malloced;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* const* getenviron(void)
|
||||||
|
{
|
||||||
|
return environ;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" size_t envlength(void)
|
||||||
|
{
|
||||||
|
if ( !environ ) { return 0; }
|
||||||
|
if ( environ_counted != environ )
|
||||||
|
{
|
||||||
|
size_t count = 0;
|
||||||
|
while ( environ[count] ) { count++; }
|
||||||
|
environ_counted = environ;
|
||||||
|
environlen = count;
|
||||||
|
}
|
||||||
|
return environlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* getenvindexed(size_t index)
|
||||||
|
{
|
||||||
|
if ( envlength() <= index ) { errno = EBOUND; return NULL; }
|
||||||
|
return environ[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" const char* sortix_getenv(const char* name)
|
||||||
|
{
|
||||||
|
size_t equalpos = strcspn(name, "=");
|
||||||
|
if ( name[equalpos] == '=' ) { return NULL; }
|
||||||
|
size_t namelen = equalpos;
|
||||||
|
size_t envlen = envlength();
|
||||||
|
for ( size_t i = 0; i < envlen; i++ )
|
||||||
|
{
|
||||||
|
if ( strncmp(name, environ[i], namelen) ) { continue; }
|
||||||
|
if ( environ[i][namelen] != '=' ) { continue; }
|
||||||
|
return environ[i] + namelen + 1;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" char* getenv(const char* name)
|
||||||
|
{
|
||||||
|
return (char*) sortix_getenv(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool makeenvironmalloced()
|
||||||
|
{
|
||||||
|
if ( environismalloced() ) { return true; }
|
||||||
|
size_t envlen = envlength();
|
||||||
|
size_t newenvlen = envlen;
|
||||||
|
size_t newenvsize = sizeof(char*) * (newenvlen+1);
|
||||||
|
char** newenviron = (char**) malloc(newenvsize);
|
||||||
|
if ( !newenviron ) { return false; }
|
||||||
|
size_t sofar = 0;
|
||||||
|
for ( size_t i = 0; i < envlen; i++ )
|
||||||
|
{
|
||||||
|
newenviron[i] = strdup(environ[i]);
|
||||||
|
if ( !newenviron[i] ) { goto cleanup; }
|
||||||
|
sofar = i;
|
||||||
|
}
|
||||||
|
newenviron[envlen] = NULL;
|
||||||
|
environlen = environroom = newenvlen;
|
||||||
|
environ = environ_malloced = environ_counted = newenviron;
|
||||||
|
return true;
|
||||||
|
cleanup:
|
||||||
|
for ( size_t i = 0; i < sofar; i++ ) { free(newenviron[i]); }
|
||||||
|
free(newenviron);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int clearenv(void)
|
||||||
|
{
|
||||||
|
if ( !environ ) { return 0; }
|
||||||
|
if ( environismalloced() )
|
||||||
|
{
|
||||||
|
for ( char** varp = environ; *varp; varp++ ) { free(*varp); }
|
||||||
|
free(environ);
|
||||||
|
}
|
||||||
|
environ = environ_counted = environ_malloced = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool doputenv(char* str, char* freeme, bool overwrite)
|
||||||
|
{
|
||||||
|
if ( !makeenvironmalloced() ) { free(freeme); return false; }
|
||||||
|
size_t strvarnamelen = strcspn(str, "=");
|
||||||
|
for ( size_t i = 0; i < envlength(); i++ )
|
||||||
|
{
|
||||||
|
char* var = environ[i];
|
||||||
|
if ( strncmp(str, var, strvarnamelen) ) { continue; }
|
||||||
|
if ( !overwrite ) { free(freeme); return true; }
|
||||||
|
free(var);
|
||||||
|
environ[i] = str;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( environlen == environroom )
|
||||||
|
{
|
||||||
|
size_t newenvironroom = environroom ? 2 * environroom : 16;
|
||||||
|
size_t newenvironsize = sizeof(char*) * (newenvironroom+1);
|
||||||
|
char** newenviron = (char**) realloc(environ, newenvironsize);
|
||||||
|
if ( !newenviron ) { free(freeme); return false; }
|
||||||
|
environ = environ_malloced = environ_counted = newenviron;
|
||||||
|
environroom = newenvironroom;
|
||||||
|
}
|
||||||
|
environ[environlen++] = str;
|
||||||
|
environ[environlen] = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int setenv(const char* name, const char* value, int overwrite)
|
||||||
|
{
|
||||||
|
if ( !name || !name[0] || strchr(name, '=') ) { errno = EINVAL; return -1; }
|
||||||
|
char* str = (char*) malloc(strlen(name) + 1 + strlen(value) + 1);
|
||||||
|
if ( !str ) { return -1; }
|
||||||
|
stpcpy(stpcpy(stpcpy(str, name), "="), value);
|
||||||
|
if ( !doputenv(str, str, overwrite) ) { return -1; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int putenv(char* str)
|
||||||
|
{
|
||||||
|
if ( !strchr(str, '=') ) { errno = EINVAL; return -1; }
|
||||||
|
if ( !doputenv(str, NULL, true) ) { return -1; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int unsetenv(const char* name)
|
||||||
|
{
|
||||||
|
size_t equalpos = strcspn(name, "=");
|
||||||
|
if ( name[equalpos] == '=' ) { return 0; }
|
||||||
|
size_t namelen = equalpos;
|
||||||
|
size_t envlen = envlength();
|
||||||
|
for ( size_t i = 0; i < envlen; i++ )
|
||||||
|
{
|
||||||
|
if ( strncmp(name, environ[i], namelen) ) { continue; }
|
||||||
|
if ( environ[i][namelen] != '=' ) { continue; }
|
||||||
|
if ( environismalloced() )
|
||||||
|
{
|
||||||
|
char* str = environ[i];
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
if ( i < envlen-1 ) { environ[i] = environ[envlen-1]; }
|
||||||
|
environ[--environlen] = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -56,20 +56,39 @@ void* calloc(size_t, size_t);
|
||||||
void exit(int);
|
void exit(int);
|
||||||
void _Exit(int status);
|
void _Exit(int status);
|
||||||
void free(void*);
|
void free(void*);
|
||||||
char* getenv(const char*);
|
|
||||||
long labs(long);
|
long labs(long);
|
||||||
long long llabs(long long);
|
long long llabs(long long);
|
||||||
void* malloc(size_t);
|
void* malloc(size_t);
|
||||||
#if !defined(_SORTIX_SOURCE)
|
#if !defined(_SORTIX_SOURCE)
|
||||||
char* mktemp(char* templ);
|
char* mktemp(char* templ);
|
||||||
#endif
|
#endif
|
||||||
|
int putenv(char*);
|
||||||
void qsort(void*, size_t, size_t, int (*)(const void*, const void*));
|
void qsort(void*, size_t, size_t, int (*)(const void*, const void*));
|
||||||
int rand(void);
|
int rand(void);
|
||||||
void* realloc(void*, size_t);
|
void* realloc(void*, size_t);
|
||||||
|
int setenv(const char*, const char*, int);
|
||||||
long strtol(const char* restrict, char** restrict, int);
|
long strtol(const char* restrict, char** restrict, int);
|
||||||
unsigned long strtoul(const char* restrict, char** restrict, int);
|
unsigned long strtoul(const char* restrict, char** restrict, int);
|
||||||
unsigned long long strtoull(const char* restrict, char** restrict, int);
|
unsigned long long strtoull(const char* restrict, char** restrict, int);
|
||||||
long long strtoll(const char* restrict, char** restrict, int);
|
long long strtoll(const char* restrict, char** restrict, int);
|
||||||
|
int unsetenv(const char*);
|
||||||
|
|
||||||
|
#if defined(_SORTIX_SOURCE) || defined(_WANT_SORTIX_ENV)
|
||||||
|
const char* const* getenviron(void);
|
||||||
|
size_t envlength(void);
|
||||||
|
const char* getenvindexed(size_t index);
|
||||||
|
const char* sortix_getenv(const char* name);
|
||||||
|
#endif
|
||||||
|
#if (defined(_SOURCE_SOURCE) && __SORTIX_STDLIB_REDIRECTS) || \
|
||||||
|
defined(_WANT_SORTIX_ENV)
|
||||||
|
const char* getenv(const char* name) asm ("sortix_getenv");
|
||||||
|
#else
|
||||||
|
char* getenv(const char*);
|
||||||
|
#endif
|
||||||
|
#if defined(_SORTIX_SOURCE) || defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE) \
|
||||||
|
|| defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
|
||||||
|
int clearenv(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* TODO: These are not implemented in libmaxsi/sortix yet. */
|
/* TODO: These are not implemented in libmaxsi/sortix yet. */
|
||||||
#if defined(__SORTIX_SHOW_UNIMPLEMENTED)
|
#if defined(__SORTIX_SHOW_UNIMPLEMENTED)
|
||||||
|
@ -99,11 +118,9 @@ long nrand48(unsigned short[3]);
|
||||||
int posix_memalign(void**, size_t, size_t);
|
int posix_memalign(void**, size_t, size_t);
|
||||||
int posix_openpt(int);
|
int posix_openpt(int);
|
||||||
char* ptsname(int);
|
char* ptsname(int);
|
||||||
int putenv(char*);
|
|
||||||
long random(void);
|
long random(void);
|
||||||
char* realpath(const char* restrict, char* restrict);
|
char* realpath(const char* restrict, char* restrict);
|
||||||
unsigned short *seed48(unsigned short [3]);
|
unsigned short *seed48(unsigned short [3]);
|
||||||
int setenv(const char*, const char*, int);
|
|
||||||
void setkey(const char*);
|
void setkey(const char*);
|
||||||
char* setstate(char*);
|
char* setstate(char*);
|
||||||
void srand(unsigned);
|
void srand(unsigned);
|
||||||
|
@ -114,7 +131,6 @@ float strtof(const char* restrict, char** restrict);
|
||||||
long double strtold(const char* restrict, char** restrict);
|
long double strtold(const char* restrict, char** restrict);
|
||||||
int system(const char*);
|
int system(const char*);
|
||||||
int unlockpt(int);
|
int unlockpt(int);
|
||||||
int unsetenv(const char*);
|
|
||||||
size_t wcstombs(char* restrict, const wchar_t *restrict, size_t);
|
size_t wcstombs(char* restrict, const wchar_t *restrict, size_t);
|
||||||
int wctomb(char*, wchar_t);
|
int wctomb(char*, wchar_t);
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,6 @@ namespace Maxsi
|
||||||
DEFN_SYSCALL0(pid_t, SysGetParentPID, SYSCALL_GETPPID);
|
DEFN_SYSCALL0(pid_t, SysGetParentPID, SYSCALL_GETPPID);
|
||||||
DEFN_SYSCALL3(pid_t, SysWait, SYSCALL_WAIT, pid_t, int*, int);
|
DEFN_SYSCALL3(pid_t, SysWait, SYSCALL_WAIT, pid_t, int*, int);
|
||||||
|
|
||||||
extern "C" char** environ = NULL;
|
|
||||||
|
|
||||||
void Abort()
|
void Abort()
|
||||||
{
|
{
|
||||||
// TODO: Send SIGABRT instead!
|
// TODO: Send SIGABRT instead!
|
||||||
|
@ -102,11 +100,6 @@ namespace Maxsi
|
||||||
{
|
{
|
||||||
return waitpid(-1, status, 0);
|
return waitpid(-1, status, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" char* getenv(const char* name)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue