Imported Upstream version 0.18.3.2
[platform/upstream/gettext.git] / gettext-tools / src / hostname.c
1 /* Display hostname in various forms.
2    Copyright (C) 2001-2003, 2006-2007, 2012 Free Software Foundation, Inc.
3    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include <errno.h>
24 #include <getopt.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <locale.h>
29
30 #if defined _WIN32 || defined __WIN32__
31 # define WIN32_NATIVE
32 #endif
33
34 /* Get gethostname().  */
35 #include <unistd.h>
36
37 #ifdef WIN32_NATIVE
38 /* Native Woe32 API lacks gethostname() but has GetComputerName() instead.  */
39 # include <windows.h>
40 #else
41 /* Some systems, like early Solaris versions, lack gethostname() but
42    have uname() instead.  */
43 # if !HAVE_GETHOSTNAME
44 #  include <sys/utsname.h>
45 # endif
46 #endif
47
48 /* Get MAXHOSTNAMELEN.  */
49 #include <sys/param.h>
50 #ifndef MAXHOSTNAMELEN
51 # define MAXHOSTNAMELEN 64
52 #endif
53
54 /* Support for using gethostbyname().  */
55 #if HAVE_GETHOSTBYNAME
56 # include <sys/types.h>
57 # include <sys/socket.h> /* defines AF_INET, AF_INET6 */
58 # include <netinet/in.h> /* declares ntohs(), defines struct sockaddr_in */
59 # if HAVE_ARPA_INET_H
60 #  include <arpa/inet.h> /* declares inet_ntoa(), inet_ntop() */
61 # endif
62 # if HAVE_IPV6
63 #  if !defined(__CYGWIN__) /* Cygwin has only s6_addr, no s6_addr16 */
64 #   if defined(__APPLE__) && defined(__MACH__) /* MacOS X */
65 #    define in6_u __u6_addr
66 #    define u6_addr16 __u6_addr16
67 #   endif
68     /* Use s6_addr16 for portability.  See RFC 2553.  */
69 #   ifndef s6_addr16
70 #    define s6_addr16 in6_u.u6_addr16
71 #   endif
72 #   define HAVE_IN6_S6_ADDR16 1
73 #  endif
74 # endif
75 # include <netdb.h> /* defines struct hostent, declares gethostbyname() */
76 #endif
77
78 /* Include this after <sys/socket.h>, to avoid a syntax error on BeOS.  */
79 #include <stdbool.h>
80
81 #include "closeout.h"
82 #include "error.h"
83 #include "error-progname.h"
84 #include "progname.h"
85 #include "relocatable.h"
86 #include "basename.h"
87 #include "xalloc.h"
88 #include "propername.h"
89 #include "gettext.h"
90
91 #define _(str) gettext (str)
92
93
94 /* Output format.  */
95 static enum { default_format, short_format, long_format, ip_format } format;
96
97 /* Long options.  */
98 static const struct option long_options[] =
99 {
100   { "fqdn", no_argument, NULL, 'f' },
101   { "help", no_argument, NULL, 'h' },
102   { "ip-address", no_argument, NULL, 'i' },
103   { "long", no_argument, NULL, 'f' },
104   { "short", no_argument, NULL, 's' },
105   { "version", no_argument, NULL, 'V' },
106   { NULL, 0, NULL, 0 }
107 };
108
109
110 /* Forward declaration of local functions.  */
111 static void usage (int status)
112 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
113      __attribute__ ((noreturn))
114 #endif
115 ;
116 static void print_hostname (void);
117
118 int
119 main (int argc, char *argv[])
120 {
121   int optchar;
122   bool do_help;
123   bool do_version;
124
125   /* Set program name for messages.  */
126   set_program_name (argv[0]);
127   error_print_progname = maybe_print_progname;
128
129 #ifdef HAVE_SETLOCALE
130   /* Set locale via LC_ALL.  */
131   setlocale (LC_ALL, "");
132 #endif
133
134   /* Set the text message domain.  */
135   bindtextdomain (PACKAGE, relocate (LOCALEDIR));
136   textdomain (PACKAGE);
137
138   /* Ensure that write errors on stdout are detected.  */
139   atexit (close_stdout);
140
141   /* Set default values for variables.  */
142   do_help = false;
143   do_version = false;
144   format = default_format;
145
146   /* Parse command line options.  */
147   while ((optchar = getopt_long (argc, argv, "fhisV", long_options, NULL))
148          != EOF)
149     switch (optchar)
150     {
151     case '\0':          /* Long option.  */
152       break;
153     case 'f':
154       format = long_format;
155       break;
156     case 's':
157       format = short_format;
158       break;
159     case 'i':
160       format = ip_format;
161       break;
162     case 'h':
163       do_help = true;
164       break;
165     case 'V':
166       do_version = true;
167       break;
168     default:
169       usage (EXIT_FAILURE);
170       /* NOTREACHED */
171     }
172
173   /* Version information requested.  */
174   if (do_version)
175     {
176       printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
177       /* xgettext: no-wrap */
178       printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
179 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
180 This is free software: you are free to change and redistribute it.\n\
181 There is NO WARRANTY, to the extent permitted by law.\n\
182 "),
183               "2001-2003, 2006-2007");
184       printf (_("Written by %s.\n"), proper_name ("Bruno Haible"));
185       exit (EXIT_SUCCESS);
186     }
187
188   /* Help is requested.  */
189   if (do_help)
190     usage (EXIT_SUCCESS);
191
192   /* Test for extraneous arguments.  */
193   if (optind != argc)
194     error (EXIT_FAILURE, 0, _("too many arguments"));
195
196   /* Get and print the hostname.  */
197   print_hostname ();
198
199   exit (EXIT_SUCCESS);
200 }
201
202 /* Display usage information and exit.  */
203 static void
204 usage (int status)
205 {
206   if (status != EXIT_SUCCESS)
207     fprintf (stderr, _("Try '%s --help' for more information.\n"),
208              program_name);
209   else
210     {
211       printf (_("\
212 Usage: %s [OPTION]\n\
213 "), program_name);
214       printf ("\n");
215       printf (_("\
216 Print the machine's hostname.\n"));
217       printf ("\n");
218       printf (_("\
219 Output format:\n"));
220       printf (_("\
221   -s, --short                 short host name\n"));
222       printf (_("\
223   -f, --fqdn, --long          long host name, includes fully qualified domain\n\
224                                 name, and aliases\n"));
225       printf (_("\
226   -i, --ip-address            addresses for the hostname\n"));
227       printf ("\n");
228       printf (_("\
229 Informative output:\n"));
230       printf (_("\
231   -h, --help                  display this help and exit\n"));
232       printf (_("\
233   -V, --version               output version information and exit\n"));
234       printf ("\n");
235       /* TRANSLATORS: The placeholder indicates the bug-reporting address
236          for this package.  Please add _another line_ saying
237          "Report translation bugs to <...>\n" with the address for translation
238          bugs (typically your translation team's web or email address).  */
239       fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
240              stdout);
241     }
242
243   exit (status);
244 }
245
246 /* Returns an xmalloc()ed string containing the machine's host name.  */
247 static char *
248 xgethostname ()
249 {
250 #ifdef WIN32_NATIVE
251   char hostname[MAX_COMPUTERNAME_LENGTH+1];
252   DWORD size = sizeof (hostname);
253
254   if (!GetComputerName (hostname, &size))
255     error (EXIT_FAILURE, 0, _("could not get host name"));
256   return xstrdup (hostname);
257 #elif HAVE_GETHOSTNAME
258   char hostname[MAXHOSTNAMELEN+1];
259
260   if (gethostname (hostname, MAXHOSTNAMELEN) < 0)
261     error (EXIT_FAILURE, errno, _("could not get host name"));
262   hostname[MAXHOSTNAMELEN] = '\0';
263   return xstrdup (hostname);
264 #else
265   struct utsname utsname;
266
267   if (uname (&utsname) < 0)
268     error (EXIT_FAILURE, errno, _("could not get host name"));
269   return xstrdup (utsname.nodename);
270 #endif
271 }
272
273 /* Converts an AF_INET address to a printable, presentable format.
274    BUFFER is an array with at least 15+1 bytes.  ADDR is 'struct in_addr'.  */
275 #if HAVE_INET_NTOP
276 # define ipv4_ntop(buffer,addr) \
277     inet_ntop (AF_INET, &addr, buffer, 15+1)
278 #else
279 # define ipv4_ntop(buffer,addr) \
280     strcpy (buffer, inet_ntoa (addr))
281 #endif
282
283 #if HAVE_IPV6
284 /* Converts an AF_INET6 address to a printable, presentable format.
285    BUFFER is an array with at least 45+1 bytes.  ADDR is 'struct in6_addr'.  */
286 # if HAVE_INET_NTOP
287 #  define ipv6_ntop(buffer,addr) \
288      inet_ntop (AF_INET6, &addr, buffer, 45+1)
289 # elif HAVE_IN6_S6_ADDR16
290 #  define ipv6_ntop(buffer,addr) \
291      sprintf (buffer, "%x:%x:%x:%x:%x:%x:%x:%x", \
292               ntohs ((addr).s6_addr16[0]), \
293               ntohs ((addr).s6_addr16[1]), \
294               ntohs ((addr).s6_addr16[2]), \
295               ntohs ((addr).s6_addr16[3]), \
296               ntohs ((addr).s6_addr16[4]), \
297               ntohs ((addr).s6_addr16[5]), \
298               ntohs ((addr).s6_addr16[6]), \
299               ntohs ((addr).s6_addr16[7]))
300 # else
301 #  define ipv6_ntop(buffer,addr) \
302      sprintf (buffer, "%x:%x:%x:%x:%x:%x:%x:%x", \
303               ((addr).s6_addr[0] << 8) | (addr).s6_addr[1], \
304               ((addr).s6_addr[2] << 8) | (addr).s6_addr[3], \
305               ((addr).s6_addr[4] << 8) | (addr).s6_addr[5], \
306               ((addr).s6_addr[6] << 8) | (addr).s6_addr[7], \
307               ((addr).s6_addr[8] << 8) | (addr).s6_addr[9], \
308               ((addr).s6_addr[10] << 8) | (addr).s6_addr[11], \
309               ((addr).s6_addr[12] << 8) | (addr).s6_addr[13], \
310               ((addr).s6_addr[14] << 8) | (addr).s6_addr[15])
311 # endif
312 #endif
313
314 /* Print the hostname according to the specified format.  */
315 static void
316 print_hostname ()
317 {
318   char *hostname;
319   char *dot;
320 #if HAVE_GETHOSTBYNAME
321   struct hostent *h;
322   size_t i;
323 #endif
324
325   hostname = xgethostname ();
326
327   switch (format)
328     {
329     case default_format:
330       /* Print the hostname, as returned by the system call.  */
331       printf ("%s\n", hostname);
332       break;
333
334     case short_format:
335       /* Print only the part before the first dot.  */
336       dot = strchr (hostname, '.');
337       if (dot != NULL)
338         *dot = '\0';
339       printf ("%s\n", hostname);
340       break;
341
342     case long_format:
343       /* Look for netwide usable hostname and aliases using gethostbyname().  */
344 #if HAVE_GETHOSTBYNAME
345       h = gethostbyname (hostname);
346       if (h != NULL)
347         {
348           printf ("%s\n", h->h_name);
349           if (h->h_aliases != NULL)
350             for (i = 0; h->h_aliases[i] != NULL; i++)
351               printf ("%s\n", h->h_aliases[i]);
352         }
353       else
354 #endif
355         printf ("%s\n", hostname);
356       break;
357
358     case ip_format:
359       /* Look for netwide usable IP addresses using gethostbyname().  */
360 #if HAVE_GETHOSTBYNAME
361       h = gethostbyname (hostname);
362       if (h != NULL && h->h_addr_list != NULL)
363         for (i = 0; h->h_addr_list[i] != NULL; i++)
364           {
365 #if HAVE_IPV6
366             if (h->h_addrtype == AF_INET6)
367               {
368                 char buffer[45+1];
369                 ipv6_ntop (buffer, *(const struct in6_addr*) h->h_addr_list[i]);
370                 printf("[%s]\n", buffer);
371               }
372             else
373 #endif
374             if (h->h_addrtype == AF_INET)
375               {
376                 char buffer[15+1];
377                 ipv4_ntop (buffer, *(const struct in_addr*) h->h_addr_list[i]);
378                 printf("[%s]\n", buffer);
379               }
380           }
381 #endif
382       break;
383
384     default:
385       abort ();
386     }
387 }