/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 1999-2017. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions 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"
static int check_env_name(char *name);
/*
* 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)));
}
BIF_RETTYPE os_getpid_0(BIF_ALIST_0)
{
char pid_string[21]; /* enough for a 64 bit number */
int n;
Eterm* hp;
sys_get_pid(pid_string, sizeof(pid_string)); /* In sys.c */
n = sys_strlen(pid_string);
hp = HAlloc(BIF_P, n*2);
BIF_RET(buf_to_intlist(&hp, pid_string, n, NIL));
}
BIF_RETTYPE os_getenv_0(BIF_ALIST_0)
{
GETENV_STATE state;
char *cp;
Eterm* hp;
Eterm ret;
Eterm str;
init_getenv_state(&state);
ret = NIL;
while ((cp = getenv_string(&state)) != NULL) {
str = erts_convert_native_to_filename(BIF_P,(byte *)cp);
hp = HAlloc(BIF_P, 2);
ret = CONS(hp, str, ret);
}
fini_getenv_state(&state);
return ret;
}
#define STATIC_BUF_SIZE 1024
BIF_RETTYPE os_getenv_1(BIF_ALIST_1)
{
Process* p = BIF_P;
Eterm str;
Sint len;
int res;
char *key_str, *val;
char buf[STATIC_BUF_SIZE];
size_t val_size = sizeof(buf);
key_str = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE,
ERTS_ALC_T_TMP,1,0,&len);
if (!check_env_name(key_str)) {
if (key_str && key_str != &buf[0])
erts_free(ERTS_ALC_T_TMP, key_str);
BIF_ERROR(p, BADARG);
}
if (key_str != &buf[0])
val = &buf[0];
else {
/* len includes zero byte */
val_size -= len;
val = &buf[len];
}
res = erts_sys_getenv(key_str, val, &val_size);
if (res < 0) {
no_var:
str = am_false;
} else {
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);
}
}
str = erts_convert_native_to_filename(p,(byte *)val);
}
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);
}
BIF_RETTYPE os_putenv_2(BIF_ALIST_2)
{
char def_buf_key[STATIC_BUF_SIZE];
char def_buf_value[STATIC_BUF_SIZE];
char *key_buf = NULL, *value_buf = NULL;
key_buf = erts_convert_filename_to_native(BIF_ARG_1,def_buf_key,
STATIC_BUF_SIZE,
ERTS_ALC_T_TMP,0,0,NULL);
if (!check_env_name(key_buf))
goto badarg;
value_buf = erts_convert_filename_to_native(BIF_ARG_2,def_buf_value,
STATIC_BUF_SIZE,
ERTS_ALC_T_TMP,1,0,
NULL);
if (!value_buf)
goto badarg;
if (erts_sys_putenv(key_buf, value_buf)) {
if (key_buf != def_buf_key) {
erts_free(ERTS_ALC_T_TMP, key_buf);
}
if (value_buf != def_buf_value) {
erts_free(ERTS_ALC_T_TMP, value_buf);
}
BIF_ERROR(BIF_P, BADARG);
}
if (key_buf != def_buf_key) {
erts_free(ERTS_ALC_T_TMP, key_buf);
}
if (value_buf != def_buf_value) {
erts_free(ERTS_ALC_T_TMP, value_buf);
}
BIF_RET(am_true);
badarg:
if (key_buf && key_buf != def_buf_key)
erts_free(ERTS_ALC_T_TMP, key_buf);
if (value_buf && value_buf != def_buf_value)
erts_free(ERTS_ALC_T_TMP, value_buf);
BIF_ERROR(BIF_P, BADARG);
}
BIF_RETTYPE os_unsetenv_1(BIF_ALIST_1)
{
char *key_buf;
char buf[STATIC_BUF_SIZE];
key_buf = erts_convert_filename_to_native(BIF_ARG_1,buf,STATIC_BUF_SIZE,
ERTS_ALC_T_TMP,0,0,NULL);
if (!check_env_name(key_buf))
goto badarg;
if (erts_sys_unsetenv(key_buf))
goto badarg;
if (key_buf != buf) {
erts_free(ERTS_ALC_T_TMP, key_buf);
}
BIF_RET(am_true);
badarg:
if (key_buf && key_buf != buf)
erts_free(ERTS_ALC_T_TMP, key_buf);
BIF_ERROR(BIF_P, BADARG);
}
BIF_RETTYPE os_set_signal_2(BIF_ALIST_2) {
if (is_atom(BIF_ARG_1) && ((BIF_ARG_2 == am_ignore) ||
(BIF_ARG_2 == am_default) ||
(BIF_ARG_2 == am_handle))) {
if (!erts_set_signal(BIF_ARG_1, BIF_ARG_2))
goto error;
BIF_RET(am_ok);
}
error:
BIF_ERROR(BIF_P, BADARG);
}
static int
check_env_name(char *raw_name)
{
byte *c = (byte *) raw_name;
int encoding;
if (!c)
return 0;
encoding = erts_get_native_filename_encoding();
if (erts_raw_env_char_is_7bit_ascii_char('\0', c, encoding))
return 0; /* Do not allow empty name... */
/* Verify no '=' characters in variable name... */
do {
if (erts_raw_env_char_is_7bit_ascii_char('=', c, encoding))
return 0;
c = erts_raw_env_next_char(c, encoding);
} while (!erts_raw_env_char_is_7bit_ascii_char('\0', c, encoding));
return 1; /* Seems ok... */
}