/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 1999-2009. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* %CopyrightEnd%
*/
/*
* BIFs belonging to the 'os' module.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "sys.h"
#include "erl_vm.h"
#include "global.h"
#include "erl_process.h"
#include "error.h"
#include "erl_driver.h"
#include "bif.h"
#include "big.h"
#include "dist.h"
#include "erl_version.h"
/*
* Return the pid for the Erlang process in the host OS.
*/
/* return a timestamp */
BIF_RETTYPE os_timestamp_0(BIF_ALIST_0)
{
Uint megasec, sec, microsec;
Eterm* hp;
get_sys_now(&megasec, &sec, µsec);
hp = HAlloc(BIF_P, 4);
BIF_RET(TUPLE3(hp, make_small(megasec), make_small(sec),
make_small(microsec)));
}
Eterm
os_getpid_0(Process* p)
{
char pid_string[21]; /* enough for a 64 bit number */
int n;
Eterm* hp;
sys_get_pid(pid_string); /* In sys.c */
n = sys_strlen(pid_string);
hp = HAlloc(p, n*2);
BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL));
}
Eterm
os_getenv_0(Process* p)
{
GETENV_STATE state;
char *cp;
Eterm* hp;
Eterm ret;
Eterm str;
int len;
init_getenv_state(&state);
ret = NIL;
while ((cp = getenv_string(&state)) != NULL) {
len = strlen(cp);
hp = HAlloc(p, len*2+2);
str = buf_to_intlist(&hp, cp, len, NIL);
ret = CONS(hp, str, ret);
}
fini_getenv_state(&state);
return ret;
}
Eterm
os_getenv_1(Process* p, Eterm key)
{
Eterm str;
int len, res;
char *key_str, *val;
char buf[1024];
size_t val_size = sizeof(buf);
len = is_string(key);
if (!len) {
BIF_ERROR(p, BADARG);
}
/* Leave at least one byte in buf for value */
key_str = len < sizeof(buf)-2 ? &buf[0] : erts_alloc(ERTS_ALC_T_TMP, len+1);
if (intlist_to_buf(key, key_str, len) != len)
erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
key_str[len] = '\0';
if (key_str != &buf[0])
val = &buf[0];
else {
val_size -= len + 1;
val = &buf[len + 1];
}
res = erts_sys_getenv(key_str, val, &val_size);
if (res < 0) {
no_var:
str = am_false;
} else {
Eterm* hp;
if (res > 0) {
val = erts_alloc(ERTS_ALC_T_TMP, val_size);
while (1) {
res = erts_sys_getenv(key_str, val, &val_size);
if (res == 0)
break;
else if (res < 0)
goto no_var;
else
val = erts_realloc(ERTS_ALC_T_TMP, val, val_size);
}
}
if (val_size)
hp = HAlloc(p, val_size*2);
str = buf_to_intlist(&hp, val, val_size, NIL);
}
if (key_str != &buf[0])
erts_free(ERTS_ALC_T_TMP, key_str);
if (val < &buf[0] || &buf[sizeof(buf)-1] < val)
erts_free(ERTS_ALC_T_TMP, val);
BIF_RET(str);
}
Eterm
os_putenv_2(Process* p, Eterm key, Eterm value)
{
char def_buf[1024];
char *buf = NULL;
int sep_ix, i, key_len, value_len, tot_len;
key_len = is_string(key);
if (!key_len) {
error:
if (buf)
erts_free(ERTS_ALC_T_TMP, (void *) buf);
BIF_ERROR(p, BADARG);
}
if (is_nil(value))
value_len = 0;
else {
value_len = is_string(value);
if (!value_len)
goto error;
}
tot_len = key_len + 1 + value_len + 1;
if (tot_len <= sizeof(def_buf))
buf = &def_buf[0];
else
buf = erts_alloc(ERTS_ALC_T_TMP, tot_len);
i = intlist_to_buf(key, buf, key_len);
if (i != key_len)
erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
sep_ix = i;
buf[i++] = '=';
if (is_not_nil(value))
i += intlist_to_buf(value, &buf[i], value_len);
if (i != key_len + 1 + value_len)
erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
buf[i] = '\0';
if (erts_sys_putenv(buf, sep_ix)) {
goto error;
}
if (buf != &def_buf[0])
erts_free(ERTS_ALC_T_TMP, (void *) buf);
BIF_RET(am_true);
}