diff options
author | max99x <max99x@gmail.com> | 2011-07-29 22:32:29 +0300 |
---|---|---|
committer | max99x <max99x@gmail.com> | 2011-07-29 22:32:29 +0300 |
commit | b6b5430d73d74671bbae160715eed397b4cecd28 (patch) | |
tree | 69187dcd51a826e5fd8b50a3da0b6678b4b5e718 /src | |
parent | 1ac86ad03da43b50092ca18b5dcdc6359028d7a5 (diff) |
Implemented support for environment variables.
Diffstat (limited to 'src')
-rw-r--r-- | src/library.js | 137 |
1 files changed, 133 insertions, 4 deletions
diff --git a/src/library.js b/src/library.js index 8d649131..232a5581 100644 --- a/src/library.js +++ b/src/library.js @@ -3184,10 +3184,6 @@ LibraryManager.library = { return ret; }, - getenv: function(name_) { - return 0; // TODO - }, - strtod__deps: ['isspace', 'isdigit'], strtod: function(str, endptr) { // Skip space. @@ -3269,6 +3265,139 @@ LibraryManager.library = { _free(temp); }, + // NOTE: The global environment array is rebuilt from scratch after every + // change, which is inefficient, but should not be a bottleneck unless + // no malloc is used. + __environ: null, + __buildEnvironment__deps: ['__environ'], + __buildEnvironment: function(env) { + if (___environ === null) ___environ = allocate([0], "i8**", ALLOC_STATIC); + var ptrSize = {{{ Runtime.getNativeFieldSize('i8*') }}}; + var envPtr = {{{ makeGetValue('___environ', '0', 'i8**') }}}; + // Clear old. + if (envPtr !== 0) { + var cur = envPtr; + while ({{{ makeGetValue('cur', '0', 'i8*') }}} !== 0) { + _free({{{ makeGetValue('cur', '0', 'i8*') }}}); + cur += ptrSize; + } + _free(envPtr); + } + // Collect key=value lines. + var strings = []; + for (var key in env) { + if (typeof env[key] === 'string') { + strings.push(key + '=' + env[key]); + } + } + // Make new. + envPtr = _malloc(ptrSize * (strings.length + 1)); + {{{ makeSetValue('___environ', '0', 'envPtr', 'i8**') }}} + for (var i = 0; i < strings.length; i++) { + var line = strings[i]; + var ptr = _malloc(line.length + 1); + for (var j = 0; j < line.length; j++) { + {{{ makeSetValue('ptr', 'j', 'line.charCodeAt(j)', 'i8') }}} + } + {{{ makeSetValue('ptr', 'j', '0', 'i8') }}} + {{{ makeSetValue('envPtr', 'i * ptrSize', 'ptr', 'i8*') }}} + } + {{{ makeSetValue('envPtr', 'strings.length * ptrSize', '0', 'i8*') }}} + }, + $ENV__deps: ['__buildEnvironment'], + $ENV__postset: '___buildEnvironment(ENV);', + $ENV: { + 'USER': 'root', + 'PATH': '/', + 'PWD': '/', + 'HOME': '/', + 'LANG': 'en_US.UTF-8', + '_': './this.program' + }, + getenv__deps: ['$ENV'], + getenv: function(name) { + // char *getenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html + if (name === 0) return 0; + name = Pointer_stringify(name); + if (!ENV.hasOwnProperty(name)) return 0; + + if (_getenv.ret) _free(_getenv.ret); + _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL); + return _getenv.ret; + }, + clearenv__deps: ['$ENV', '__buildEnvironment'], + clearenv: function(name) { + // int clearenv (void); + // http://www.gnu.org/s/hello/manual/libc/Environment-Access.html#index-clearenv-3107 + ENV = {}; + ___buildEnvironment(ENV); + return 0; + }, + setenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], + setenv: function(envname, envval, overwrite) { + // int setenv(const char *envname, const char *envval, int overwrite); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/setenv.html + if (envname === 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + var name = Pointer_stringify(envname); + var val = Pointer_stringify(envval); + if (name === '' || name.indexOf('=') !== -1) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + if (ENV.hasOwnProperty(name) && !overwrite) return 0; + ENV[name] = val; + ___buildEnvironment(ENV); + return 0; + }, + unsetenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], + unsetenv: function(name) { + // int unsetenv(const char *name); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/unsetenv.html + if (name === 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + name = Pointer_stringify(name); + if (name === '' || name.indexOf('=') !== -1) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + if (ENV.hasOwnProperty(name)) { + delete ENV[name]; + ___buildEnvironment(ENV); + } + return 0; + }, + putenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], + putenv: function(string) { + // int putenv(char *string); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/putenv.html + // WARNING: According to the standard (and the glibc implementation), the + // string is taken by reference so future changes are reflected. + // We copy it instead, possibly breaking some uses. + if (string === 0) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + string = Pointer_stringify(string); + var splitPoint = string.indexOf('=') + if (string === '' || string.indexOf('=') === -1) { + ___setErrNo(ERRNO_CODES.EINVAL); + return -1; + } + var name = string.slice(0, splitPoint); + var value = string.slice(splitPoint + 1); + if (!(name in ENV) || ENV[name] !== value) { + ENV[name] = value; + ___buildEnvironment(ENV); + } + return 0; + }, + // ========================================================================== // string.h // ========================================================================== |