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

Reply via email to