gio: use reentrant getservbyname_r() if available

This commit is contained in:
Thomas Haller 2023-08-11 12:08:42 +02:00 committed by Philip Withnall
parent 8aa889dbf1
commit f738c7f3db
5 changed files with 50 additions and 11 deletions

View File

@ -486,10 +486,7 @@ g_network_address_parse (const gchar *host_and_port,
else
{
struct servent *entry;
entry = getservbyname (port, "tcp");
if (entry == NULL)
if (!g_getservbyname_ntohs (port, "tcp", &portnum))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Unknown service '%s' specified in hostname '%s'",
@ -501,8 +498,6 @@ g_network_address_parse (const gchar *host_and_port,
return NULL;
}
portnum = g_ntohs (entry->s_port);
#ifdef HAVE_ENDSERVENT
endservent ();
#endif

View File

@ -23,6 +23,7 @@
#include "config.h"
#include "gnetworking.h"
#include "gnetworkingprivate.h"
/**
* SECTION:gnetworking
@ -76,3 +77,26 @@ g_networking_init (void)
}
#endif
}
gboolean
g_getservbyname_ntohs (const char *name, const char *proto, guint16 *out_port)
{
struct servent *result;
#ifdef HAVE_GETSERVBYNAME_R
struct servent result_buf;
char buf[2048];
int r;
r = getservbyname_r (name, proto, &result_buf, buf, sizeof (buf), &result);
if (r != 0 || result != &result_buf)
result = NULL;
#else
result = getservbyname (name, proto);
#endif
if (!result)
return FALSE;
*out_port = g_ntohs (result->s_port);
return TRUE;
}

View File

@ -33,6 +33,8 @@ gint g_socket (gint domain,
gint protocol,
GError **error);
gboolean g_getservbyname_ntohs (const char *name, const char *proto, guint16 *out_port);
G_END_DECLS
#endif /* __G_NETWORKINGPRIVATE_H__ */

View File

@ -364,17 +364,17 @@ static GList *
g_network_service_fallback_targets (GNetworkService *srv)
{
GSrvTarget *target;
struct servent *entry;
gboolean has_port;
guint16 port;
entry = getservbyname (srv->priv->service, "tcp");
port = entry ? g_ntohs (entry->s_port) : 0;
has_port = g_getservbyname_ntohs (srv->priv->service, "tcp", &port);
#ifdef HAVE_ENDSERVENT
endservent ();
#endif
if (entry == NULL)
return NULL;
if (!has_port)
return NULL;
target = g_srv_target_new (srv->priv->domain, port, 0, 0);
return g_list_append (NULL, target);

View File

@ -756,6 +756,24 @@ if cc.has_function('memalign', prefix: '#include <stdlib.h>\n#include <malloc.h>
glib_conf.set('HAVE_MEMALIGN', 1)
endif
# For example on Openbsd, getservbyname_r() has a different signature.
# https://man.openbsd.org/getservbyname.3
if cc.compiles('''#include <netdb.h>
int main (int argc, char ** argv) {
int (*fcn)(const char *,
const char *,
struct servent *,
char *,
size_t,
struct servent **) = getservbyname_r;
(void) fcn;
return 0;
}''',
name : 'getservbyname_r()',
args: '-Werror=incompatible-pointer-types')
glib_conf.set('HAVE_GETSERVBYNAME_R', 1)
endif
if cc.has_function('_aligned_malloc', prefix: '#include <malloc.h>')
glib_conf.set('HAVE__ALIGNED_MALLOC', 1)
endif