Jim Meyering wrote: > > Jim, maybe it would be an idea to merge this program with the 'hostname' > > from coreutils. What's your stand on it? > > Good idea. > I'd welcome the addition.
That means that you want me to do the work, I guess? OK, here's the program, consisting of - a patch to lib/gethostname.c to add Woe32 support, - a new src/hostname.c, - some autoconf macros that you can add to configure.ac or where it fits. If that's OK, I can also go out and write the documentation update. 2004-01-18 Bruno Haible <[EMAIL PROTECTED]> * gethostname.c: Add support for Windows. Include <string.h>. (gethostname): On Windows, use GetComputerName(). 2004-01-18 Bruno Haible <[EMAIL PROTECTED]> * hostname.c: Include getopt.h, not long-options.h. Include headers for using IPv6. Include xgethostname.h. (xgethostname): Remove declaration. (AUTHORS): Add me. (format): New variable. (ipv4_ntop, ipv6_ntop): New macros. (print_hostname): New function. (sethostname): Provide a fallback definition that just signals an error. (long_options): New variable. (usage): Document new options -s, -f, -i, -h, -V. (main): Use getopt_long instead of parse_long_options. Initialize 'format'. Invoke print_hostname.
*** lib/gethostname.c.bak Sun Jan 18 18:09:50 2004 --- lib/gethostname.c Sun Jan 18 17:06:04 2004 *************** *** 1,5 **** /* gethostname emulation for SysV and POSIX.1. ! Copyright (C) 1992, 2003 Free Software Foundation, Inc. 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 --- 1,5 ---- /* gethostname emulation for SysV and POSIX.1. ! Copyright (C) 1992, 2003-2004 Free Software Foundation, Inc. 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 *************** *** 21,40 **** # include <config.h> #endif ! #ifdef HAVE_UNAME ! # include <sys/utsname.h> #endif /* Put up to LEN chars of the host name into NAME. Null terminate it if the name is shorter than LEN. Return 0 if ok, -1 if error. */ - #include <stddef.h> - int gethostname (char *name, size_t len) { ! #ifdef HAVE_UNAME struct utsname uts; if (uname (&uts) == -1) --- 21,90 ---- # include <config.h> #endif ! #if defined _WIN32 || defined __WIN32__ ! # undef WIN32 /* avoid warning on mingw32 */ ! # define WIN32 #endif + #ifdef WIN32 + /* 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. */ + # ifdef HAVE_UNAME + # include <sys/utsname.h> + # endif + #endif + + #include <stddef.h> + #include <string.h> + /* Put up to LEN chars of the host name into NAME. Null terminate it if the name is shorter than LEN. Return 0 if ok, -1 if error. */ int gethostname (char *name, size_t len) { ! #ifdef WIN32 ! /* The buffer passed to GetComputerName() must have at least ! MAX_COMPUTERNAME_LENGTH+1 bytes, the docs say. */ ! char buffer[MAX_COMPUTERNAME_LENGTH+1]; ! DWORD size; ! ! if (len >= sizeof (buffer)) ! { ! size = len; ! if (!GetComputerName (name, &size)) ! { ! if (GetLastError () == ERROR_MORE_DATA) ! errno = ENAMETOOLONG; ! else ! errno = EINVAL; ! return -1; ! } ! } ! else ! { ! size = sizeof (buffer); ! if (!GetComputerName (buffer, &size)) ! { ! if (GetLastError () == ERROR_MORE_DATA) ! errno = ENAMETOOLONG; ! else ! errno = EINVAL; ! return -1; ! } ! if (strlen (buffer) >= len) ! { ! errno = ENAMETOOLONG; ! return -1; ! } ! strcpy (name, buffer); ! } ! #else ! # ifdef HAVE_UNAME struct utsname uts; if (uname (&uts) == -1) *************** *** 46,53 **** len = sizeof (uts.nodename); } strncpy (name, uts.nodename, len); ! #else strcpy (name, ""); /* Hardcode your system name if you want. */ #endif return 0; } --- 96,104 ---- len = sizeof (uts.nodename); } strncpy (name, uts.nodename, len); ! # else strcpy (name, ""); /* Hardcode your system name if you want. */ + # endif #endif return 0; }
*** src/hostname.c.bak Wed Nov 5 04:46:46 2003 --- src/hostname.c Sun Jan 18 17:38:36 2004 *************** *** 1,5 **** /* hostname - set or print the name of current host system ! Copyright (C) 1994-1997, 1999-2003 Free Software Foundation, Inc. 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 --- 1,5 ---- /* hostname - set or print the name of current host system ! Copyright (C) 1994-1997, 1999-2004 Free Software Foundation, Inc. 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 *************** *** 15,43 **** along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ! /* Written by Jim Meyering. */ #include <config.h> #include <stdio.h> #include <sys/types.h> #include "system.h" - #include "long-options.h" #include "error.h" /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "hostname" ! #define AUTHORS "Jim Meyering" ! #if !defined(HAVE_SETHOSTNAME) && defined(HAVE_SYSINFO) && \ ! defined (HAVE_SYS_SYSTEMINFO_H) && defined(HAVE_LIMITS_H) ! # include <sys/systeminfo.h> int ! sethostname (name, namelen) ! char *name; ! int namelen; { /* Using sysinfo() is the SVR4 mechanism to set a hostname. */ int result; --- 15,193 ---- along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ! /* Written by Jim Meyering and Bruno Haible. */ #include <config.h> #include <stdio.h> + #include <getopt.h> #include <sys/types.h> + /* 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 "system.h" #include "error.h" + #include "xgethostname.h" /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "hostname" ! #define AUTHORS "Jim Meyering", "Bruno Haible" ! ! ! /* --------------------- Printing the host name --------------------- */ ! ! /* Output format. */ ! static enum { default_format, short_format, long_format, ip_format } format; ! ! /* 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 (); ! } ! } ! ! ! /* --------------------- Setting the host name --------------------- */ ! ! #if !defined(HAVE_SETHOSTNAME) ! # if defined(HAVE_SYSINFO) && defined(HAVE_SYS_SYSTEMINFO_H) \ ! && defined(HAVE_LIMITS_H) ! # include <sys/systeminfo.h> int ! sethostname (char *name, int namelen) { /* Using sysinfo() is the SVR4 mechanism to set a hostname. */ int result; *************** *** 47,60 **** return (result == -1 ? result : 0); } ! # define HAVE_SETHOSTNAME 1 /* Now we have it... */ #endif ! char *xgethostname (); /* The name this program was run with. */ char *program_name; void usage (int status) { --- 197,235 ---- return (result == -1 ? result : 0); } ! # else ! ! int ! sethostname (char *name, int namelen) ! { ! error (EXIT_FAILURE, 0, ! _("cannot set hostname; this system lacks the functionality")); ! return -1; ! } ! ! # endif ! #endif ! ! /* --------------------- Main program --------------------- */ ! ! /* Long options. */ ! static const struct option long_options[] = ! { ! { "fqdn", no_argument, NULL, 'f' }, ! { "ip-address", no_argument, NULL, 'i' }, ! { "long", no_argument, NULL, 'f' }, ! { "short", no_argument, NULL, 's' }, ! {GETOPT_HELP_OPTION_DECL}, ! {GETOPT_VERSION_OPTION_DECL}, ! { NULL, 0, NULL, 0 } ! }; /* The name this program was run with. */ char *program_name; + /* Display usage information and exit. */ void usage (int status) { *************** *** 64,77 **** else { printf (_("\ ! Usage: %s [NAME]\n\ ! or: %s OPTION\n\ ! Print or set the hostname of the current system.\n\ ! \n\ "), ! program_name, program_name); ! fputs (HELP_OPTION_DESCRIPTION, stdout); ! fputs (VERSION_OPTION_DESCRIPTION, stdout); printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); } exit (status); --- 239,269 ---- else { printf (_("\ ! Usage: %s [OPTION] [NAME]\n\ ! Displays or sets the hostname of the machine.\n\ "), ! program_name); ! printf ("\n"); ! printf (_("\ ! When NAME is not specified, the program prints the hostname.\n\ ! When NAME is specified, the program sets the hostname to NAME.\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 (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); } exit (status); *************** *** 80,121 **** int main (int argc, char **argv) { ! char *hostname; initialize_main (&argc, &argv); program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout); ! parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION, ! usage, AUTHORS, (char const *) NULL); ! #ifdef HAVE_SETHOSTNAME ! if (argc == 2) { int err; ! /* Set hostname to argv[1]. */ ! err = sethostname (argv[1], strlen (argv[1])); if (err != 0) ! error (EXIT_FAILURE, errno, _("cannot set hostname to `%s'"), argv[1]); ! exit (EXIT_SUCCESS); } ! #else ! if (argc == 2) ! error (EXIT_FAILURE, 0, ! _("cannot set hostname; this system lacks the functionality")); ! #endif ! ! if (argc <= 1) { ! hostname = xgethostname (); ! if (hostname == NULL) ! error (EXIT_FAILURE, errno, _("cannot determine hostname")); ! printf ("%s\n", hostname); } else { --- 272,341 ---- int main (int argc, char **argv) { ! int optchar; initialize_main (&argc, &argv); + + /* Set program name for messages. */ program_name = argv[0]; + + /* Set locale via LC_ALL. */ setlocale (LC_ALL, ""); + + /* Set the text message domain. */ bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); + /* Ensure that write errors on stdout are detected. */ atexit (close_stdout); ! /* Set default values for variables. */ ! 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': ! case_GETOPT_HELP_CHAR; ! case 'V': ! case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); ! default: ! usage (EXIT_FAILURE); ! /* NOTREACHED */ ! } ! if (argc == optind + 1) { + char *hostname = argv[optind]; int err; ! /* Options -s, -f, -i have no meaning here. */ ! if (format != default_format) ! usage (EXIT_FAILURE); ! ! /* Set hostname. */ ! err = sethostname (hostname, strlen (hostname)); if (err != 0) ! error (EXIT_FAILURE, errno, _("cannot set hostname to `%s'"), ! hostname); } ! else if (argc == optind) { ! /* Get and print the hostname. */ ! print_hostname (); } else {
AC_CHECK_HEADERS(arpa/inet.h) AC_CHECK_FUNCS(gethostbyname inet_ntop) AC_MSG_CHECKING([for IPv6 sockets]) AC_CACHE_VAL(gt_cv_socket_ipv6,[ AC_TRY_COMPILE([ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>], [int x = AF_INET6; struct in6_addr y; struct sockaddr_in6 z;], gt_cv_socket_ipv6=yes, gt_cv_socket_ipv6=no) ]) AC_MSG_RESULT($gt_cv_socket_ipv6) if test $gt_cv_socket_ipv6 = yes; then AC_DEFINE(HAVE_IPV6, 1, [Define if <sys/socket.h> defines AF_INET6.]) AC_CHECK_MEMBER(struct in6_addr.s6_addr16, [AC_DEFINE(HAVE_IN6_S6_ADDR16, 1, [Define if 'struct in6_addr' has the 's6_addr16' member.])], ,[ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h>]) fi
_______________________________________________ Bug-coreutils mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/bug-coreutils