mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
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
4 changed files with 213 additions and 11 deletions
|
@ -50,6 +50,7 @@ start.o \
|
|||
time.o \
|
||||
random.o \
|
||||
abs.o \
|
||||
env.o \
|
||||
integer.o \
|
||||
c++.o \
|
||||
memory.o \
|
||||
|
|
192
libmaxsi/env.cpp
Normal file
192
libmaxsi/env.cpp
Normal file
|
@ -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 status);
|
||||
void free(void*);
|
||||
char* getenv(const char*);
|
||||
long labs(long);
|
||||
long long llabs(long long);
|
||||
void* malloc(size_t);
|
||||
#if !defined(_SORTIX_SOURCE)
|
||||
char* mktemp(char* templ);
|
||||
#endif
|
||||
int putenv(char*);
|
||||
void qsort(void*, size_t, size_t, int (*)(const void*, const void*));
|
||||
int rand(void);
|
||||
void* realloc(void*, size_t);
|
||||
int setenv(const char*, const char*, int);
|
||||
long strtol(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);
|
||||
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. */
|
||||
#if defined(__SORTIX_SHOW_UNIMPLEMENTED)
|
||||
|
@ -99,11 +118,9 @@ long nrand48(unsigned short[3]);
|
|||
int posix_memalign(void**, size_t, size_t);
|
||||
int posix_openpt(int);
|
||||
char* ptsname(int);
|
||||
int putenv(char*);
|
||||
long random(void);
|
||||
char* realpath(const char* restrict, char* restrict);
|
||||
unsigned short *seed48(unsigned short [3]);
|
||||
int setenv(const char*, const char*, int);
|
||||
void setkey(const char*);
|
||||
char* setstate(char*);
|
||||
void srand(unsigned);
|
||||
|
@ -114,7 +131,6 @@ float strtof(const char* restrict, char** restrict);
|
|||
long double strtold(const char* restrict, char** restrict);
|
||||
int system(const char*);
|
||||
int unlockpt(int);
|
||||
int unsetenv(const char*);
|
||||
size_t wcstombs(char* restrict, const wchar_t *restrict, size_t);
|
||||
int wctomb(char*, wchar_t);
|
||||
|
||||
|
|
|
@ -40,8 +40,6 @@ namespace Maxsi
|
|||
DEFN_SYSCALL0(pid_t, SysGetParentPID, SYSCALL_GETPPID);
|
||||
DEFN_SYSCALL3(pid_t, SysWait, SYSCALL_WAIT, pid_t, int*, int);
|
||||
|
||||
extern "C" char** environ = NULL;
|
||||
|
||||
void Abort()
|
||||
{
|
||||
// TODO: Send SIGABRT instead!
|
||||
|
@ -102,11 +100,6 @@ namespace Maxsi
|
|||
{
|
||||
return waitpid(-1, status, 0);
|
||||
}
|
||||
|
||||
extern "C" char* getenv(const char* name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue