mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 20:07:36 +00:00
LibC: Remove dependency of getservbyname() in getaddrinfo()
This commit is contained in:
parent
37cea81837
commit
2b430e1f56
1 changed files with 91 additions and 6 deletions
|
@ -822,11 +822,96 @@ int getaddrinfo(char const* __restrict node, char const* __restrict service, con
|
||||||
|
|
||||||
long port;
|
long port;
|
||||||
int socktype;
|
int socktype;
|
||||||
servent* svc_ent = nullptr;
|
|
||||||
if (!hints || (hints->ai_flags & AI_NUMERICSERV) == 0) {
|
struct ServiceData {
|
||||||
svc_ent = getservbyname(service, proto);
|
String protocol;
|
||||||
|
u32 port;
|
||||||
|
};
|
||||||
|
Optional<ServiceData> service_data = {};
|
||||||
|
|
||||||
|
if ((!hints || (hints->ai_flags & AI_NUMERICSERV) == 0) && service) {
|
||||||
|
services_file = fopen(services_path, "r");
|
||||||
|
if (!services_file) {
|
||||||
|
return EAI_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
char* line = nullptr;
|
||||||
|
size_t length = 0;
|
||||||
|
ssize_t read;
|
||||||
|
|
||||||
|
// Read lines from services file until an actual service name is found.
|
||||||
|
do {
|
||||||
|
read = getline(&line, &length, services_file);
|
||||||
|
if (read > 0 && (line[0] >= 65 && line[0] <= 122)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (read != -1);
|
||||||
|
|
||||||
|
if (read == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto split_line = StringView(line, read).replace(" "sv, "\t"sv, ReplaceMode::All).split('\t');
|
||||||
|
if (split_line.size() < 2)
|
||||||
|
return EAI_FAIL;
|
||||||
|
|
||||||
|
auto name_or_error = String::from_deprecated_string(split_line[0]);
|
||||||
|
if (name_or_error.is_error())
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
auto name = name_or_error.release_value();
|
||||||
|
if (name != service)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto port_protocol_or_error = String::from_deprecated_string(split_line[1]);
|
||||||
|
if (port_protocol_or_error.is_error())
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
auto port_protocol = port_protocol_or_error.release_value();
|
||||||
|
|
||||||
|
auto port_protocol_split_or_error = port_protocol.split('/');
|
||||||
|
if (port_protocol_split_or_error.is_error())
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
auto port_protocol_split = port_protocol_split_or_error.release_value();
|
||||||
|
|
||||||
|
if (port_protocol_split.size() < 2)
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
auto number = port_protocol_split[0].to_number<u32>();
|
||||||
|
if (!number.has_value())
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
auto port = number.value();
|
||||||
|
|
||||||
|
// Remove any annoying whitespace at the end of the protocol.
|
||||||
|
auto protocol_or_error = port_protocol_split[1].replace(" "sv, ""sv, ReplaceMode::All);
|
||||||
|
if (protocol_or_error.is_error())
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
protocol_or_error = protocol_or_error.value().replace("\t"sv, ""sv, ReplaceMode::All);
|
||||||
|
if (protocol_or_error.is_error())
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
protocol_or_error = protocol_or_error.value().replace("\n"sv, ""sv, ReplaceMode::All);
|
||||||
|
if (protocol_or_error.is_error())
|
||||||
|
return EAI_SYSTEM;
|
||||||
|
|
||||||
|
auto protocol = protocol_or_error.release_value();
|
||||||
|
|
||||||
|
if (protocol != proto)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
service_data = { { protocol,
|
||||||
|
port } };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fclose(services_file) < 0)
|
||||||
|
return EAI_SYSTEM;
|
||||||
}
|
}
|
||||||
if (!svc_ent) {
|
if (!service_data.has_value()) {
|
||||||
if (service) {
|
if (service) {
|
||||||
char* end;
|
char* end;
|
||||||
port = htons(strtol(service, &end, 10));
|
port = htons(strtol(service, &end, 10));
|
||||||
|
@ -841,8 +926,8 @@ int getaddrinfo(char const* __restrict node, char const* __restrict service, con
|
||||||
else
|
else
|
||||||
socktype = SOCK_STREAM;
|
socktype = SOCK_STREAM;
|
||||||
} else {
|
} else {
|
||||||
port = svc_ent->s_port;
|
port = service_data.value().port;
|
||||||
socktype = strcmp(svc_ent->s_proto, "tcp") ? SOCK_STREAM : SOCK_DGRAM;
|
socktype = service_data.value().protocol == "tcp" ? SOCK_STREAM : SOCK_DGRAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
addrinfo* first_info = nullptr;
|
addrinfo* first_info = nullptr;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue