1245803Stheraven/* xgethostname.c -- return current hostname with unlimited length
2245803Stheraven
3245803Stheraven   Copyright (C) 1992, 1996, 2000, 2001, 2003, 2004, 2005 Free Software
4245803Stheraven   Foundation, Inc.
5245803Stheraven
6245803Stheraven   This program is free software; you can redistribute it and/or modify
7245803Stheraven   it under the terms of the GNU General Public License as published by
8245803Stheraven   the Free Software Foundation; either version 2, or (at your option)
9245803Stheraven   any later version.
10245803Stheraven
11245803Stheraven   This program is distributed in the hope that it will be useful,
12245803Stheraven   but WITHOUT ANY WARRANTY; without even the implied warranty of
13245803Stheraven   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14245803Stheraven   GNU General Public License for more details.
15245803Stheraven
16245803Stheraven   You should have received a copy of the GNU General Public License
17245803Stheraven   along with this program; if not, write to the Free Software Foundation,
18245803Stheraven   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
19245803Stheraven#include <sys/cdefs.h>
20245803Stheraven__RCSID("$NetBSD: xgethostname.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
21245803Stheraven
22245803Stheraven
23245803Stheraven/* written by Jim Meyering */
24245803Stheraven
25245803Stheraven#ifdef HAVE_CONFIG_H
26245803Stheraven# include <config.h>
27245803Stheraven#endif
28245803Stheraven
29245803Stheraven/* Specification.  */
30245803Stheraven#include "xgethostname.h"
31245803Stheraven
32245803Stheraven#include <stdlib.h>
33245803Stheraven#include <errno.h>
34245839Stheraven
35245803Stheraven#if HAVE_UNISTD_H
36245839Stheraven# include <unistd.h>
37245839Stheraven#endif
38245803Stheraven
39245839Stheraven#include "xalloc.h"
40245803Stheraven
41245803Stheraven#ifndef ENAMETOOLONG
42245803Stheraven# define ENAMETOOLONG 0
43245803Stheraven#endif
44245803Stheraven
45245803Stheraven#ifndef INITIAL_HOSTNAME_LENGTH
46245803Stheraven# define INITIAL_HOSTNAME_LENGTH 34
47289935Stheraven#endif
48245803Stheraven
49289935Stheraven/* Return the current hostname in malloc'd storage.
50245803Stheraven   If malloc fails, exit.
51245803Stheraven   Upon any other failure, return NULL and set errno.  */
52245803Stheravenchar *
53245803Stheravenxgethostname (void)
54245803Stheraven{
55245803Stheraven  char *hostname = NULL;
56245803Stheraven  size_t size = INITIAL_HOSTNAME_LENGTH;
57245803Stheraven
58245803Stheraven  while (1)
59245803Stheraven    {
60245803Stheraven      /* Use SIZE_1 here rather than SIZE to work around the bug in
61245803Stheraven	 SunOS 5.5's gethostname whereby it NUL-terminates HOSTNAME
62245803Stheraven	 even when the name is as long as the supplied buffer.  */
63245803Stheraven      size_t size_1;
64245803Stheraven
65245803Stheraven      hostname = x2realloc (hostname, &size);
66245803Stheraven      size_1 = size - 1;
67245803Stheraven      hostname[size_1 - 1] = '\0';
68245803Stheraven      errno = 0;
69245803Stheraven
70245803Stheraven      if (gethostname (hostname, size_1) == 0)
71245803Stheraven	{
72245803Stheraven	  if (! hostname[size_1 - 1])
73245803Stheraven	    break;
74245803Stheraven	}
75245803Stheraven      else if (errno != 0 && errno != ENAMETOOLONG && errno != EINVAL
76245803Stheraven	       /* OSX/Darwin does this when the buffer is not large enough */
77245803Stheraven	       && errno != ENOMEM)
78245803Stheraven	{
79245803Stheraven	  int saved_errno = errno;
80245803Stheraven	  free (hostname);
81245803Stheraven	  errno = saved_errno;
82245803Stheraven	  return NULL;
83245803Stheraven	}
84245803Stheraven    }
85245803Stheraven
86245803Stheraven  return hostname;
87245803Stheraven}
88245803Stheraven