diff options
Diffstat (limited to 'gettext-tools/src/hostname.c')
-rw-r--r-- | gettext-tools/src/hostname.c | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/gettext-tools/src/hostname.c b/gettext-tools/src/hostname.c new file mode 100644 index 0000000..a7032b3 --- /dev/null +++ b/gettext-tools/src/hostname.c @@ -0,0 +1,389 @@ +/* Display hostname in various forms. + Copyright (C) 2001-2003, 2006-2007, 2012 Free Software Foundation, Inc. + Written by Bruno Haible <haible@clisp.cons.org>, 2001. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <errno.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> + +#if defined _WIN32 || defined __WIN32__ +# define WIN32_NATIVE +#endif + +/* Get gethostname(). */ +#include <unistd.h> + +#ifdef WIN32_NATIVE +/* Native Woe32 API lacks gethostname() but has GetComputerName() instead. */ +# include <windows.h> +#else +/* Some systems, like early Solaris versions, lack gethostname() but + have uname() instead. */ +# if !HAVE_GETHOSTNAME +# include <sys/utsname.h> +# endif +#endif + +/* Get MAXHOSTNAMELEN. */ +#if HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 64 +#endif + +/* Support for using gethostbyname(). */ +#if HAVE_GETHOSTBYNAME +# include <sys/types.h> +# include <sys/socket.h> /* defines AF_INET, AF_INET6 */ +# include <netinet/in.h> /* declares ntohs(), defines struct sockaddr_in */ +# if HAVE_ARPA_INET_H +# include <arpa/inet.h> /* declares inet_ntoa(), inet_ntop() */ +# endif +# if HAVE_IPV6 +# if !defined(__CYGWIN__) /* Cygwin has only s6_addr, no s6_addr16 */ +# if defined(__APPLE__) && defined(__MACH__) /* MacOS X */ +# define in6_u __u6_addr +# define u6_addr16 __u6_addr16 +# endif + /* Use s6_addr16 for portability. See RFC 2553. */ +# ifndef s6_addr16 +# define s6_addr16 in6_u.u6_addr16 +# endif +# define HAVE_IN6_S6_ADDR16 1 +# endif +# endif +# include <netdb.h> /* defines struct hostent, declares gethostbyname() */ +#endif + +/* Include this after <sys/socket.h>, to avoid a syntax error on BeOS. */ +#include <stdbool.h> + +#include "closeout.h" +#include "error.h" +#include "error-progname.h" +#include "progname.h" +#include "relocatable.h" +#include "basename.h" +#include "xalloc.h" +#include "propername.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +/* Output format. */ +static enum { default_format, short_format, long_format, ip_format } format; + +/* Long options. */ +static const struct option long_options[] = +{ + { "fqdn", no_argument, NULL, 'f' }, + { "help", no_argument, NULL, 'h' }, + { "ip-address", no_argument, NULL, 'i' }, + { "long", no_argument, NULL, 'f' }, + { "short", no_argument, NULL, 's' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, NULL, 0 } +}; + + +/* Forward declaration of local functions. */ +static void usage (int status) +#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2) + __attribute__ ((noreturn)) +#endif +; +static void print_hostname (void); + +int +main (int argc, char *argv[]) +{ + int optchar; + bool do_help; + bool do_version; + + /* Set program name for messages. */ + set_program_name (argv[0]); + error_print_progname = maybe_print_progname; + +#ifdef HAVE_SETLOCALE + /* Set locale via LC_ALL. */ + setlocale (LC_ALL, ""); +#endif + + /* Set the text message domain. */ + bindtextdomain (PACKAGE, relocate (LOCALEDIR)); + textdomain (PACKAGE); + + /* Ensure that write errors on stdout are detected. */ + atexit (close_stdout); + + /* Set default values for variables. */ + do_help = false; + do_version = false; + format = default_format; + + /* Parse command line options. */ + while ((optchar = getopt_long (argc, argv, "fhisV", long_options, NULL)) + != EOF) + switch (optchar) + { + case '\0': /* Long option. */ + break; + case 'f': + format = long_format; + break; + case 's': + format = short_format; + break; + case 'i': + format = ip_format; + break; + case 'h': + do_help = true; + break; + case 'V': + do_version = true; + break; + default: + usage (EXIT_FAILURE); + /* NOTREACHED */ + } + + /* Version information requested. */ + if (do_version) + { + printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION); + /* xgettext: no-wrap */ + printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\ +License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\ +This is free software: you are free to change and redistribute it.\n\ +There is NO WARRANTY, to the extent permitted by law.\n\ +"), + "2001-2003, 2006-2007"); + printf (_("Written by %s.\n"), proper_name ("Bruno Haible")); + exit (EXIT_SUCCESS); + } + + /* Help is requested. */ + if (do_help) + usage (EXIT_SUCCESS); + + /* Test for extraneous arguments. */ + if (optind != argc) + error (EXIT_FAILURE, 0, _("too many arguments")); + + /* Get and print the hostname. */ + print_hostname (); + + exit (EXIT_SUCCESS); +} + +/* Display usage information and exit. */ +static void +usage (int status) +{ + if (status != EXIT_SUCCESS) + fprintf (stderr, _("Try '%s --help' for more information.\n"), + program_name); + else + { + printf (_("\ +Usage: %s [OPTION]\n\ +"), program_name); + printf ("\n"); + printf (_("\ +Print the machine's hostname.\n")); + printf ("\n"); + printf (_("\ +Output format:\n")); + printf (_("\ + -s, --short short host name\n")); + printf (_("\ + -f, --fqdn, --long long host name, includes fully qualified domain\n\ + name, and aliases\n")); + printf (_("\ + -i, --ip-address addresses for the hostname\n")); + printf ("\n"); + printf (_("\ +Informative output:\n")); + printf (_("\ + -h, --help display this help and exit\n")); + printf (_("\ + -V, --version output version information and exit\n")); + printf ("\n"); + /* TRANSLATORS: The placeholder indicates the bug-reporting address + for this package. Please add _another line_ saying + "Report translation bugs to <...>\n" with the address for translation + bugs (typically your translation team's web or email address). */ + fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), + stdout); + } + + exit (status); +} + +/* Returns an xmalloc()ed string containing the machine's host name. */ +static char * +xgethostname () +{ +#ifdef WIN32_NATIVE + char hostname[MAX_COMPUTERNAME_LENGTH+1]; + DWORD size = sizeof (hostname); + + if (!GetComputerName (hostname, &size)) + error (EXIT_FAILURE, 0, _("could not get host name")); + return xstrdup (hostname); +#elif HAVE_GETHOSTNAME + char hostname[MAXHOSTNAMELEN+1]; + + if (gethostname (hostname, MAXHOSTNAMELEN) < 0) + error (EXIT_FAILURE, errno, _("could not get host name")); + hostname[MAXHOSTNAMELEN] = '\0'; + return xstrdup (hostname); +#else + struct utsname utsname; + + if (uname (&utsname) < 0) + error (EXIT_FAILURE, errno, _("could not get host name")); + return xstrdup (utsname.nodename); +#endif +} + +/* Converts an AF_INET address to a printable, presentable format. + BUFFER is an array with at least 15+1 bytes. ADDR is 'struct in_addr'. */ +#if HAVE_INET_NTOP +# define ipv4_ntop(buffer,addr) \ + inet_ntop (AF_INET, &addr, buffer, 15+1) +#else +# define ipv4_ntop(buffer,addr) \ + strcpy (buffer, inet_ntoa (addr)) +#endif + +#if HAVE_IPV6 +/* Converts an AF_INET6 address to a printable, presentable format. + BUFFER is an array with at least 45+1 bytes. ADDR is 'struct in6_addr'. */ +# if HAVE_INET_NTOP +# define ipv6_ntop(buffer,addr) \ + inet_ntop (AF_INET6, &addr, buffer, 45+1) +# elif HAVE_IN6_S6_ADDR16 +# define ipv6_ntop(buffer,addr) \ + sprintf (buffer, "%x:%x:%x:%x:%x:%x:%x:%x", \ + ntohs ((addr).s6_addr16[0]), \ + ntohs ((addr).s6_addr16[1]), \ + ntohs ((addr).s6_addr16[2]), \ + ntohs ((addr).s6_addr16[3]), \ + ntohs ((addr).s6_addr16[4]), \ + ntohs ((addr).s6_addr16[5]), \ + ntohs ((addr).s6_addr16[6]), \ + ntohs ((addr).s6_addr16[7])) +# else +# define ipv6_ntop(buffer,addr) \ + sprintf (buffer, "%x:%x:%x:%x:%x:%x:%x:%x", \ + ((addr).s6_addr[0] << 8) | (addr).s6_addr[1], \ + ((addr).s6_addr[2] << 8) | (addr).s6_addr[3], \ + ((addr).s6_addr[4] << 8) | (addr).s6_addr[5], \ + ((addr).s6_addr[6] << 8) | (addr).s6_addr[7], \ + ((addr).s6_addr[8] << 8) | (addr).s6_addr[9], \ + ((addr).s6_addr[10] << 8) | (addr).s6_addr[11], \ + ((addr).s6_addr[12] << 8) | (addr).s6_addr[13], \ + ((addr).s6_addr[14] << 8) | (addr).s6_addr[15]) +# endif +#endif + +/* Print the hostname according to the specified format. */ +static void +print_hostname () +{ + char *hostname; + char *dot; +#if HAVE_GETHOSTBYNAME + struct hostent *h; + size_t i; +#endif + + hostname = xgethostname (); + + switch (format) + { + case default_format: + /* Print the hostname, as returned by the system call. */ + printf ("%s\n", hostname); + break; + + case short_format: + /* Print only the part before the first dot. */ + dot = strchr (hostname, '.'); + if (dot != NULL) + *dot = '\0'; + printf ("%s\n", hostname); + break; + + case long_format: + /* Look for netwide usable hostname and aliases using gethostbyname(). */ +#if HAVE_GETHOSTBYNAME + h = gethostbyname (hostname); + if (h != NULL) + { + printf ("%s\n", h->h_name); + if (h->h_aliases != NULL) + for (i = 0; h->h_aliases[i] != NULL; i++) + printf ("%s\n", h->h_aliases[i]); + } + else +#endif + printf ("%s\n", hostname); + break; + + case ip_format: + /* Look for netwide usable IP addresses using gethostbyname(). */ +#if HAVE_GETHOSTBYNAME + h = gethostbyname (hostname); + if (h != NULL && h->h_addr_list != NULL) + for (i = 0; h->h_addr_list[i] != NULL; i++) + { +#if HAVE_IPV6 + if (h->h_addrtype == AF_INET6) + { + char buffer[45+1]; + ipv6_ntop (buffer, *(const struct in6_addr*) h->h_addr_list[i]); + printf("[%s]\n", buffer); + } + else +#endif + if (h->h_addrtype == AF_INET) + { + char buffer[15+1]; + ipv4_ntop (buffer, *(const struct in_addr*) h->h_addr_list[i]); + printf("[%s]\n", buffer); + } + } +#endif + break; + + default: + abort (); + } +} |