Skip to content

Commit

Permalink
gio: use reentrant getservbyname_r() if available
Browse files Browse the repository at this point in the history
  • Loading branch information
thom311 authored and pwithnall committed Aug 14, 2023
1 parent 8aa889d commit f738c7f
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 11 deletions.
7 changes: 1 addition & 6 deletions gio/gnetworkaddress.c
Original file line number Diff line number Diff line change
Expand Up @@ -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'",
Expand All @@ -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
Expand Down
24 changes: 24 additions & 0 deletions gio/gnetworking.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "config.h"

#include "gnetworking.h"
#include "gnetworkingprivate.h"

/**
* SECTION:gnetworking
Expand Down Expand Up @@ -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;
}
2 changes: 2 additions & 0 deletions gio/gnetworkingprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
10 changes: 5 additions & 5 deletions gio/gnetworkservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit f738c7f

Please sign in to comment.