Index: fusl/src/network/getservbyport_r.c |
diff --git a/fusl/src/network/getservbyport_r.c b/fusl/src/network/getservbyport_r.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a0a7caecf77e8dd89bbbc3aa3ee3d3b4112ac08a |
--- /dev/null |
+++ b/fusl/src/network/getservbyport_r.c |
@@ -0,0 +1,55 @@ |
+#define _GNU_SOURCE |
+#include <sys/socket.h> |
+#include <netinet/in.h> |
+#include <netdb.h> |
+#include <inttypes.h> |
+#include <errno.h> |
+#include <string.h> |
+ |
+int getservbyport_r(int port, const char *prots, |
+ struct servent *se, char *buf, size_t buflen, struct servent **res) |
+{ |
+ int i; |
+ struct sockaddr_in sin = { |
+ .sin_family = AF_INET, |
+ .sin_port = port, |
+ }; |
+ |
+ if (!prots) { |
+ int r = getservbyport_r(port, "tcp", se, buf, buflen, res); |
+ if (r) r = getservbyport_r(port, "udp", se, buf, buflen, res); |
+ return r; |
+ } |
+ |
+ /* Align buffer */ |
+ i = (uintptr_t)buf & sizeof(char *)-1; |
+ if (!i) i = sizeof(char *); |
+ if (buflen < 3*sizeof(char *)-i) |
+ return ERANGE; |
+ buf += sizeof(char *)-i; |
+ buflen -= sizeof(char *)-i; |
+ |
+ if (strcmp(prots, "tcp") && strcmp(prots, "udp")) return EINVAL; |
+ |
+ se->s_port = port; |
+ se->s_proto = (char *)prots; |
+ se->s_aliases = (void *)buf; |
+ buf += 2*sizeof(char *); |
+ buflen -= 2*sizeof(char *); |
+ se->s_aliases[1] = 0; |
+ se->s_aliases[0] = se->s_name = buf; |
+ |
+ switch (getnameinfo((void *)&sin, sizeof sin, 0, 0, buf, buflen, |
+ strcmp(prots, "udp") ? 0 : NI_DGRAM)) { |
+ case EAI_MEMORY: |
+ case EAI_SYSTEM: |
+ return ENOMEM; |
+ default: |
+ return ENOENT; |
+ case 0: |
+ break; |
+ } |
+ |
+ *res = se; |
+ return 0; |
+} |