From d3ce5c1c868b3704b8e194adf718e7c026496760 Mon Sep 17 00:00:00 2001 From: llsth Date: Wed, 13 Jul 2016 23:51:58 +0200 Subject: [PATCH] Initial commit --- Makefile | 35 +++ config.h | 72 +++++ configure | 116 ++++++++ doc/whois.1 | 268 ++++++++++++++++++ doc/whois.guide | 146 ++++++++++ doc/whois.txt | 140 ++++++++++ error.c | 80 ++++++ getaddrinfo.c | 507 +++++++++++++++++++++++++++++++++++ getaddrinfo.h | 226 ++++++++++++++++ include/clib/amitcp_protos.h | 116 ++++++++ include/inline/amitcp.h | 203 ++++++++++++++ sgetln.c | 31 +++ strnstr.c | 67 +++++ version.h | 103 +++++++ wasprint.c | 84 ++++++ whois.c | 457 +++++++++++++++++++++++++++++++ whois_freebsd.c | 487 +++++++++++++++++++++++++++++++++ whois_netbsd.c | 329 +++++++++++++++++++++++ workman.sh | 37 +++ 19 files changed, 3504 insertions(+) create mode 100644 Makefile create mode 100644 config.h create mode 100644 configure create mode 100644 doc/whois.1 create mode 100644 doc/whois.guide create mode 100644 doc/whois.txt create mode 100644 error.c create mode 100644 getaddrinfo.c create mode 100644 getaddrinfo.h create mode 100644 include/clib/amitcp_protos.h create mode 100644 include/inline/amitcp.h create mode 100644 sgetln.c create mode 100644 strnstr.c create mode 100644 version.h create mode 100644 wasprint.c create mode 100644 whois.c create mode 100644 whois_freebsd.c create mode 100644 whois_netbsd.c create mode 100644 workman.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5192186 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +# Portable Makefile generated by configure + +all: whois + +CC = m68k-amigaos-gcc +CFLAGS = -O2 -m68000 -noixemul -Iinclude -Wall -Werror +LDFLAGS = -s -liberty -lm -lgcc + +config.h: getaddrinfo.h + touch config.h + +version.h: config.h + touch version.h + +whois.o: whois.c config.h version.h + +error.o: error.c config.h + +getaddrinfo.o: getaddrinfo.c config.h getaddrinfo.h + +sgetln.o: sgetln.c config.h + +strnstr.o: strnstr.c + +wasprint.o: wasprint.c config.h + + +whois: whois.o error.o getaddrinfo.o sgetln.o strnstr.o wasprint.o + ${CC} ${CFLAGS} -o whois whois.o error.o getaddrinfo.o sgetln.o strnstr.o wasprint.o ${LDFLAGS} + +clean: + rm -f whois.o error.o getaddrinfo.o sgetln.o strnstr.o wasprint.o whois + +depend: + @echo Dependencies already done diff --git a/config.h b/config.h new file mode 100644 index 0000000..7e86604 --- /dev/null +++ b/config.h @@ -0,0 +1,72 @@ +/* + * Written by Carsten Larsen. + * Public domain. + */ + +#ifndef WHOIS_CONFIG_H +#define WHOIS_CONFIG_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__AMIGA__) +#include +#include +#define IPTR ULONG +#endif + +#if defined(__AROS__) +#include +#define HAVE_ADDRINFO +#define INTELCPU +#define Socket socket +#define Connect connect +#define Send send +#endif + +#include "getaddrinfo.h" + +#define OPEN_VER_ERROR "Cannot open %s (%d.0)\n" +#define DOSLIB_NAME "dos.library" +#define DOSLIB_REV 33L +#define BSDLIB_NAME "bsdsocket.library" +#define BSDLIB_REV 03L + +#include + +extern struct Library *DOSBase; +extern struct Library *SocketBase; + +extern int errno; + +const char *getprogname(void); +void setprogname(const char *progname); + +void err0(int eval, const char *text); +void errx0(int eval, const char *text); +void errx2(int eval, const char *fmt, const void *arg1, const void *arg2); +void warn2(const char *fmt, const void *arg1, const void *arg2); +void warnx0(const char *text); +void warnx1(const char *fmt, const void *arg1); +void warnx2(const char *fmt, const void *arg1, const void *arg2); + +void cpy1(char **dest, const char *src); +void cpy2(char **dest, const char *src1, const char *src2); +void cpy1pad(char **dest, int minlen, const char *src); + +char *strnstr(const char *s, const char *find, size_t slen); + +char* sgetln(int sd, size_t *len); + +#ifndef EX_USAGE +#define EX_USAGE 64 +#endif + +#endif diff --git a/configure b/configure new file mode 100644 index 0000000..e288ac4 --- /dev/null +++ b/configure @@ -0,0 +1,116 @@ +#!/bin/sh +# +# Copyright (c) 2015 Carsten Larsen +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +set -e + +EXEC='whois' + +HDRS=' + config.h + getaddrinfo.h + version.h +' + +SRCS=' + whois.c + error.c + getaddrinfo.c + sgetln.c + strnstr.c + wasprint.c +' + +if make -v 2>&1 | grep GNU > /dev/null 2>&1 ; then + echo "make is GNU make." + VALID=true +#else +# echo "Wrong version of make." +# VALID=false +fi + +if $VALID ; then + ( + echo '# Portable Makefile generated by configure' + echo '' + echo "all: $EXEC" + echo '' + if [ -n "$1" ] && [ $1 = "AMIGA" ] ; then + echo 'CC = m68k-amigaos-gcc' + echo "CFLAGS = -O2 -m68000 -noixemul -Iinclude -Wall -Werror" + echo "LDFLAGS = -s -liberty -lm -lgcc" + elif [ -n "$1" ] && [ $1 = "AROS" ] ; then + echo 'CC = gcc' + echo "CFLAGS = -O2 -Iinclude -Wall -Werror" + echo "LDFLAGS = -lm" + else + echo "CFLAGS = -O2 -Wall -Werror" + echo "LDFLAGS = -s -lm" + fi + echo '' + + for f in ${HDRS} + do + b=`basename $f .h` + i=`sed -n -e '/#include.*"/{ + s/"$// + s/.*"// + p + }' $f | sort -u` + if [ "x${i}" != "x" ] ; then + echo "${b}.h: " ${i} + echo " touch ${b}.h" + echo + fi + done + + l="" + for f in ${SRCS} + do + b=`basename $f .c` + i=`sed -n -e '/#include.*"/{ + s/"$// + s/.*"// + p + }' $f | sort -u` + echo "${b}.o: ${b}.c" ${i} + echo + l="${l} ${b}.o" + done + + echo + echo "$EXEC: ${l}" + echo " \${CC} \${CFLAGS} -o $EXEC ${l} \${LDFLAGS}" + echo + echo "clean:" + echo " rm -f ${l} $EXEC" + echo + echo "depend:" + echo " @echo Dependencies already done" + ) > Makefile + + echo "Makefile generated" +fi diff --git a/doc/whois.1 b/doc/whois.1 new file mode 100644 index 0000000..287a42e --- /dev/null +++ b/doc/whois.1 @@ -0,0 +1,268 @@ +.\" Copyright (c) 1985, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" From: @(#)whois.1 8.1 (Berkeley) 6/6/93 +.\" $FreeBSD$ +.\" +.Dd October 2, 2009 +.Dt WHOIS 1 +.Os +.Sh NAME +.Nm whois +.Nd "Internet domain name and network number directory service" +.Sh SYNOPSIS +.Nm +.Op Fl aAbfgiIklmQrR +.Op Fl c Ar country-code | Fl h Ar host +.Op Fl p Ar port +.Ar name ... +.Sh DESCRIPTION +The +.Nm +utility looks up records in the databases maintained by several +Network Information Centers +.Pq Tn NICs . +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl a +Use the American Registry for Internet Numbers +.Pq Tn ARIN +database. +It contains network numbers used in those parts of the world covered neither by +.Tn APNIC , AfriNIC , LACNIC , +nor by +.Tn RIPE . +.Pp +(Hint: All point of contact handles in the +.Tn ARIN +whois database end with +.Qq Li -ARIN . ) +.Pp +.It Fl A +Use the Asia/Pacific Network Information Center +.Pq Tn APNIC +database. +It contains network numbers used in East Asia, Australia, +New Zealand, and the Pacific islands. +.It Fl b +Use the Network Abuse Clearinghouse database. +It contains addresses to which network abuse should be reported, +indexed by domain name. +.It Fl c Ar country-code +This is the equivalent of using the +.Fl h +option with an argument of +.Qq Ar country-code Ns Li .whois-servers.net . +.It Fl f +Use the African Network Information Centre +.Pq Tn AfriNIC +database. +It contains network numbers used in Africa and the islands of the +western Indian Ocean. +.It Fl g +Use the US non-military federal government database, which contains points of +contact for subdomains of +.Pa .GOV . +.It Fl h Ar host +Use the specified host instead of the default variant. +Either a host name or an IP address may be specified. +.Pp +By default +.Nm +constructs the name of a whois server to use from the top-level domain +.Pq Tn TLD +of the supplied (single) argument, and appending +.Qq Li .whois-servers.net . +This effectively allows a suitable whois server to be selected +automatically for a large number of +.Tn TLDs . +.Pp +In the event that an IP +address is specified, the whois server will default to the American +Registry for Internet Numbers +.Pq Tn ARIN . +If a query to +.Tn ARIN +references +.Tn APNIC , AfriNIC , LACNIC , +or +.Tn RIPE , +that server will be queried also, provided that the +.Fl Q +option is not specified. +.Pp +If the query is not a domain name or IP address, +.Nm +will fall back to +.Pa whois.crsnic.net . +.It Fl i +Use the Network Solutions Registry for Internet Numbers +.Pq Pa whois.networksolutions.com +database. +It contains network numbers and domain contact information for most of +.Pa .COM , .NET , .ORG +and +.Pa .EDU +domains. +.Pp +.Sy NOTE ! +The registration of these domains is now done by a number of +independent and competing registrars and this database holds no information +on the domains registered by organizations other than Network Solutions, Inc. +Also, note that the +.Tn InterNIC +database +.Pq Pa whois.internic.net +is no longer handled by Network Solutions, Inc. +For details, see +.Pa http://www.internic.net/ . +.Pp +(Hint: Contact information, identified by the term +.Em handle , +can be looked up by prefixing +.Qq Li "handle " +to the +.Tn NIC +handle in the query.) +.It Fl I +Use the Internet Assigned Numbers Authority +.Pq Tn IANA +database. +It contains network information for top-level domains. +.It Fl k +Use the National Internet Development Agency of Korea's +.Pq Tn KRNIC +database. +It contains network numbers and domain contact information +for Korea. +.It Fl l +Use the Latin American and Caribbean IP address Regional Registry +.Pq Tn LACNIC +database. +It contains network numbers used in much of Latin America and the +Caribbean. +.It Fl m +Use the Route Arbiter Database +.Pq Tn RADB +database. +It contains route policy specifications for a large +number of operators' networks. +.It Fl p Ar port +Connect to the whois server on +.Ar port . +If this option is not specified, +.Nm +defaults to port 43. +.It Fl Q +Do a quick lookup. +This means that +.Nm +will not attempt to lookup the name in the authoritative whois +server (if one is listed). +This option has no effect when combined with any other options. +.It Fl r +Use the R\(aaeseaux IP Europ\(aaeens +.Pq Tn RIPE +database. +It contains network numbers and domain contact information +for Europe. +.It Fl R +Use the Russia Network Information Center +.Pq Tn RIPN +database. +It contains network numbers and domain contact information +for subdomains of +.Pa .RU . +This option is deprecated; use the +.Fl c +option with an argument of +.Qq Li RU +instead. +.El +.Pp +The operands specified to +.Nm +are treated independently and may be used +as queries on different whois servers. +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +Most types of data, such as domain names and +.Tn IP +addresses, can be used as arguments to +.Nm +without any options, and +.Nm +will choose the correct whois server to query. +Some exceptions, where +.Nm +will not be able to handle data correctly, are detailed below. +.Pp +To obtain contact information about an +administrator located in the Russian +.Tn TLD +domain +.Qq Li RU , +use the +.Fl c +option as shown in the following example, where +.Ar CONTACT-ID +is substituted with the actual contact identifier. +.Pp +.Dl "whois -c RU CONTACT-ID" +.Pp +(Note: This example is specific to the +.Tn TLD +.Qq Li RU , +but other +.Tn TLDs +can be queried by using a similar syntax.) +.Pp +The following example demonstrates how to query +a whois server using a non-standard port, where +.Dq Li query-data +is the query to be sent to +.Dq Li whois.example.com +on port +.Dq Li rwhois +(written numerically as 4321). +.Pp +.Dl "whois -h whois.example.com -p rwhois query-data" +.Sh SEE ALSO +.Rs +.%A Ken Harrenstien +.%A Vic White +.%T NICNAME/WHOIS +.%D 1 March 1982 +.%O RFC 812 +.Re +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/doc/whois.guide b/doc/whois.guide new file mode 100644 index 0000000..3b1b438 --- /dev/null +++ b/doc/whois.guide @@ -0,0 +1,146 @@ +@database whois.guide +@author Carsten Larsen +@(c) Carsten Larsen +@$VER: whois.guide 1.37 (21.11.2015) +@node Main "whois manual" +@title "whois manual" + +NAME + whois -- Internet domain name and network number directory service + +SYNOPSIS + whois [-aAbfgiIklmQrR] [-c country-code | -h host] [-p port] name ... + +DESCRIPTION + The whois utility looks up records in the databases maintained by several + Network Information Centers (NICs). + + The options are as follows: + + -a Use the American Registry for Internet Numbers (ARIN) database. + It contains network numbers used in those parts of the world cov- + ered neither by APNIC, AfriNIC, LACNIC, nor by RIPE. + + (Hint: All point of contact handles in the ARIN whois database + end with "-ARIN".) + + -A Use the Asia/Pacific Network Information Center (APNIC) database. + It contains network numbers used in East Asia, Australia, New + Zealand, and the Pacific islands. + + -b Use the Network Abuse Clearinghouse database. It contains + addresses to which network abuse should be reported, indexed by + domain name. + + -c country-code + This is the equivalent of using the -h option with an argument of + "country-code.whois-servers.net". + + -f Use the African Network Information Centre (AfriNIC) database. + It contains network numbers used in Africa and the islands of the + western Indian Ocean. + + -g Use the US non-military federal government database, which con- + tains points of contact for subdomains of .GOV. + + -h host + Use the specified host instead of the default variant. Either a + host name or an IP address may be specified. + + By default whois constructs the name of a whois server to use + from the top-level domain (TLD) of the supplied (single) argu- + ment, and appending ".whois-servers.net". This effectively + allows a suitable whois server to be selected automatically for a + large number of TLDs. + + In the event that an IP address is specified, the whois server + will default to the American Registry for Internet Numbers + (ARIN). If a query to ARIN references APNIC, AfriNIC, LACNIC, or + RIPE, that server will be queried also, provided that the -Q + option is not specified. + + If the query is not a domain name or IP address, whois will fall + back to whois.crsnic.net. + + -i Use the Network Solutions Registry for Internet Numbers + (whois.networksolutions.com) database. It contains network num- + bers and domain contact information for most of .COM, .NET, .ORG + and .EDU domains. + + NOTE! The registration of these domains is now done by a number + of independent and competing registrars and this database holds + no information on the domains registered by organizations other + than Network Solutions, Inc. Also, note that the InterNIC data- + base (whois.internic.net) is no longer handled by Network Solu- + tions, Inc. For details, see http://www.internic.net/. + + (Hint: Contact information, identified by the term handle, can be + looked up by prefixing "handle " to the NIC handle in the query.) + + -I Use the Internet Assigned Numbers Authority (IANA) database. It + contains network information for top-level domains. + + -k Use the National Internet Development Agency of Korea's (KRNIC) + database. It contains network numbers and domain contact infor- + mation for Korea. + + -l Use the Latin American and Caribbean IP address Regional Registry + (LACNIC) database. It contains network numbers used in much of + Latin America and the Caribbean. + + -m Use the Route Arbiter Database (RADB) database. It contains + route policy specifications for a large number of operators' net- + works. + + -p port + Connect to the whois server on port. If this option is not spec- + ified, whois defaults to port 43. + + -Q Do a quick lookup. This means that whois will not attempt to + lookup the name in the authoritative whois server (if one is + listed). This option has no effect when combined with any other + options. + + -r Use the R'eseaux IP Europ'eens (RIPE) database. It contains net- + work numbers and domain contact information for Europe. + + -R Use the Russia Network Information Center (RIPN) database. It + contains network numbers and domain contact information for sub- + domains of .RU. This option is deprecated; use the -c option + with an argument of "RU" instead. + + The operands specified to whois are treated independently and may be used + as queries on different whois servers. + +EXIT STATUS + The whois utility exits 0 on success, and >0 if an error occurs. + +EXAMPLES + Most types of data, such as domain names and IP addresses, can be used as + arguments to whois without any options, and whois will choose the correct + whois server to query. Some exceptions, where whois will not be able to + handle data correctly, are detailed below. + + To obtain contact information about an administrator located in the Rus- + sian TLD domain "RU", use the -c option as shown in the following exam- + ple, where CONTACT-ID is substituted with the actual contact identifier. + + whois -c RU CONTACT-ID + + (Note: This example is specific to the TLD "RU", but other TLDs can be + queried by using a similar syntax.) + + The following example demonstrates how to query a whois server using a + non-standard port, where ``query-data'' is the query to be sent to + ``whois.example.com'' on port ``rwhois'' (written numerically as 4321). + + whois -h whois.example.com -p rwhois query-data + +SEE ALSO + Ken Harrenstien and Vic White, NICNAME/WHOIS, 1 March 1982, RFC 812. + +HISTORY + The whois command appeared in 4.3BSD. + + October 2, 2009 +@endnode diff --git a/doc/whois.txt b/doc/whois.txt new file mode 100644 index 0000000..20ce029 --- /dev/null +++ b/doc/whois.txt @@ -0,0 +1,140 @@ +WHOIS(1) BSD General Commands Manual WHOIS(1) + +NAME + whois -- Internet domain name and network number directory service + +SYNOPSIS + whois [-aAbfgiIklmQrR] [-c country-code | -h host] [-p port] name ... + +DESCRIPTION + The whois utility looks up records in the databases maintained by several + Network Information Centers (NICs). + + The options are as follows: + + -a Use the American Registry for Internet Numbers (ARIN) database. + It contains network numbers used in those parts of the world cov- + ered neither by APNIC, AfriNIC, LACNIC, nor by RIPE. + + (Hint: All point of contact handles in the ARIN whois database + end with "-ARIN".) + + -A Use the Asia/Pacific Network Information Center (APNIC) database. + It contains network numbers used in East Asia, Australia, New + Zealand, and the Pacific islands. + + -b Use the Network Abuse Clearinghouse database. It contains + addresses to which network abuse should be reported, indexed by + domain name. + + -c country-code + This is the equivalent of using the -h option with an argument of + "country-code.whois-servers.net". + + -f Use the African Network Information Centre (AfriNIC) database. + It contains network numbers used in Africa and the islands of the + western Indian Ocean. + + -g Use the US non-military federal government database, which con- + tains points of contact for subdomains of .GOV. + + -h host + Use the specified host instead of the default variant. Either a + host name or an IP address may be specified. + + By default whois constructs the name of a whois server to use + from the top-level domain (TLD) of the supplied (single) argu- + ment, and appending ".whois-servers.net". This effectively + allows a suitable whois server to be selected automatically for a + large number of TLDs. + + In the event that an IP address is specified, the whois server + will default to the American Registry for Internet Numbers + (ARIN). If a query to ARIN references APNIC, AfriNIC, LACNIC, or + RIPE, that server will be queried also, provided that the -Q + option is not specified. + + If the query is not a domain name or IP address, whois will fall + back to whois.crsnic.net. + + -i Use the Network Solutions Registry for Internet Numbers + (whois.networksolutions.com) database. It contains network num- + bers and domain contact information for most of .COM, .NET, .ORG + and .EDU domains. + + NOTE! The registration of these domains is now done by a number + of independent and competing registrars and this database holds + no information on the domains registered by organizations other + than Network Solutions, Inc. Also, note that the InterNIC data- + base (whois.internic.net) is no longer handled by Network Solu- + tions, Inc. For details, see http://www.internic.net/. + + (Hint: Contact information, identified by the term handle, can be + looked up by prefixing "handle " to the NIC handle in the query.) + + -I Use the Internet Assigned Numbers Authority (IANA) database. It + contains network information for top-level domains. + + -k Use the National Internet Development Agency of Korea's (KRNIC) + database. It contains network numbers and domain contact infor- + mation for Korea. + + -l Use the Latin American and Caribbean IP address Regional Registry + (LACNIC) database. It contains network numbers used in much of + Latin America and the Caribbean. + + -m Use the Route Arbiter Database (RADB) database. It contains + route policy specifications for a large number of operators' net- + works. + + -p port + Connect to the whois server on port. If this option is not spec- + ified, whois defaults to port 43. + + -Q Do a quick lookup. This means that whois will not attempt to + lookup the name in the authoritative whois server (if one is + listed). This option has no effect when combined with any other + options. + + -r Use the R'eseaux IP Europ'eens (RIPE) database. It contains net- + work numbers and domain contact information for Europe. + + -R Use the Russia Network Information Center (RIPN) database. It + contains network numbers and domain contact information for sub- + domains of .RU. This option is deprecated; use the -c option + with an argument of "RU" instead. + + The operands specified to whois are treated independently and may be used + as queries on different whois servers. + +EXIT STATUS + The whois utility exits 0 on success, and >0 if an error occurs. + +EXAMPLES + Most types of data, such as domain names and IP addresses, can be used as + arguments to whois without any options, and whois will choose the correct + whois server to query. Some exceptions, where whois will not be able to + handle data correctly, are detailed below. + + To obtain contact information about an administrator located in the Rus- + sian TLD domain "RU", use the -c option as shown in the following exam- + ple, where CONTACT-ID is substituted with the actual contact identifier. + + whois -c RU CONTACT-ID + + (Note: This example is specific to the TLD "RU", but other TLDs can be + queried by using a similar syntax.) + + The following example demonstrates how to query a whois server using a + non-standard port, where ``query-data'' is the query to be sent to + ``whois.example.com'' on port ``rwhois'' (written numerically as 4321). + + whois -h whois.example.com -p rwhois query-data + +SEE ALSO + Ken Harrenstien and Vic White, NICNAME/WHOIS, 1 March 1982, RFC 812. + +HISTORY + The whois command appeared in 4.3BSD. + +BSD October 2, 2009 BSD diff --git a/error.c b/error.c new file mode 100644 index 0000000..95cc39b --- /dev/null +++ b/error.c @@ -0,0 +1,80 @@ +/* + * Written by Carsten Larsen. + * Public domain. + */ + +#include "config.h" + +void err0(int eval, const char *text) { + int errno2 = errno; + fprintf(stderr, "%s: ", getprogname()); + + if (text != NULL) { + fprintf(stderr, "%s", text); + fprintf(stderr, ": "); + } + + fprintf(stderr, "%s\n", strerror(errno2)); + + exit(eval); +} + +void errx0(int eval, const char *text) { + fprintf(stderr, "%s: ", getprogname()); + + if (text != NULL) + fprintf(stderr, "%s", text); + + fprintf(stderr, "\n"); + exit(eval); +} + +void errx2(int eval, const char *fmt, const void *arg1, const void *arg2) { + fprintf(stderr, "%s: ", getprogname()); + + if (fmt != NULL) + fprintf(stderr, fmt, arg1, arg2); + + fprintf(stderr, "\n"); + exit(eval); +} + +void warn2(const char *fmt, const void *arg1, const void *arg2) { + int errno2 = errno; + fprintf(stderr, "%s: ", getprogname()); + + if (fmt != NULL) { + fprintf(stderr, fmt, arg1, arg2); + fprintf(stderr, ": "); + } + + fprintf(stderr, "%s\n", strerror(errno2)); +} + +void warnx0(const char *text) { + fprintf(stderr, "%s: ", getprogname()); + + if (text != NULL) + fprintf(stderr, "%s", text); + + fprintf(stderr, "\n"); +} + +void warnx1(const char *fmt, const void *arg1) +{ + fprintf(stderr, "%s: ", getprogname()); + + if (fmt != NULL) + fprintf(stderr, fmt, arg1); + + fprintf(stderr, "\n"); +} + +void warnx2(const char *fmt, const void *arg1, const void *arg2) { + fprintf(stderr, "%s: ", getprogname()); + + if (fmt != NULL) + fprintf(stderr, fmt, arg1, arg2); + + fprintf(stderr, "\n"); +} diff --git a/getaddrinfo.c b/getaddrinfo.c new file mode 100644 index 0000000..1c9312e --- /dev/null +++ b/getaddrinfo.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2015 Carsten Larsen + * Copyright (c) 2001, 02 Motoyuki Kasahara + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This program provides getaddrinfo() and getnameinfo() described in + * RFC2133, 2553 and 3493. These functions are mainly used for IPv6 + * application to resolve hostname or address. + * + * This program is designed to be working on traditional IPv4 systems + * which don't have those functions. Therefore, this implementation + * supports IPv4 only. + * + * This program is useful for application which should support both IPv6 + * and traditional IPv4 systems. Use genuine getaddrinfo() and getnameinfo() + * provided by system if the system supports IPv6. Otherwise, use this + * implementation. + * + * This program also provides freeaddrinfo() and gai_strerror(). + * + * Restriction: + * getaddrinfo() and getnameinfo() of this program are NOT thread + * safe, unless the cpp macro ENABLE_PTHREAD is defined. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "config.h" +#include "getaddrinfo.h" + +#ifdef ENABLE_NLS +#include +#endif + +#ifdef ENABLE_NLS +#define _(string) gettext(string) +#ifdef gettext_noop +#define N_(string) gettext_noop(string) +#else +#define N_(string) (string) +#endif +#else +#define gettext(string) (string) +#define _(string) (string) +#define N_(string) (string) +#endif + +/* + * Error messages for gai_strerror(). + */ +static char *eai_errlist[] = { + N_("Success"), + + /* EAI_ADDRFAMILY */ + N_("Address family for hostname not supported"), + + /* EAI_AGAIN */ + N_("Temporary failure in name resolution"), + + /* EAI_BADFLAGS */ + N_("Invalid value for ai_flags"), + + /* EAI_FAIL */ + N_("Non-recoverable failure in name resolution"), + + /* EAI_FAMILY */ + N_("ai_family not supported"), + + /* EAI_MEMORY */ + N_("Memory allocation failure"), + + /* EAI_NONAME */ + N_("hostname nor servname provided, or not known"), + + /* EAI_OVERFLOW */ + N_("An argument buffer overflowed"), + + /* EAI_SERVICE */ + N_("servname not supported for ai_socktype"), + + /* EAI_SOCKTYPE */ + N_("ai_socktype not supported"), + + /* EAI_SYSTEM */ + N_("System error returned in errno") +}; + +/* + * Default hints for getaddrinfo(). + */ +static struct addrinfo default_hints = { + 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL +}; + +/* + * Mutex. + */ +struct SignalSemaphore GetaddrinfoSemaphore; + +/* + * Declaration of static functions. + */ +#ifdef __STDC__ +static int is_integer(const char *); +static int is_address(const char *); +static int itoa_length(int); +#else +static int is_integer(); +static int is_address(); +static int itoa_length(); +#endif + +/* + * gai_strerror(). + */ +const char * +gai_strerror(ecode) +int ecode; +{ + if (ecode < 0 || ecode > EAI_SYSTEM) + return _("Unknown error"); + + return gettext(eai_errlist[ecode]); +} + +/* + * freeaddrinfo(). + */ +void +freeaddrinfo(ai) +struct addrinfo *ai; +{ + struct addrinfo *next_ai; + + while (ai != NULL) { + if (ai->ai_canonname != NULL) + free(ai->ai_canonname); + if (ai->ai_addr != NULL) + free(ai->ai_addr); + next_ai = ai->ai_next; + free(ai); + ai = next_ai; + } +} + +/* + * Return 1 if the string `s' represents an integer. + */ +static int +is_integer(s) +const char *s; +{ + if (*s == '-' || *s == '+') + s++; + if (*s < '0' || '9' < *s) + return 0; + + s++; + while ('0' <= *s && *s <= '9') + s++; + + return (*s == '\0'); +} + +/* + * Return 1 if the string `s' represents an IPv4 address. + * Unlike inet_addr(), it doesn't permit malformed nortation such + * as "192.168". + */ +static int +is_address(s) +const char *s; +{ + const static char delimiters[] = {'.', '.', '.', '\0'}; + int i, j; + int octet; + + for (i = 0; i < 4; i++) { + if (*s == '0' && *(s + 1) != delimiters[i]) + return 0; + for (j = 0, octet = 0; '0' <= *s && *s <= '9' && j < 3; s++, j++) + octet = octet * 10 + (*s - '0'); + if (j == 0 || octet > 255 || *s != delimiters[i]) + return 0; + s++; + } + + return 1; +} + +/* + * Calcurate length of the string `s', where `s' is set by + * sprintf(s, "%d", n). + */ +static int +itoa_length(n) +int n; +{ + int result = 1; + + if (n < 0) { + n = -n; + result++; + } + + while (n >= 10) { + result++; + n /= 10; + } + + return result; +} + +/* + * getaddrinfo(). + */ +int +getaddrinfo(nodename, servname, hints, res) +const char *nodename; +const char *servname; +const struct addrinfo *hints; +struct addrinfo **res; +{ + struct addrinfo *head_res = NULL; + struct addrinfo *tail_res = NULL; + struct addrinfo *new_res; + struct sockaddr_in *sa_in; + struct in_addr **addr_list; + struct in_addr *addr_list_buf[2]; + struct in_addr addr_buf; + struct in_addr **ap; + struct servent *servent; + struct hostent *hostent; + const char *canonname = NULL; + in_port_t port; + int saved_h_errno; + int result = 0; + + ObtainSemaphore(&GetaddrinfoSemaphore); + saved_h_errno = h_errno; + + if (nodename == NULL && servname == NULL) { + result = EAI_NONAME; + goto end; + } + + if (hints != NULL) { + if (hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC) { + result = EAI_FAMILY; + goto end; + } + if (hints->ai_socktype != SOCK_DGRAM + && hints->ai_socktype != SOCK_STREAM + && hints->ai_socktype != 0) { + result = EAI_SOCKTYPE; + goto end; + } + } else { + hints = &default_hints; + } + + if (servname != NULL) { + if (is_integer(servname)) + port = htons(atoi(servname)); + else { + if (hints->ai_flags & AI_NUMERICSERV) { + result = EAI_NONAME; + goto end; + } + + if (hints->ai_socktype == SOCK_DGRAM) + servent = getservbyname((char*)servname, (char*)"udp"); + else if (hints->ai_socktype == SOCK_STREAM) + servent = getservbyname((char*)servname, (char*)"tcp"); + else if (hints->ai_socktype == 0) + servent = getservbyname((char*)servname, (char*)"tcp"); + else { + result = EAI_SOCKTYPE; + goto end; + } + + if (servent == NULL) { + result = EAI_SERVICE; + goto end; + } + port = servent->s_port; + } + } else { + port = htons(0); + } + + if (nodename != NULL) { + if (is_address(nodename)) { + addr_buf.s_addr = inet_addr(nodename); + addr_list_buf[0] = &addr_buf; + addr_list_buf[1] = NULL; + addr_list = addr_list_buf; + + if (hints->ai_flags & AI_CANONNAME + && !(hints->ai_flags & AI_NUMERICHOST)) { + hostent = gethostbyaddr((char *)&addr_buf, + sizeof(struct in_addr), AF_INET); + if (hostent != NULL) + canonname = hostent->h_name; + else + canonname = nodename; + } + } else { + if (hints->ai_flags & AI_NUMERICHOST) { + result = EAI_NONAME; + goto end; + } + + hostent = gethostbyname(nodename); + if (hostent == NULL) { + switch (h_errno) { + case HOST_NOT_FOUND: + case NO_DATA: + result = EAI_NONAME; + goto end; + case TRY_AGAIN: + result = EAI_AGAIN; + goto end; + default: + result = EAI_FAIL; + goto end; + } + } + addr_list = (struct in_addr **)hostent->h_addr_list; + + if (hints->ai_flags & AI_CANONNAME) + canonname = hostent->h_name; + } + } else { + if (hints->ai_flags & AI_PASSIVE) + addr_buf.s_addr = htonl(INADDR_ANY); + else + addr_buf.s_addr = htonl(0x7F000001); + addr_list_buf[0] = &addr_buf; + addr_list_buf[1] = NULL; + addr_list = addr_list_buf; + } + + for (ap = addr_list; *ap != NULL; ap++) { + new_res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); + if (new_res == NULL) { + if (head_res != NULL) + freeaddrinfo(head_res); + result = EAI_MEMORY; + goto end; + } + + new_res->ai_family = PF_INET; + new_res->ai_socktype = hints->ai_socktype; + new_res->ai_protocol = hints->ai_protocol; + new_res->ai_addr = NULL; + new_res->ai_addrlen = sizeof(struct sockaddr_in); + new_res->ai_canonname = NULL; + new_res->ai_next = NULL; + + new_res->ai_addr = (struct sockaddr *) + malloc(sizeof(struct sockaddr_in)); + if (new_res->ai_addr == NULL) { + free(new_res); + if (head_res != NULL) + freeaddrinfo(head_res); + result = EAI_MEMORY; + goto end; + } + + sa_in = (struct sockaddr_in *)new_res->ai_addr; + memset(sa_in, 0, sizeof(struct sockaddr_in)); + sa_in->sin_family = PF_INET; + sa_in->sin_port = port; + memcpy(&sa_in->sin_addr, *ap, sizeof(struct in_addr)); + + if (head_res == NULL) + head_res = new_res; + else + tail_res->ai_next = new_res; + tail_res = new_res; + } + + if (canonname != NULL && head_res != NULL) { + head_res->ai_canonname = (char *)malloc(strlen(canonname) + 1); + if (head_res->ai_canonname != NULL) + strcpy(head_res->ai_canonname, canonname); + } + + *res = head_res; + +end: + h_errno = saved_h_errno; + ReleaseSemaphore(&GetaddrinfoSemaphore); + return result; +} + +int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *serv, socklen_t servlen, int flags) { + + const struct sockaddr_in *sa_in = (const struct sockaddr_in *)sa; + struct hostent *hostent; + struct servent *servent; + char *ntoa_address; + int saved_h_errno; + int result = 0; + + ObtainSemaphore(&GetaddrinfoSemaphore); + saved_h_errno = h_errno; + + if (sa_in->sin_family != PF_INET) { + result = EAI_FAMILY; + goto end; + } else if (node == NULL && serv == NULL) { + result = EAI_NONAME; + goto end; + } + + if (serv != NULL && servlen > 0) { + if (flags & NI_NUMERICSERV) + servent = NULL; + else if (flags & NI_DGRAM) + servent = getservbyport(sa_in->sin_port, "udp"); + else + servent = getservbyport(sa_in->sin_port, "tcp"); + + if (servent != NULL) { + if (servlen <= strlen(servent->s_name)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(serv, servent->s_name); + } else { + if (servlen <= itoa_length(ntohs(sa_in->sin_port))) { + result = EAI_OVERFLOW; + goto end; + } + sprintf(serv, "%d", ntohs(sa_in->sin_port)); + } + } + + if (node != NULL && nodelen > 0) { + if (flags & NI_NUMERICHOST) + hostent = NULL; + else { + hostent = gethostbyaddr((char *)&sa_in->sin_addr, + sizeof(struct in_addr), AF_INET); + } + if (hostent != NULL) { + if (nodelen <= strlen(hostent->h_name)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(node, hostent->h_name); + } else { + if (flags & NI_NAMEREQD) { + result = EAI_NONAME; + goto end; + } + ntoa_address = inet_ntoa(sa_in->sin_addr); + if (nodelen <= strlen(ntoa_address)) { + result = EAI_OVERFLOW; + goto end; + } + strcpy(node, ntoa_address); + } + + } + +end: + h_errno = saved_h_errno; + ReleaseSemaphore(&GetaddrinfoSemaphore); + return result; +} diff --git a/getaddrinfo.h b/getaddrinfo.h new file mode 100644 index 0000000..4a649d7 --- /dev/null +++ b/getaddrinfo.h @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2015 Carsten Larsen + * Copyright (c) 2001, 02 Motoyuki Kasahara + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef INET_GETADDRINFO_H +#define INET_GETADDRINFO_H + +#include +#include +#include +#include + +/********************************************************************/ +/* + * Undefine all the macros. + * might defines some of them. + */ +#ifdef EAI_ADDRFAMILY +#undef EAI_ADDRFAMILY +#endif +#ifdef EAI_AGAIN +#undef EAI_AGAIN +#endif +#ifdef EAI_BADFLAGS +#undef EAI_BADFLAGS +#endif +#ifdef EAI_FAIL +#undef EAI_FAIL +#endif +#ifdef EAI_FAMILY +#undef EAI_FAMILY +#endif +#ifdef EAI_MEMORY +#undef EAI_MEMORY +#endif +#ifdef EAI_NONAME +#undef EAI_NONAME +#endif +#ifdef EAI_OVERFLOW +#undef EAI_OVERFLOW +#endif +#ifdef EAI_SERVICE +#undef EAI_SERVICE +#endif +#ifdef EAI_SOCKTYPE +#undef EAI_SOCKTYPE +#endif +#ifdef EAI_SYSTEM +#undef EAI_SYSTEM +#endif + +#ifdef AI_PASSIVE +#undef AI_PASSIVE +#endif +#ifdef AI_CANONNAME +#undef AI_CANONNAME +#endif +#ifdef AI_NUMERICHOST +#undef AI_NUMERICHOST +#endif +#ifdef AI_NUMERICSERV +#undef AI_NUMERICSERV +#endif +#ifdef AI_V4MAPPED +#undef AI_V4MAPPED +#endif +#ifdef AI_ALL +#undef AI_ALL +#endif +#ifdef AI_ADDRCONFIG +#undef AI_ADDRCONFIG +#endif +#ifdef AI_DEFAULT +#undef AI_DEFAULT +#endif + +#ifdef NI_NOFQDN +#undef NI_NOFQDN +#endif +#ifdef NI_NUMERICHOST +#undef NI_NUMERICHOST +#endif +#ifdef NI_NAMEREQD +#undef NI_NAMEREQD +#endif +#ifdef NI_NUMERICSERV +#undef NI_NUMERICSERV +#endif +#ifdef NI_NUMERICSCOPE +#undef NI_NUMERICSCOPE +#endif + +#ifdef NI_DGRAM +#undef NI_DGRAM +#endif +#ifdef NI_MAXHOST +#undef NI_MAXHOST +#endif +#ifdef NI_MAXSERV +#undef NI_MAXSERV +#endif + +/* + * Fake struct and function names. + * might declares all or some of them. + */ +/* +#if defined(HAVE_GETADDRINFO) || defined(HAVE_GETNAMEINFO) +#define addrinfo my_addrinfo +#define gai_strerror my_gai_strerror +#define freeaddrinfo my_freeaddrinfo +#define getaddrinfo my_getaddrinfo +#define getnameinfo my_getnameinfo +#endif +*/ + +/********************************************************************/ +/* + * Error codes. + */ +#define EAI_ADDRFAMILY 1 +#define EAI_AGAIN 2 +#define EAI_BADFLAGS 3 +#define EAI_FAIL 4 +#define EAI_FAMILY 5 +#define EAI_MEMORY 6 +#define EAI_NONAME 7 +#define EAI_OVERFLOW 8 +#define EAI_SERVICE 9 +#define EAI_SOCKTYPE 10 +#define EAI_SYSTEM 11 + +/* + * Flags for getaddrinfo(). + */ +#define AI_ADDRCONFIG 0x0001 +#define AI_ALL 0x0002 +#define AI_CANONNAME 0x0004 +#define AI_NUMERICHOST 0x0008 +#define AI_NUMERICSERV 0x0010 +#define AI_PASSIVE 0x0020 +#define AI_V4MAPPED 0x0040 +#define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG) + +/* + * Flags for getnameinfo(). + */ +#define NI_DGRAM 0x0001 +#define NI_NAMEREQD 0x0002 +#define NI_NOFQDN 0x0004 +#define NI_NUMERICHOST 0x0008 +#define NI_NUMERICSCOPE 0x0010 +#define NI_NUMERICSERV 0x0020 + +/* + * Maximum length of FQDN and servie name for getnameinfo(). + */ +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Address families and Protocol families. + */ +#ifndef AF_UNSPEC +#define AF_UNSPEC AF_INET +#endif +#ifndef PF_UNSPEC +#define PF_UNSPEC PF_INET +#endif + +//#include +//typedef uint32_t socklen_t +typedef unsigned int socklen_t; + +#ifndef HAVE_ADDRINFO +/* Structure to contain information about address of a service provider. */ +struct addrinfo +{ + int ai_flags; /* Input flags. */ + int ai_family; /* Protocol family for socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol for socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address for socket. */ + char *ai_canonname; /* Canonical name for service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif + +typedef u_int16_t in_port_t; +typedef unsigned int sa_family_t; + +#include +extern struct SignalSemaphore GetaddrinfoSemaphore; + +const char* gai_strerror(int); +void freeaddrinfo(struct addrinfo *); +int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); +int getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *, socklen_t, int); + +#endif diff --git a/include/clib/amitcp_protos.h b/include/clib/amitcp_protos.h new file mode 100644 index 0000000..856a082 --- /dev/null +++ b/include/clib/amitcp_protos.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 Carsten Larsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _SOCKET_AMITCP_H +#define _SOCKET_AMITCP_H +//--------------------------------------------------------------------------// +#define AMITCP_BASE_NAME SocketBase +#include "inline/amitcp.h" +//--------------------------------------------------------------------------// +#define socket Socket +#define bind Bind +#define listen Listen +#define accept Accept +#define connect Connect +#define send Send +#define sendto SendTo +#define sendmsg SendMsg +#define recv Recv +#define recvfrom RecvFrom +#define recvmsg RecvMsg +#define select Select +#define shutdown ShutDown +#define setsockopt SetSockOpt +#define getsockopt GetSockOpt +#define getsockname GetSockName +#define getpeername GetPeerName +#define inet_addr Inet_Addr +#define inet_network Inet_Network +#define inet_ntoa Inet_NtoA +#define gethostbyname GetHostByName +#define gethostbyaddr GetHostByAddr +#define getnetbyname GetNetByName +#define getnetbyaddr GetNetByAddr +#define getservbyname GetServByName +#define getservbyport GetServByPort +#define getprotobyname GetProtoByName +#define getprotobynumber GetProtoByNumber +#define getdtablesize GetDTableSize +#define gethostname GetHostName +#define gethostid GetHostId +#define vsyslog SyslogA +#define syslog Syslog +//--------------------------------------------------------------------------// +#define Accept TCP_Accept +#define Bind TCP_Bind +#define CloseSocket TCP_CloseSocket +#define Connect TCP_Connect +#define Dup2Socket TCP_Dup2Socket +#define Errno TCP_Errno +#define GetDTableSize TCP_GetDTableSize +#define GetHostByAddr TCP_GetHostByAddr +#define GetHostByName TCP_GetHostByName +#define GetHostId TCP_GetHostId +#define GetHostName TCP_GetHostName +#define GetNetByAddr TCP_GetNetByAddr +#define GetNetByName TCP_GetNetByName +#define GetPeerName TCP_GetPeerName +#define GetProtoByName TCP_GetProtoByName +#define GetProtoByNumber TCP_GetProtoByNumber +#define GetServByName TCP_GetServByName +#define GetServByPort TCP_GetServByPort +#define GetSockName TCP_GetSockName +#define GetSockOpt TCP_GetSockOpt +#define GetSocketEvents TCP_GetSocketEvents +#define Inet_Addr TCP_Inet_Addr +#define Inet_LnaOf TCP_Inet_LnaOf +#define Inet_MakeAddr TCP_Inet_MakeAddr +#define Inet_NetOf TCP_Inet_NetOf +#define Inet_Network TCP_Inet_Network +#define Inet_NtoA(x) TCP_Inet_NtoA((x).s_addr) +#define IoctlSocket TCP_IoctlSocket +#define Listen TCP_Listen +#define ObtainSocket TCP_ObtainSocket +#define Recv TCP_Recv +#define RecvFrom TCP_RecvFrom +#define RecvMsg TCP_RecvMsg +#define ReleaseCopyOfSocket TCP_ReleaseCopyOfSocket +#define ReleaseSocket TCP_ReleaseSocket +#define Send TCP_Send +#define SendMsg TCP_SendMsg +#define SendTo TCP_SendTo +#define SetErrnoPtr TCP_SetErrnoPtr +#define SetSockOpt TCP_SetSockOpt +#define SetSocketSignals TCP_SetSocketSignals +#define ShutDown TCP_ShutDown +#define Socket TCP_Socket +#define SocketBaseTagList TCP_SocketBaseTagList +#define SocketBaseTags TCP_SocketBaseTags +#define SyslogA TCP_SyslogA +#define WaitSelect TCP_WaitSelect +#define Select(n,r,w,e,t) TCP_WaitSelect(n,r,w,e,t,0) +//--------------------------------------------------------------------------// +#endif diff --git a/include/inline/amitcp.h b/include/inline/amitcp.h new file mode 100644 index 0000000..1ee4f30 --- /dev/null +++ b/include/inline/amitcp.h @@ -0,0 +1,203 @@ +/* Automatically generated header! Do not edit! */ + +#ifndef _INLINE_AMITCP_H +#define _INLINE_AMITCP_H + +#ifndef __INLINE_MACROS_H +#include +#endif /* !__INLINE_MACROS_H */ + +#ifndef AMITCP_BASE_NAME +#define AMITCP_BASE_NAME lss->lx_BsdSocketBase +#endif /* !AMITCP_BASE_NAME */ + +#define TCP_Accept(s, addr, addrlen) \ + LP3(0x30, LONG, TCP_Accept, LONG, s, d0, struct sockaddr *, addr, a0, int *, addrlen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_Bind(s, name, namelen) \ + LP3(0x24, LONG, TCP_Bind, LONG, s, d0, const struct sockaddr *, name, a0, LONG, namelen, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_CloseSocket(d) \ + LP1(0x78, LONG, TCP_CloseSocket, LONG, d, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_Connect(s, name, namelen) \ + LP3(0x36, LONG, TCP_Connect, LONG, s, d0, const struct sockaddr *, name, a0, LONG, namelen, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Dup2Socket(fd1, fd2) \ + LP2(0x108, LONG, TCP_Dup2Socket, LONG, fd1, d0, LONG, fd2, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Errno() \ + LP0(0xa2, LONG, TCP_Errno, \ + , AMITCP_BASE_NAME) + +#define TCP_GetDTableSize() \ + LP0(0x8a, LONG, TCP_GetDTableSize, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostByAddr(addr, len, type) \ + LP3(0xd8, struct hostent *, TCP_GetHostByAddr, const UBYTE *, addr, a0, LONG, len, d0, LONG, type, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostByName(name) \ + LP1(0xd2, struct hostent *, TCP_GetHostByName, const UBYTE *, name, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostId() \ + LP0(0x120, ULONG, TCP_GetHostId, \ + , AMITCP_BASE_NAME) + +#define TCP_GetHostName(hostname, size) \ + LP2(0x11a, LONG, TCP_GetHostName, STRPTR, hostname, a0, LONG, size, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetNetByAddr(net, type) \ + LP2(0xe4, struct netent *, TCP_GetNetByAddr, LONG, net, d0, LONG, type, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetNetByName(name) \ + LP1(0xde, struct netent *, TCP_GetNetByName, const UBYTE *, name, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetPeerName(s, hostname, namelen) \ + LP3(0x6c, LONG, TCP_GetPeerName, LONG, s, d0, struct sockaddr *, hostname, a0, int *, namelen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetProtoByName(name) \ + LP1(0xf6, struct protoent *, TCP_GetProtoByName, const UBYTE *, name, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetProtoByNumber(proto) \ + LP1(0xfc, struct protoent *, TCP_GetProtoByNumber, LONG, proto, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetServByName(name, proto) \ + LP2(0xea, struct servent *, TCP_GetServByName, const UBYTE *, name, a0, const UBYTE *, proto, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetServByPort(port, proto) \ + LP2(0xf0, struct servent *, TCP_GetServByPort, LONG, port, d0, const UBYTE *, proto, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_GetSockName(s, hostname, namelen) \ + LP3(0x66, LONG, TCP_GetSockName, LONG, s, d0, struct sockaddr *, hostname, a0, int *, namelen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetSockOpt(s, level, optname, optval, optlen) \ + LP5(0x60, LONG, TCP_GetSockOpt, LONG, s, d0, LONG, level, d1, LONG, optname, d2, void *, optval, a0, int *, optlen, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_GetSocketEvents(eventmaskp) \ + LP1(0x12c, LONG, TCP_GetSocketEvents, ULONG *, eventmaskp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_Addr(cp) \ + LP1(0xb4, ULONG, TCP_Inet_Addr, const UBYTE *, cp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_LnaOf(in) \ + LP1(0xba, ULONG, TCP_Inet_LnaOf, LONG, in, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_MakeAddr(net, host) \ + LP2(0xc6, ULONG, TCP_Inet_MakeAddr, ULONG, net, d0, ULONG, host, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_NetOf(in) \ + LP1(0xc0, ULONG, TCP_Inet_NetOf, LONG, in, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_Network(cp) \ + LP1(0xcc, ULONG, TCP_Inet_Network, const UBYTE *, cp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Inet_NtoA(in) \ + LP1(0xae, char *, TCP_Inet_NtoA, ULONG, in, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_IoctlSocket(d, request, argp) \ + LP3(0x72, LONG, TCP_IoctlSocket, LONG, d, d0, ULONG, request, d1, char *, argp, a0, \ + , AMITCP_BASE_NAME) + +#define TCP_Listen(s, backlog) \ + LP2(0x2a, LONG, TCP_Listen, LONG, s, d0, LONG, backlog, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_ObtainSocket(id, domain, type, protocol) \ + LP4(0x90, LONG, TCP_ObtainSocket, LONG, id, d0, LONG, domain, d1, LONG, type, d2, LONG, protocol, d3, \ + , AMITCP_BASE_NAME) + +#define TCP_Recv(s, buf, len, flags) \ + LP4(0x4e, LONG, TCP_Recv, LONG, s, d0, UBYTE *, buf, a0, LONG, len, d1, LONG, flags, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_RecvFrom(s, buf, len, flags, from, fromlen) \ + LP6(0x48, LONG, TCP_RecvFrom, LONG, s, d0, UBYTE *, buf, a0, LONG, len, d1, LONG, flags, d2, struct sockaddr *, from, a1, int *, fromlen, a2, \ + , AMITCP_BASE_NAME) + +#define TCP_RecvMsg(s, msg, flags) \ + LP3(0x114, LONG, TCP_RecvMsg, LONG, s, d0, struct msghdr *, msg, a0, LONG, flags, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_ReleaseCopyOfSocket(fd, id) \ + LP2(0x9c, LONG, TCP_ReleaseCopyOfSocket, LONG, fd, d0, LONG, id, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_ReleaseSocket(fd, id) \ + LP2(0x96, LONG, TCP_ReleaseSocket, LONG, fd, d0, LONG, id, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Send(s, msg, len, flags) \ + LP4(0x42, LONG, TCP_Send, LONG, s, d0, const UBYTE *, msg, a0, LONG, len, d1, LONG, flags, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_SendMsg(s, msg, flags) \ + LP3(0x10e, LONG, TCP_SendMsg, LONG, s, d0, const struct msghdr *, msg, a0, LONG, flags, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_SendTo(s, msg, len, flags, to, tolen) \ + LP6(0x3c, LONG, TCP_SendTo, LONG, s, d0, const UBYTE *, msg, a0, LONG, len, d1, LONG, flags, d2, const struct sockaddr *, to, a1, LONG, tolen, d3, \ + , AMITCP_BASE_NAME) + +#define TCP_SetErrnoPtr(errno_p, size) \ + LP2(0xa8, LONG, TCP_SetErrnoPtr, void *, errno_p, a0, LONG, size, d0, \ + , AMITCP_BASE_NAME) + +#define TCP_SetSockOpt(s, level, optname, optval, optlen) \ + LP5(0x5a, LONG, TCP_SetSockOpt, LONG, s, d0, LONG, level, d1, LONG, optname, d2, const void *, optval, a0, LONG, optlen, d3, \ + , AMITCP_BASE_NAME) + +#define TCP_SetSocketSignals(SIGINTR, SIGIO, SIGURG) \ + LP3NR(0x84, TCP_SetSocketSignals, ULONG, SIGINTR, d0, ULONG, SIGIO, d1, ULONG, SIGURG, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_ShutDown(s, how) \ + LP2(0x54, LONG, TCP_ShutDown, LONG, s, d0, LONG, how, d1, \ + , AMITCP_BASE_NAME) + +#define TCP_Socket(domain, type, protocol) \ + LP3(0x1e, LONG, TCP_Socket, LONG, domain, d0, LONG, type, d1, LONG, protocol, d2, \ + , AMITCP_BASE_NAME) + +#define TCP_SocketBaseTagList(taglist) \ + LP1(0x126, LONG, TCP_SocketBaseTagList, struct TagItem *, taglist, a0, \ + , AMITCP_BASE_NAME) + +#ifndef NO_INLINE_STDARG +#define TCP_SocketBaseTags(tags...) \ + ({ULONG _tags[] = { tags }; TCP_SocketBaseTagList((struct TagItem *)_tags);}) +#endif + +#define TCP_SyslogA(level, format, ap) \ + LP3NR(0x102, TCP_SyslogA, ULONG, level, d0, const char *, format, a0, va_list, ap, a1, \ + , AMITCP_BASE_NAME) + +#define TCP_WaitSelect(nfds, readfds, writefds, execptfds, timeout, maskp) \ + LP6(0x7e, LONG, TCP_WaitSelect, LONG, nfds, d0, fd_set *, readfds, a0, fd_set *, writefds, a1, fd_set *, execptfds, a2, struct timeval *, timeout, a3, ULONG *, maskp, d1, \ + , AMITCP_BASE_NAME) + +#endif /* !_INLINE_AMITCP_H */ diff --git a/sgetln.c b/sgetln.c new file mode 100644 index 0000000..6f9036a --- /dev/null +++ b/sgetln.c @@ -0,0 +1,31 @@ +/* + * Written by Carsten Larsen. + * Public domain. + */ + +#include "config.h" + +char sgetln_buf[512]; + +char* sgetln(int sd, size_t *len) { + int res; + char in; + char *p; + int count = 0; + + memset(&sgetln_buf, 0, sizeof(sgetln_buf)); + p = (char*)&sgetln_buf; + + while((res = recv(sd, &in, sizeof(char), 0))) { + *p++ = in; + count++; + + if (in == '\n' || count == sizeof(sgetln_buf) - 1) { + *len = count; + return (char*)&sgetln_buf; + } + } + + *len = 0; + return NULL; +} diff --git a/strnstr.c b/strnstr.c new file mode 100644 index 0000000..258578f --- /dev/null +++ b/strnstr.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2001 Mike Barcroft + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)strstr.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +#include +__FBSDID("$FreeBSD$"); +#endif + +#include + +/* + * Find the first occurrence of find in s, where the search is limited to the + * first slen characters of s. + */ +char * +strnstr(const char *s, const char *find, size_t slen) +{ + char c, sc; + size_t len; + + if ((c = *find++) != '\0') { + len = strlen(find); + do { + do { + if (slen-- < 1 || (sc = *s++) == '\0') + return (NULL); + } while (sc != c); + if (len > slen) + return (NULL); + } while (strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} diff --git a/version.h b/version.h new file mode 100644 index 0000000..14f9257 --- /dev/null +++ b/version.h @@ -0,0 +1,103 @@ +/* + * Written by Carsten Larsen. + * Public domain. + */ + +#ifndef WHOIS_VERSION_H +#define WHOIS_VERSION_H + +#include "config.h" + +#define PACKAGE_NAME "whois" +#define PACKAGE_VERSION "1.37" +#define PACKAGE_DATE "28.11.2015" + +#define EMPTYSTRING "" +#define SPACE " " + +// ----------------------------------------------------- +// --------- Processor architecture definitions -------- +// ----------------------------------------------------- + +#ifdef mc68000 +#define ACPU "68000+" +#endif + +#ifdef mc68020 +#ifdef ACPU +#undef ACPU +#endif +#define ACPU "68020" +#endif + +#ifdef mc68030 +#ifdef ACPU +#undef ACPU +#endif +#define ACPU "68030" +#endif + +#ifdef mc68040 +#ifdef ACPU +#undef ACPU +#endif +#define ACPU "68040" +#endif + +#ifdef mc68060 +#ifdef ACPU +#undef ACPU +#endif +#define ACPU "68060" +#endif + +#if defined(INTELCPU) || defined(i386) || defined(i486) || \ + defined(intel) || defined(x86) || defined(i86pc) || \ + defined(__i386__) || defined(_M_IX86) +#ifdef ACPU +#undef ACPU +#endif +#define ACPU "i386" +#endif + +#ifdef __powerpc__ +#define ACPU "PowerPC" +#endif + +#if defined(__x86_64__) +#ifdef ACPU +#undef ACPU +#endif +#define ACPU "amd64" +#endif + +#ifdef WITHTEST +#define ATEST SPACE "TEST" +#else +#define ATEST EMPTYSTRING +#endif + +#if defined(ACPU) && defined(__HAVE_68881__) +#define AFPU SPACE "FPU" +#else +#define AFPU EMPTYSTRING +#endif + +#ifndef ACPU +#define ACPU EMPTYSTRING +#endif + +// ----------------------------------------------------- +// --------- Package version string definition --------- +// ----------------------------------------------------- + +#define PACKAGE_COMMENT ACPU AFPU + +#define PACKAGE_VERSION_STRING \ + "\0$VER:" SPACE \ + PACKAGE_NAME SPACE \ + PACKAGE_VERSION SPACE \ + PACKAGE_DATE SPACE \ + PACKAGE_COMMENT + +#endif diff --git a/wasprint.c b/wasprint.c new file mode 100644 index 0000000..baaf458 --- /dev/null +++ b/wasprint.c @@ -0,0 +1,84 @@ +/* + * Written by Carsten Larsen. + * Public domain. + */ + +#include "config.h" + +void cpy1(char **dest, const char *src) +{ + char *nbuf; + int len = strlen(src); + + if ((nbuf = malloc(len + 1)) == NULL) + err0(1, "malloc"); + + memcpy(nbuf, src, len); + nbuf[len] = '\0'; + + *dest = nbuf; +} + +void cpy2(char **dest, const char *src1, const char *src2) +{ + char *nbuf; + int len = strlen(src1) + strlen(src2); + + if ((nbuf = malloc(len + 1)) == NULL) + err0(1, "malloc"); + + memcpy(nbuf, src1, len); + nbuf[len] = '\0'; + strcat(nbuf, src2); // TODO: Change to fast copy + + *dest = nbuf; +} + +void cpy1pad(char **dest, int minlen, const char *src) +{ + char *nbuf; + int alloclen, pad; + int len = strlen(src); + + if (len < minlen) { + alloclen = minlen; + pad = minlen - len; + } else { + alloclen = len; + pad = 0; + } + + if ((nbuf = malloc(alloclen + 1)) == NULL) + err0(1, "malloc"); + + while (pad-- > 0) { + *nbuf++ = ' '; + } + memcpy(nbuf, src, len); + nbuf[len] = '\0'; + + *dest = nbuf; +} + +/****************************************************************************/ + +#ifdef __AMIGA__ + +int isblank(int c) +{ + return c == '\t' || c == ' ' ; +} + +int isspace(int c) +{ + return c == '\t' || + c == '\r' || + c == '\n' || + c == '\v' || + c == '\f' || + c == ' '; +} + +#endif + +/****************************************************************************/ diff --git a/whois.c b/whois.c new file mode 100644 index 0000000..827ca2f --- /dev/null +++ b/whois.c @@ -0,0 +1,457 @@ +/* $AmigaOS: whois_amiga.c,v 1.37 2015/11/21 18:25:49 Exp $ */ + +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +const char copyright[] = + "@(#) Copyright (c) 1980, 1993\n" + "The Regents of the University of California. All rights reserved.\n"; +const char sccsid[] = + "@(#)whois.c 8.1 (Berkeley) 6/6/93"; + +#include "version.h" +const char *vers = PACKAGE_VERSION_STRING; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ABUSEHOST "whois.abuse.net" +#define NICHOST "whois.crsnic.net" +#define INICHOST "whois.networksolutions.com" +#define GNICHOST "whois.nic.gov" +#define ANICHOST "whois.arin.net" +#define LNICHOST "whois.lacnic.net" +#define KNICHOST "whois.krnic.net" +#define RNICHOST "whois.ripe.net" +#define PNICHOST "whois.apnic.net" +#define MNICHOST "whois.ra.net" +#define QNICHOST_TAIL ".whois-servers.net" +#define BNICHOST "whois.registro.br" +#define NORIDHOST "whois.norid.no" +#define IANAHOST "whois.iana.org" +#define GERMNICHOST "de.whois-servers.net" +#define FNICHOST "whois.afrinic.net" + +#ifdef __AMIGA__ +#define DEFAULT_PORT "whois" +#endif + +#ifdef __AROS__ +#define DEFAULT_PORT "43" +#endif + +#define WHOIS_SERVER_ID "Whois Server: " +#define WHOIS_ORG_SERVER_ID "Registrant Street1:Whois Server:" + +#define WHOIS_RECURSE 0x01 +#define WHOIS_QUICK 0x02 + +#define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-') + +static const char *ip_whois[] = { LNICHOST, RNICHOST, PNICHOST, BNICHOST, + FNICHOST, NULL + }; +static const char *port = DEFAULT_PORT; + +static char *choose_server(char *); +static void usage(void); +static void whois(const char *, const char *, int); + +#ifdef __AMIGA__ +int h_errno = 0; +#endif + +/****************************************************************************/ + +char *progname_storage = NULL; + +const char *getprogname(void) { + return (const char*)progname_storage; +} + +void setprogname(const char *progname) { + if (progname == NULL) { + return; + } + + if (progname_storage != NULL) { + free(progname_storage); + } + + progname_storage = malloc(strlen(progname)); + strcpy(progname_storage, progname); +} + +/****************************************************************************/ + +struct Library *DOSBase = NULL; +struct Library *SocketBase = NULL; + +void close_libs() +{ + if (DOSBase != NULL) { + CloseLibrary(DOSBase); + DOSBase = NULL; + } + + if (SocketBase != NULL) { + CloseLibrary(SocketBase); + SocketBase = NULL; + } + + if (progname_storage != NULL) { + free(progname_storage); + } +} + +int open_libs() +{ + atexit(close_libs); + InitSemaphore(&GetaddrinfoSemaphore); + + if(!(DOSBase = OpenLibrary((STRPTR)DOSLIB_NAME, DOSLIB_REV))) { + warnx2(OPEN_VER_ERROR, DOSLIB_NAME, (void*)DOSLIB_REV); + return 5; + } + + if(!(SocketBase = OpenLibrary((STRPTR)BSDLIB_NAME, BSDLIB_REV))) { + warnx2(OPEN_VER_ERROR, BSDLIB_NAME, (void*)BSDLIB_REV); + return 5; + } else { + SocketBaseTags( + SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (IPTR) &errno, + SBTM_SETVAL(SBTC_HERRNOLONGPTR), (IPTR) &h_errno, + SBTM_SETVAL(SBTC_LOGTAGPTR), (IPTR) &progname_storage, + TAG_DONE ); + } + + return 0; +} + +/****************************************************************************/ + +int +main(int argc, char *argv[]) +{ + const char *country, *host; + char *qnichost; + int ch, flags, use_qnichost; + + if (argc > 0) { + setprogname(argv[0]); + open_libs(); + } else { + return -1; + } + + country = host = qnichost = NULL; + flags = use_qnichost = 0; + while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:QrR6")) != -1) { + switch (ch) { + case 'a': + host = ANICHOST; + break; + case 'A': + host = PNICHOST; + break; + case 'b': + host = ABUSEHOST; + break; + case 'c': + country = optarg; + break; + case 'f': + host = FNICHOST; + break; + case 'g': + host = GNICHOST; + break; + case 'h': + host = optarg; + break; + case 'i': + host = INICHOST; + break; + case 'I': + host = IANAHOST; + break; + case 'k': + host = KNICHOST; + break; + case 'l': + host = LNICHOST; + break; + case 'm': + host = MNICHOST; + break; + case 'p': + port = optarg; + break; + case 'Q': + flags |= WHOIS_QUICK; + break; + case 'r': + host = RNICHOST; + break; + case 'R': + warnx0("-R is deprecated; use '-c ru' instead"); + country = "ru"; + break; + /* Remove in FreeBSD 10 */ + case '6': + errx0(EX_USAGE, "-6 is deprecated; use -[aAflr] instead"); + break; + case '?': + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (!argc || (country != NULL && host != NULL)) + usage(); + + /* + * If no host or country is specified determine the top level domain + * from the query. If the TLD is a number, query ARIN. Otherwise, use + * TLD.whois-server.net. If the domain does not contain '.', fall + * back to NICHOST. + */ + if (host == NULL && country == NULL) { + if ((host = getenv("RA_SERVER")) == NULL) { + use_qnichost = 1; + host = NICHOST; + if (!(flags & WHOIS_QUICK)) + flags |= WHOIS_RECURSE; + } + } + + while (argc-- > 0) { + if (country != NULL) { + cpy2(&qnichost, country, QNICHOST_TAIL); + whois(*argv, qnichost, flags); + } else if (use_qnichost) + if ((qnichost = choose_server(*argv)) != NULL) + whois(*argv, qnichost, flags); + + if (qnichost == NULL) + whois(*argv, host, flags); + + free(qnichost); + qnichost = NULL; + argv++; + } + + exit(0); +} + +/* + * This function will remove any trailing periods from domain, after which it + * returns a pointer to newly allocated memory containing the whois server to + * be queried, or a NULL if the correct server couldn't be determined. The + * caller must remember to free(3) the allocated memory. + */ +static char * +choose_server(char *domain) +{ + char *pos, *retval; + + if (strchr(domain, ':')) { + cpy1(&retval, ANICHOST); + return (retval); + } + + for (pos = strchr(domain, '\0'); pos > domain && *--pos == '.';) + *pos = '\0'; + + if (*domain == '\0') + errx0(EX_USAGE, "can't search for a null string"); + + if (strlen(domain) > sizeof("-NORID")-1 && + strcasecmp(domain + strlen(domain) - sizeof("-NORID") + 1, + "-NORID") == 0) { + cpy1(&retval, NORIDHOST); + return (retval); + } + + while (pos > domain && *pos != '.') + --pos; + + if (pos <= domain) + return (NULL); + + if (isdigit((unsigned char)*++pos)) + cpy1(&retval, ANICHOST); + else + cpy2(&retval, pos, QNICHOST_TAIL); + + return (retval); +} + +static void +whois(const char *query, const char *hostname, int flags) +{ + const short BUFSIZE = 256; + char message[BUFSIZE]; + struct addrinfo *hostres; + char *buf, *host, *nhost, *p, *tbuf; + size_t c, len; + int i, s, error; + const char *reason = NULL; + struct addrinfo hints, *ai; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = 0; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(hostname, port, &hints, &hostres); + if (error) { + warnx2("%s: %s", hostname, gai_strerror(error)); + return; + } + + for (s = -1, ai = hostres; ai != NULL; ai = ai->ai_next) { + s = Socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s < 0) { + error = errno; + reason = "socket"; + continue; + } + if (Connect(s, ai->ai_addr, ai->ai_addrlen) < 0) { + error = errno; + reason = "connect"; + CloseSocket(s); + s = -1; + continue; + } + break; + } + + if (s < 0) { + if (reason) { + errno = error; + warn2("%s: %s", hostname, reason); + } else { + warnx0("Unknown error in connection attempt"); + } + freeaddrinfo(hostres); + return; + } + + if (strcmp(hostname, GERMNICHOST) == 0) { + snprintf(message, BUFSIZE, "-T dn,ace -C US-ASCII %s\r\n", query); + } else if (strcmp(hostname, "dk" QNICHOST_TAIL) == 0) { + snprintf(message, BUFSIZE, "--show-handles %s\r\n", query); + } else if (isdigit(query[0])) { + snprintf(message, BUFSIZE, "n + %s\r\n", query); + } else { + snprintf(message, BUFSIZE, "%s\r\n", query); + } + + if(Send(s, message, strlen(message), 0) < 0) { + err0(1, "send failed"); + } + + nhost = NULL; + while ((buf = sgetln(s, &len)) != NULL) { + + while (len > 0 && isspace(buf[len - 1])) + buf[--len] = '\0'; + + cpy1pad(&tbuf, len, buf); + printf("%s\n", tbuf); + free(tbuf); + + if ((flags & WHOIS_RECURSE) && nhost == NULL) { + host = strnstr(buf, WHOIS_SERVER_ID, len); + if (host != NULL) { + host += sizeof(WHOIS_SERVER_ID) - 1; + for (p = host; p < buf + len; p++) { + if (!ishost(*p)) { + *p = '\0'; + break; + } + } + cpy1pad(&nhost, (int)(buf + len - host), host); + } else if ((host = + strnstr(buf, WHOIS_ORG_SERVER_ID, len)) != NULL) { + host += sizeof(WHOIS_ORG_SERVER_ID) - 1; + for (p = host; p < buf + len; p++) { + if (!ishost(*p)) { + *p = '\0'; + break; + } + } + cpy1pad(&nhost, (int)(buf + len - host), host); + } else if (strcmp(hostname, ANICHOST) == 0) { + for (c = 0; c <= len; c++) + buf[c] = tolower((unsigned char)buf[c]); + for (i = 0; ip_whois[i] != NULL; i++) { + if (strnstr(buf, ip_whois[i], len) != + NULL) { + cpy1(&nhost, ip_whois[i]); + break; + } + } + } + } + } + + CloseSocket(s); + + if (nhost != NULL) { + whois(query, nhost, 0); + free(nhost); + } +} + +static void +usage(void) +{ + fprintf(stderr, + "usage: whois [-aAbfgiIklmQrR6] [-c country-code | -h hostname] " + "[-p port] name ...\n"); + exit(EX_USAGE); +} diff --git a/whois_freebsd.c b/whois_freebsd.c new file mode 100644 index 0000000..58f50dc --- /dev/null +++ b/whois_freebsd.c @@ -0,0 +1,487 @@ +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)whois.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ABUSEHOST "whois.abuse.net" +#define NICHOST "whois.crsnic.net" +#define INICHOST "whois.networksolutions.com" +#define GNICHOST "whois.nic.gov" +#define ANICHOST "whois.arin.net" +#define LNICHOST "whois.lacnic.net" +#define KNICHOST "whois.krnic.net" +#define RNICHOST "whois.ripe.net" +#define PNICHOST "whois.apnic.net" +#define MNICHOST "whois.ra.net" +#define QNICHOST_TAIL ".whois-servers.net" +#define BNICHOST "whois.registro.br" +#define NORIDHOST "whois.norid.no" +#define IANAHOST "whois.iana.org" +#define GERMNICHOST "de.whois-servers.net" +#define FNICHOST "whois.afrinic.net" +#define DEFAULT_PORT "whois" +#define WHOIS_SERVER_ID "Whois Server: " +#define WHOIS_ORG_SERVER_ID "Registrant Street1:Whois Server:" + +#define WHOIS_RECURSE 0x01 +#define WHOIS_QUICK 0x02 + +#define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-') + +static const char *ip_whois[] = { LNICHOST, RNICHOST, PNICHOST, BNICHOST, + FNICHOST, NULL }; +static const char *port = DEFAULT_PORT; + +static char *choose_server(char *); +static struct addrinfo *gethostinfo(char const *host, int exit_on_error); +static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3); +static void usage(void); +static void whois(const char *, const char *, int); + +int +main(int argc, char *argv[]) +{ + const char *country, *host; + char *qnichost; + int ch, flags, use_qnichost; + +#ifdef SOCKS + SOCKSinit(argv[0]); +#endif + + country = host = qnichost = NULL; + flags = use_qnichost = 0; + while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:QrR6")) != -1) { + switch (ch) { + case 'a': + host = ANICHOST; + break; + case 'A': + host = PNICHOST; + break; + case 'b': + host = ABUSEHOST; + break; + case 'c': + country = optarg; + break; + case 'f': + host = FNICHOST; + break; + case 'g': + host = GNICHOST; + break; + case 'h': + host = optarg; + break; + case 'i': + host = INICHOST; + break; + case 'I': + host = IANAHOST; + break; + case 'k': + host = KNICHOST; + break; + case 'l': + host = LNICHOST; + break; + case 'm': + host = MNICHOST; + break; + case 'p': + port = optarg; + break; + case 'Q': + flags |= WHOIS_QUICK; + break; + case 'r': + host = RNICHOST; + break; + case 'R': + warnx("-R is deprecated; use '-c ru' instead"); + country = "ru"; + break; + /* Remove in FreeBSD 10 */ + case '6': + errx(EX_USAGE, + "-6 is deprecated; use -[aAflr] instead"); + break; + case '?': + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (!argc || (country != NULL && host != NULL)) + usage(); + + /* + * If no host or country is specified determine the top level domain + * from the query. If the TLD is a number, query ARIN. Otherwise, use + * TLD.whois-server.net. If the domain does not contain '.', fall + * back to NICHOST. + */ + if (host == NULL && country == NULL) { + if ((host = getenv("RA_SERVER")) == NULL) { + use_qnichost = 1; + host = NICHOST; + if (!(flags & WHOIS_QUICK)) + flags |= WHOIS_RECURSE; + } + } + while (argc-- > 0) { + if (country != NULL) { + s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL); + whois(*argv, qnichost, flags); + } else if (use_qnichost) + if ((qnichost = choose_server(*argv)) != NULL) + whois(*argv, qnichost, flags); + if (qnichost == NULL) + whois(*argv, host, flags); + free(qnichost); + qnichost = NULL; + argv++; + } + exit(0); +} + +/* + * This function will remove any trailing periods from domain, after which it + * returns a pointer to newly allocated memory containing the whois server to + * be queried, or a NULL if the correct server couldn't be determined. The + * caller must remember to free(3) the allocated memory. + */ +static char * +choose_server(char *domain) +{ + char *pos, *retval; + + if (strchr(domain, ':')) { + s_asprintf(&retval, "%s", ANICHOST); + return (retval); + } + for (pos = strchr(domain, '\0'); pos > domain && *--pos == '.';) + *pos = '\0'; + if (*domain == '\0') + errx(EX_USAGE, "can't search for a null string"); + if (strlen(domain) > sizeof("-NORID")-1 && + strcasecmp(domain + strlen(domain) - sizeof("-NORID") + 1, + "-NORID") == 0) { + s_asprintf(&retval, "%s", NORIDHOST); + return (retval); + } + while (pos > domain && *pos != '.') + --pos; + if (pos <= domain) + return (NULL); + if (isdigit((unsigned char)*++pos)) + s_asprintf(&retval, "%s", ANICHOST); + else + s_asprintf(&retval, "%s%s", pos, QNICHOST_TAIL); + return (retval); +} + +static struct addrinfo * +gethostinfo(char const *host, int exit_on_error) +{ + struct addrinfo hints, *res; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = 0; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(host, port, &hints, &res); + if (error) { + warnx("%s: %s", host, gai_strerror(error)); + if (exit_on_error) + exit(EX_NOHOST); + return (NULL); + } + return (res); +} + +/* + * Wrapper for asprintf(3) that exits on error. + */ +static void +s_asprintf(char **ret, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + if (vasprintf(ret, format, ap) == -1) { + va_end(ap); + err(EX_OSERR, "vasprintf()"); + } + va_end(ap); +} + +static void +whois(const char *query, const char *hostname, int flags) +{ + FILE *sfi, *sfo; + struct addrinfo *hostres, *res; + char *buf, *host, *nhost, *p; + int s = -1, f; + nfds_t i, j; + size_t c, len, count; + struct pollfd *fds; + int timeout = 180; + + hostres = gethostinfo(hostname, 1); + for (res = hostres, count = 0; res; res = res->ai_next) + count++; + + fds = calloc(count, sizeof(*fds)); + if (fds == NULL) + err(EX_OSERR, "calloc()"); + + /* + * Traverse the result list elements and make non-block + * connection attempts. + */ + count = i = 0; + for (res = hostres; res != NULL; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK, + res->ai_protocol); + if (s < 0) + continue; + if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { + if (errno == EINPROGRESS) { + /* Add the socket to poll list */ + fds[i].fd = s; + fds[i].events = POLLERR | POLLHUP | + POLLIN | POLLOUT; + count++; + i++; + } else { + close(s); + s = -1; + + /* + * Poll only if we have something to poll, + * otherwise just go ahead and try next + * address + */ + if (count == 0) + continue; + } + } else + goto done; + + /* + * If we are at the last address, poll until a connection is + * established or we failed all connection attempts. + */ + if (res->ai_next == NULL) + timeout = INFTIM; + + /* + * Poll the watched descriptors for successful connections: + * if we still have more untried resolved addresses, poll only + * once; otherwise, poll until all descriptors have errors, + * which will be considered as ETIMEDOUT later. + */ + do { + int n; + + n = poll(fds, i, timeout); + if (n == 0) { + /* + * No event reported in time. Try with a + * smaller timeout (but cap at 2-3ms) + * after a new host have been added. + */ + if (timeout >= 3) + timeout <<= 1; + + break; + } else if (n < 0) { + /* + * errno here can only be EINTR which we would want + * to clean up and bail out. + */ + s = -1; + goto done; + } + + /* + * Check for the event(s) we have seen. + */ + for (j = 0; j < i; j++) { + if (fds[j].fd == -1 || fds[j].events == 0 || + fds[j].revents == 0) + continue; + if (fds[j].revents & ~(POLLIN | POLLOUT)) { + close(s); + fds[j].fd = -1; + fds[j].events = 0; + count--; + continue; + } else if (fds[j].revents & (POLLIN | POLLOUT)) { + /* Connect succeeded. */ + s = fds[j].fd; + + goto done; + } + + } + } while (timeout == INFTIM && count != 0); + } + + /* All attempts were failed */ + s = -1; + if (count == 0) + errno = ETIMEDOUT; + +done: + /* Close all watched fds except the succeeded one */ + for (j = 0; j < i; j++) + if (fds[j].fd != s && fds[j].fd != -1) + close(fds[j].fd); + + if (s != -1) { + /* Restore default blocking behavior. */ + if ((f = fcntl(s, F_GETFL)) != -1) { + f &= ~O_NONBLOCK; + if (fcntl(s, F_SETFL, f) == -1) + err(EX_OSERR, "fcntl()"); + } else + err(EX_OSERR, "fcntl()"); + } + + free(fds); + freeaddrinfo(hostres); + if (s == -1) + err(EX_OSERR, "connect()"); + + sfi = fdopen(s, "r"); + sfo = fdopen(s, "w"); + if (sfi == NULL || sfo == NULL) + err(EX_OSERR, "fdopen()"); + if (strcmp(hostname, GERMNICHOST) == 0) { + fprintf(sfo, "-T dn,ace -C US-ASCII %s\r\n", query); + } else if (strcmp(hostname, "dk" QNICHOST_TAIL) == 0) { + fprintf(sfo, "--show-handles %s\r\n", query); + } else { + fprintf(sfo, "%s\r\n", query); + } + fflush(sfo); + nhost = NULL; + while ((buf = fgetln(sfi, &len)) != NULL) { + while (len > 0 && isspace((unsigned char)buf[len - 1])) + buf[--len] = '\0'; + printf("%.*s\n", (int)len, buf); + + if ((flags & WHOIS_RECURSE) && nhost == NULL) { + host = strnstr(buf, WHOIS_SERVER_ID, len); + if (host != NULL) { + host += sizeof(WHOIS_SERVER_ID) - 1; + for (p = host; p < buf + len; p++) { + if (!ishost(*p)) { + *p = '\0'; + break; + } + } + s_asprintf(&nhost, "%.*s", + (int)(buf + len - host), host); + } else if ((host = + strnstr(buf, WHOIS_ORG_SERVER_ID, len)) != NULL) { + host += sizeof(WHOIS_ORG_SERVER_ID) - 1; + for (p = host; p < buf + len; p++) { + if (!ishost(*p)) { + *p = '\0'; + break; + } + } + s_asprintf(&nhost, "%.*s", + (int)(buf + len - host), host); + } else if (strcmp(hostname, ANICHOST) == 0) { + for (c = 0; c <= len; c++) + buf[c] = tolower((unsigned char)buf[c]); + for (i = 0; ip_whois[i] != NULL; i++) { + if (strnstr(buf, ip_whois[i], len) != + NULL) { + s_asprintf(&nhost, "%s", + ip_whois[i]); + break; + } + } + } + } + } + if (nhost != NULL) { + whois(query, nhost, 0); + free(nhost); + } +} + +static void +usage(void) +{ + fprintf(stderr, + "usage: whois [-aAbfgiIklmQrR6] [-c country-code | -h hostname] " + "[-p port] name ...\n"); + exit(EX_USAGE); +} diff --git a/whois_netbsd.c b/whois_netbsd.c new file mode 100644 index 0000000..0dd48f6 --- /dev/null +++ b/whois_netbsd.c @@ -0,0 +1,329 @@ +/* $NetBSD: whois.c,v 1.36 2013/02/20 09:27:52 ws Exp $ */ +/* $OpenBSD: whois.c,v 1.28 2003/09/18 22:16:15 fgsch Exp $ */ + +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1980, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static const char sccsid[] = "@(#)whois.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: whois.c,v 1.36 2013/02/20 09:27:52 ws Exp $"); +#endif +#endif /* not lint */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define ANICHOST "whois.arin.net" +#define BNICHOST "whois.registro.br" +#define CNICHOST "whois.corenic.net" +#define DNICHOST "whois.nic.mil" +#define FNICHOST "whois.afrinic.net" +#define GNICHOST "whois.nic.gov" +#define INICHOST "whois.networksolutions.com" +#define LNICHOST "whois.lacnic.net" +#define MNICHOST "whois.ra.net" +#define NICHOST "whois.crsnic.net" +#define PNICHOST "whois.apnic.net" +#define QNICHOST_TAIL ".whois-servers.net" +#define RNICHOST "whois.ripe.net" +#define RUNICHOST "whois.ripn.net" +#define SNICHOST "whois.6bone.net" + +#define WHOIS_PORT "whois" +#define WHOIS_SERVER_ID "Whois Server:" + +#define WHOIS_RECURSE 0x01 +#define WHOIS_QUICK 0x02 + +static const char *port_whois = WHOIS_PORT; +static const char *ip_whois[] = + { LNICHOST, RNICHOST, PNICHOST, FNICHOST, BNICHOST, NULL }; + +static void usage(void) __dead; +static int whois(const char *, const char *, const char *, int); +static const char *choose_server(const char *, const char *); + +int +main(int argc, char *argv[]) +{ + int ch, flags, rval; + const char *host, *name, *country; + +#ifdef SOCKS + SOCKSinit(argv[0]); +#endif + country = host = NULL; + flags = rval = 0; + while ((ch = getopt(argc, argv, "6Aac:dfgh:ilmp:qQRr")) != -1) + switch(ch) { + case 'a': + host = ANICHOST; + break; + case 'A': + host = PNICHOST; + break; + case 'c': + country = optarg; + break; + case 'd': + host = DNICHOST; + break; + case 'f': + host = FNICHOST; + break; + case 'g': + host = GNICHOST; + break; + case 'h': + host = optarg; + break; + case 'i': + host = INICHOST; + break; + case 'l': + host = LNICHOST; + break; + case 'm': + host = MNICHOST; + break; + case 'p': + port_whois = optarg; + break; + case 'q': + /* deprecated, now the default */ + break; + case 'Q': + flags |= WHOIS_QUICK; + break; + case 'r': + host = RNICHOST; + break; + case 'R': + host = RUNICHOST; + break; + case '6': + host = SNICHOST; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (!argc || (country != NULL && host != NULL)) + usage(); + + if (host == NULL && country == NULL && !(flags & WHOIS_QUICK)) + flags |= WHOIS_RECURSE; + for (name = *argv; (name = *argv) != NULL; argv++) + rval += whois(name, host ? host : choose_server(name, country), + port_whois, flags); + return rval; +} + +static int +whois(const char *query, const char *server, const char *port, int flags) +{ + FILE *sfi, *sfo; + char *buf, *p, *nhost, *nbuf = NULL; + size_t len; + int i, s, error; + const char *reason = NULL, *fmt; + struct addrinfo hints, *res, *ai; + + (void)memset(&hints, 0, sizeof(hints)); + hints.ai_flags = 0; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(server, port, &hints, &res); + if (error) { + warnx("%s: %s", server, gai_strerror(error)); + return (1); + } + + for (s = -1, ai = res; ai != NULL; ai = ai->ai_next) { + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s < 0) { + error = errno; + reason = "socket"; + continue; + } + if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) { + error = errno; + reason = "connect"; + close(s); + s = -1; + continue; + } + break; /*okay*/ + } + if (s < 0) { + if (reason) { + errno = error; + warn("%s: %s", server, reason); + } else + warnx("Unknown error in connection attempt"); + freeaddrinfo(res); + return (1); + } + + if (strcmp(server, "whois.denic.de") == 0 || + strcmp(server, "de.whois-servers.net") == 0) + fmt = "-T dn,ace -C ISO-8859-1 "; + else + fmt = ""; + + sfi = fdopen(s, "r"); + sfo = fdopen(s, "w"); + if (sfi == NULL || sfo == NULL) + err(1, "fdopen"); + (void)fprintf(sfo, "%s%s\r\n", fmt, query); + (void)fflush(sfo); + nhost = NULL; + while ((buf = fgetln(sfi, &len)) != NULL) { + p = buf + len - 1; + if (isspace((unsigned char)*p)) { + do + *p = '\0'; + while (p > buf && isspace((unsigned char)*--p)); + } else { + if ((nbuf = malloc(len + 1)) == NULL) + err(1, "malloc"); + (void)memcpy(nbuf, buf, len); + nbuf[len] = '\0'; + buf = nbuf; + } + (void)puts(buf); + + if (nhost != NULL || !(flags & WHOIS_RECURSE)) + continue; + + if ((p = strstr(buf, WHOIS_SERVER_ID))) { + p += sizeof(WHOIS_SERVER_ID) - 1; + while (isblank((unsigned char)*p)) + p++; + if ((len = strcspn(p, " \t\n\r"))) { + if ((nhost = malloc(len + 1)) == NULL) + err(1, "malloc"); + (void)memcpy(nhost, p, len); + nhost[len] = '\0'; + } + } else if (strcmp(server, ANICHOST) == 0) { + for (p = buf; *p != '\0'; p++) + *p = tolower((unsigned char)*p); + for (i = 0; ip_whois[i] != NULL; i++) { + if (strstr(buf, ip_whois[i]) != NULL) { + nhost = strdup(ip_whois[i]); + if (nhost == NULL) + err(1, "strdup"); + break; + } + } + } + } + if (nbuf != NULL) + free(nbuf); + + if (nhost != NULL) { + error = whois(query, nhost, port, 0); + free(nhost); + } + freeaddrinfo(res); + (void)fclose(sfi); + (void)fclose(sfo); + return (error); +} + +/* + * If no country is specified determine the top level domain from the query. + * If the TLD is a number, query ARIN, otherwise, use TLD.whois-server.net. + * If the domain does not contain '.', check to see if it is an NSI handle + * (starts with '!') or a CORE handle (COCO-[0-9]+ or COHO-[0-9]+). + * Fall back to NICHOST for the non-handle case. + */ +static const char * +choose_server(const char *name, const char *country) +{ + static char *server; + char *nserver; + const char *qhead; + char *ep; + size_t len; + + if (country != NULL) + qhead = country; + else if ((qhead = strrchr(name, '.')) == NULL) { + if (*name == '!') + return (INICHOST); + else if ((strncasecmp(name, "COCO-", 5) == 0 || + strncasecmp(name, "COHO-", 5) == 0) && + strtol(name + 5, &ep, 10) > 0 && *ep == '\0') + return (CNICHOST); + else + return (NICHOST); + } else if (isdigit((unsigned char)*(++qhead))) + return (ANICHOST); + len = strlen(qhead) + sizeof(QNICHOST_TAIL); + if ((nserver = realloc(server, len)) == NULL) + err(1, "realloc"); + server = nserver; + (void)strlcpy(server, qhead, len); + (void)strlcat(server, QNICHOST_TAIL, len); + return (server); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: %s [-6AadgilmQRr] [-c country-code | -h hostname] " + "[-p port] name ...\n", getprogname()); + exit(1); +} diff --git a/workman.sh b/workman.sh new file mode 100644 index 0000000..1ef4536 --- /dev/null +++ b/workman.sh @@ -0,0 +1,37 @@ +#! /bin/sh + +# This file is in the public domain, so clarified as of +# 2009-05-17 by Arthur David Olson. + +# Modified by Carsten Larsen + +# Tell groff not to emit SGR escape sequences (ANSI color escapes). +GROFF_NO_SGR=1 +export GROFF_NO_SGR + +#GROFF_SGR=1 +#export GROFF_SGR + +echo ".am TH +.hy 0 +.na +.. +.rm }H +.rm }F" | nroff -Tascii -man - ${1+"$@"} | perl -ne ' + binmode STDIN, '\'':encoding(ascii)'\''; + binmode STDOUT, '\'':encoding(iso-8859-15)'\''; + chomp; + s/.\010//g; + s/\s*$//; + if (/^$/) { + $sawblank = 1; + next; + } else { + if ($sawblank && $didprint) { + print "\n"; + $sawblank = 0; + } + print "$_\n"; + $didprint = 1; + } +'