From f6ec5d2bc0610b81dbb387b5a59f80d37997617a Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Tue, 26 Jul 2016 23:04:52 +0200 Subject: [PATCH] Add getaddrinfo(1). --- utils/.gitignore | 1 + utils/Makefile | 1 + utils/getaddrinfo.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 utils/getaddrinfo.c diff --git a/utils/.gitignore b/utils/.gitignore index ce68ef78..96c61ba7 100644 --- a/utils/.gitignore +++ b/utils/.gitignore @@ -20,6 +20,7 @@ env expr false find +getaddrinfo halt head help diff --git a/utils/Makefile b/utils/Makefile index 1921f4ba..21bb8b86 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -31,6 +31,7 @@ env \ expr \ false \ find \ +getaddrinfo \ halt \ head \ help \ diff --git a/utils/getaddrinfo.c b/utils/getaddrinfo.c new file mode 100644 index 00000000..19e22927 --- /dev/null +++ b/utils/getaddrinfo.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * getaddrinfo.c + * Wrapper program for getaddrinfo(3). + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +static void compact_arguments(int* argc, char*** argv) +{ + for ( int i = 0; i < *argc; i++ ) + { + while ( i < *argc && !(*argv)[i] ) + { + for ( int n = i; n < *argc; n++ ) + (*argv)[n] = (*argv)[n+1]; + (*argc)--; + } + } +} + +int main(int argc, char* argv[]) +{ + const char* argv0 = argv[0]; + for ( int i = 1; i < argc; i++ ) + { + const char* arg = argv[i]; + if ( arg[0] != '-' || !arg[1] ) + continue; + argv[i] = NULL; + if ( !strcmp(arg, "--") ) + break; + if ( arg[1] != '-' ) + { + char c; + while ( (c = *++arg) ) switch ( c ) + { + default: + fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c); + exit(1); + } + } + else + { + fprintf(stderr, "%s: unknown option: %s\n", argv0, arg); + exit(1); + } + } + + compact_arguments(&argc, &argv); + + if ( argc < 2 ) + errx(1, "No host given"); + const char* host = argv[1]; + if ( 3 < argc ) + errx(1, "Unexpected extra operand `%s'", argv[3]); + const char* service = argv[2]; + + struct addrinfo* res = NULL; + int status = getaddrinfo(host, service, NULL, &res); + if ( status == EAI_SYSTEM ) + err(1, "%s", host); + if ( status ) + errx(1, "%s: %s", host, gai_strerror(status)); + for ( struct addrinfo* iter = res; iter; iter = iter->ai_next ) + { + // TODO: Implement and use getnameinfo(3). + if ( iter->ai_family == AF_INET ) + { + struct sockaddr_in* sin = (struct sockaddr_in*) iter->ai_addr; + char str[INET_ADDRSTRLEN]; + inet_ntop(iter->ai_family, &sin->sin_addr, str, sizeof(str)); + printf("%s\n", str); + } + else if ( iter->ai_family == AF_INET6 ) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*) iter->ai_addr; + char str[INET6_ADDRSTRLEN]; + inet_ntop(iter->ai_family, &sin6->sin6_addr, str, sizeof(str)); + printf("%s\n", str); + } + else + printf("(unknown address family %i)\n", iter->ai_family); + } + freeaddrinfo(res); + + return 0; +}