+2021-04-03 Paul Eggert <eggert@cs.ucla.edu>
+
+ xgethostname: reorganize / simplify
+ xgethostname and xgetdomainname were essentially copies long
+ ago, but they’ve diverged. Bring them back together again
+ by implementing the (rarely used) latter in terms of the former.
+ And avoid some unnecessary realloc calls while we’re at it.
+ * lib/xgetdomainname.c: Rewrite from scratch so that it merely
+ includes xgethostname.c with a few preliminaries.
+ * lib/xgethostname.c: Generalize so that it can be included
+ from xgetdomainname.c.
+ (GETANAME, XGETANAME): New macros.
+ (INITIAL_HOSTNAME_LENGTH): Remove. No need for this parameter.
+ Use 100 instead, as few hostnames are longer than that.
+ (XGETANAME): Try getting the hostname into the stack first,
+ as that avoids a malloc call in the usual case.
+ Check for both POSIX-style truncation and SunOS 5.5 bug
+ in a cleaner way, by simply checking string length.
+ Don’t use x2realloc, which wastes time preserving buffer garbage;
+ use xpalloc with NULL instead. Don’t bother shrinking buffer
+ in the very rare case where the hostname is longer than sizeof
+ buf; it’s not worth the aggravation.
+ * modules/xgetdomainname (Depends-on): Remove free-posix, xalloc.
+ Add xgethostname.
+
2021-04-03 Bruno Haible <bruno@clisp.org>
*-list tests: Add more tests.
-/* xgetdomainname.c -- Return the NIS domain name, without size limitations.
- Copyright (C) 1992, 1996, 2000-2001, 2003-2004, 2006, 2008-2021 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
- 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 <https://www.gnu.org/licenses/>. */
-
-/* Based on xgethostname.c, written by Jim Meyering. */
-
-#include <config.h>
-
-/* Specification. */
+/* Return the NIS domain name, without size limitations. */
#include "xgetdomainname.h"
-
-/* Get getdomainname. */
-#include <unistd.h>
-
-/* Get errno. */
-#include <errno.h>
-
-/* Get strlen. */
-#include <string.h>
-
-/* Get free. */
-#include <stdlib.h>
-
-#include "xalloc.h"
-
-#ifndef INITIAL_DOMAINNAME_LENGTH
-# define INITIAL_DOMAINNAME_LENGTH 34
-#endif
-
-/* Return the NIS domain name of the machine, in malloc'd storage.
- WARNING! The NIS domain name is unrelated to the fully qualified host name
- of the machine. It is also unrelated to email addresses.
- WARNING! The NIS domain name is usually the empty string or "(none)" when
- not using NIS.
- If malloc fails, exit.
- Upon any other failure, set errno and return NULL. */
-char *
-xgetdomainname (void)
-{
- char *domainname;
- size_t size;
-
- size = INITIAL_DOMAINNAME_LENGTH;
- domainname = xmalloc (size);
- while (1)
- {
- int k = size - 1;
- int err;
-
- errno = 0;
- domainname[k] = '\0';
- err = getdomainname (domainname, size);
- if (err >= 0 && domainname[k] == '\0')
- break;
- else if (err < 0 && errno != EINVAL)
- {
- free (domainname);
- return NULL;
- }
- size *= 2;
- domainname = xrealloc (domainname, size);
- }
-
- /* Shrink DOMAINNAME before returning it. */
- {
- size_t actual_size = strlen (domainname) + 1;
- if (actual_size < size)
- {
- char *shrinked_domainname = realloc (domainname, actual_size);
- if (shrinked_domainname != NULL)
- domainname = shrinked_domainname;
- }
- }
-
- return domainname;
-}
+#define GETANAME getdomainname
+#define XGETANAME xgetdomainname
+#include "xgethostname.c"
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
-/* written by Jim Meyering */
+/* written by Jim Meyering and Paul Eggert */
#include <config.h>
+#ifndef GETANAME
/* Specification. */
-#include "xgethostname.h"
+# include "xgethostname.h"
+# define GETANAME gethostname
+# define XGETANAME xgethostname
+#endif
#include <stdlib.h>
#include <errno.h>
#include "xalloc.h"
-#ifndef INITIAL_HOSTNAME_LENGTH
-# define INITIAL_HOSTNAME_LENGTH 34
-#endif
-
-/* Return the current hostname in malloc'd storage.
+/* Return the current host or domain name in malloc'd storage.
If malloc fails, exit.
Upon any other failure, return NULL and set errno. */
char *
-xgethostname (void)
+XGETANAME (void)
{
- char *hostname = NULL;
- size_t size = INITIAL_HOSTNAME_LENGTH;
+ char buf[100];
+ idx_t size = sizeof buf;
+ char *name = buf;
+ char *alloc = NULL;
while (1)
{
/* Use SIZE_1 here rather than SIZE to work around the bug in
SunOS 5.5's gethostname whereby it NUL-terminates HOSTNAME
even when the name is as long as the supplied buffer. */
- size_t size_1;
-
- hostname = x2realloc (hostname, &size);
- size_1 = size - 1;
- hostname[size_1 - 1] = '\0';
+ idx_t size_1 = size - 1;
+ name[size_1] = '\0';
errno = 0;
-
- if (gethostname (hostname, size_1) == 0)
+ if (GETANAME (name, size_1) == 0)
{
- if (! hostname[size_1 - 1])
- break;
- }
- else if (errno != 0 && errno != ENAMETOOLONG && errno != EINVAL
- /* OSX/Darwin does this when the buffer is not large enough */
- && errno != ENOMEM)
- {
- free (hostname);
- return NULL;
+ /* Check whether the name was possibly truncated; POSIX does not
+ specify whether a truncated name is null-terminated. */
+ idx_t actual_size = strlen (name) + 1;
+ if (actual_size < size_1)
+ return alloc ? alloc : xmemdup (name, actual_size);
+ errno = 0;
}
+ free (alloc);
+ if (errno != 0 && errno != ENAMETOOLONG && errno != EINVAL
+ /* macOS/Darwin does this when SIZE_1 is too small. */
+ && errno != ENOMEM)
+ return NULL;
+ name = alloc = xpalloc (NULL, &size, 1, -1, 1);
}
-
- /* Shrink HOSTNAME before returning it. */
- {
- size_t actual_size = strlen (hostname) + 1;
- if (actual_size < size)
- {
- char *shrinked_hostname = realloc (hostname, actual_size);
- if (shrinked_hostname != NULL)
- hostname = shrinked_hostname;
- }
- }
-
- return hostname;
}
lib/xgetdomainname.c
Depends-on:
-free-posix
getdomainname
-xalloc
+xgethostname
configure.ac: