diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f2a8b1d1..8c60f40c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for external refs and encoded refs in external terms - Introduce ports to represent native processes and added support for external ports and encoded ports in external terms - Added support for socket asynchronous API for `recv` and `recvfrom`. +- Added `net:gethostname/0` on platforms with gethostname(3). ## [0.6.6] - Unreleased diff --git a/libs/estdlib/src/net.erl b/libs/estdlib/src/net.erl index 73385a333..08eb4d4a0 100644 --- a/libs/estdlib/src/net.erl +++ b/libs/estdlib/src/net.erl @@ -20,7 +20,7 @@ -module(net). --export([getaddrinfo/1, getaddrinfo/2]). +-export([getaddrinfo/1, getaddrinfo/2, gethostname/0]). %% nif call (so we can use guards at the API) -export([getaddrinfo_nif/2]). @@ -78,3 +78,12 @@ getaddrinfo(Host, Service) when %% @hidden getaddrinfo_nif(_Host, _Service) -> erlang:nif_error(undefined). + +%%----------------------------------------------------------------------------- +%% @returns The (usually short) name of the host. +%% @doc Get the hostname +%% @end +%%----------------------------------------------------------------------------- +-spec gethostname() -> {ok, string()} | {error, any()}. +gethostname() -> + erlang:nif_error(undefined). diff --git a/src/libAtomVM/otp_net.c b/src/libAtomVM/otp_net.c index a57a0aba9..42b37cf56 100644 --- a/src/libAtomVM/otp_net.c +++ b/src/libAtomVM/otp_net.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -325,6 +326,38 @@ static term nif_net_getaddrinfo(Context *ctx, int argc, term argv[]) return ret; } +// +// net:gethostname/0 +// +#ifdef HAVE_GETHOSTNAME +static term nif_net_gethostname(Context *ctx, int argc, term argv[]) +{ + TRACE("nif_net_gethostname\n"); + UNUSED(argc); + UNUSED(argv); + + char buf[256]; + int r = gethostname(buf, sizeof(buf)); + if (UNLIKELY(r)) { + if (UNLIKELY(memory_ensure_free_opt(ctx, TUPLE_SIZE(2), MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + return make_error_tuple(posix_errno_to_term(errno, ctx->global), ctx); + } + + size_t len = strlen(buf); + if (UNLIKELY(memory_ensure_free_opt(ctx, TUPLE_SIZE(2) + len * CONS_SIZE, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) { + RAISE_ERROR(OUT_OF_MEMORY_ATOM); + } + + term result = term_alloc_tuple(2, &ctx->heap); + term_put_tuple_element(result, 0, OK_ATOM); + term_put_tuple_element(result, 1, interop_bytes_to_list(buf, len, &ctx->heap)); + + return result; +} +#endif + // // Nifs // @@ -333,6 +366,12 @@ static const struct Nif net_getaddrinfo_nif = { .base.type = NIFFunctionType, .nif_ptr = nif_net_getaddrinfo }; +#ifdef HAVE_GETHOSTNAME +static const struct Nif net_gethostname_nif = { + .base.type = NIFFunctionType, + .nif_ptr = nif_net_gethostname +}; +#endif // // Entrypoints @@ -346,6 +385,12 @@ const struct Nif *otp_net_nif_get_nif(const char *nifname) TRACE("Resolved platform nif %s ...\n", nifname); return &net_getaddrinfo_nif; } +#ifdef HAVE_GETHOSTNAME + if (strcmp("gethostname/0", rest) == 0) { + TRACE("Resolved platform nif %s ...\n", nifname); + return &net_gethostname_nif; + } +#endif } return NULL; } diff --git a/src/platforms/esp32/components/avm_sys/CMakeLists.txt b/src/platforms/esp32/components/avm_sys/CMakeLists.txt index 5b4af68cb..ebcedd3b5 100644 --- a/src/platforms/esp32/components/avm_sys/CMakeLists.txt +++ b/src/platforms/esp32/components/avm_sys/CMakeLists.txt @@ -70,6 +70,10 @@ set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${soc_target_include_dir} include(CheckSymbolExists) include(CheckCSourceCompiles) +# Both don't exist in ESP32 at the moment +define_if_function_exists(libAtomVM${PLATFORM_LIB_SUFFIX} getservbyname "netdb.h" PRIVATE HAVE_SERVBYNAME) +define_if_function_exists(libAtomVM${PLATFORM_LIB_SUFFIX} gethostname "unistd.h" PRIVATE HAVE_GETHOSTNAME) + if ("${pthread_srcs}" MATCHES pthread_rwlock.c) set(HAVE_PTHREAD_RWLOCK YES) message(STATUS "pthread component includes pthread_rwlock.c, assuming it is available") diff --git a/src/platforms/generic_unix/lib/CMakeLists.txt b/src/platforms/generic_unix/lib/CMakeLists.txt index b02dba9bf..0b19309eb 100644 --- a/src/platforms/generic_unix/lib/CMakeLists.txt +++ b/src/platforms/generic_unix/lib/CMakeLists.txt @@ -57,6 +57,7 @@ endif() include(DefineIfExists) define_if_function_exists(libAtomVM${PLATFORM_LIB_SUFFIX} signal "signal.h" PRIVATE HAVE_SIGNAL) define_if_function_exists(libAtomVM${PLATFORM_LIB_SUFFIX} getservbyname "netdb.h" PRIVATE HAVE_SERVBYNAME) +define_if_function_exists(libAtomVM${PLATFORM_LIB_SUFFIX} gethostname "unistd.h" PRIVATE HAVE_GETHOSTNAME) target_link_libraries(libAtomVM${PLATFORM_LIB_SUFFIX} PUBLIC libAtomVM) include_directories(${CMAKE_SOURCE_DIR}/src/platforms/generic_unix/lib) diff --git a/src/platforms/rp2/src/lib/CMakeLists.txt b/src/platforms/rp2/src/lib/CMakeLists.txt index 699326b9d..957e34653 100644 --- a/src/platforms/rp2/src/lib/CMakeLists.txt +++ b/src/platforms/rp2/src/lib/CMakeLists.txt @@ -102,6 +102,11 @@ if (PICO_CYW43_SUPPORTED) otp_net_lwip_raw.h) target_link_libraries(libAtomVM${PLATFORM_LIB_SUFFIX} PUBLIC pico_cyw43_arch_lwip_threadsafe_background pico_lwip_sntp INTERFACE pan_lwip_dhserver) target_link_options(libAtomVM${PLATFORM_LIB_SUFFIX} PUBLIC "SHELL:-Wl,-u -Wl,networkregister_port_driver -Wl,-u -Wl,otp_socket_nif -Wl,-u -Wl,otp_net_nif -Wl,-u -Wl,otp_ssl_nif") + + include(CheckSymbolExists) + + define_if_function_exists(libAtomVM${PLATFORM_LIB_SUFFIX} getservbyname "netdb.h" PRIVATE HAVE_SERVBYNAME) + define_if_function_exists(libAtomVM${PLATFORM_LIB_SUFFIX} gethostname "unistd.h" PRIVATE HAVE_GETHOSTNAME) endif() target_link_options(libAtomVM${PLATFORM_LIB_SUFFIX} PUBLIC "SHELL:-Wl,-u -Wl,gpio_nif -Wl,-u -Wl,otp_crypto_nif") diff --git a/tests/libs/estdlib/test_net.erl b/tests/libs/estdlib/test_net.erl index 37042df43..05e445a3c 100644 --- a/tests/libs/estdlib/test_net.erl +++ b/tests/libs/estdlib/test_net.erl @@ -25,6 +25,7 @@ test() -> ok = test_getaddrinfo(), ok = test_getaddrinfo2(), + ok = test_gethostname(), ok. test_getaddrinfo() -> @@ -141,3 +142,7 @@ get_addr(AddrInfo) -> _ -> maps:get(addr, maps:get(address, AddrInfo)) end. + +test_gethostname() -> + {ok, [_ | _]} = net:gethostname(), + ok.