Use sys/xattr.h instead of attr/xattr.h
[platform/upstream/net-tools.git] / hostname.c
1 /*
2  * hostname   This file contains an implementation of the command
3  *              that maintains the hostname and the domainname. It
4  *              is also used to show the FQDN and the IP-Addresses.
5  *
6  * Usage:       hostname [-d|-f|-s|-a|-i|-y|-n]
7  *              hostname [-h|-V]
8  *              hostname {name|-F file}
9  *              dnsdmoainname   
10  *              nisdomainname {name|-F file}
11  *
12  * Version:     hostname 1.101 (2003-10-11)
13  *
14  * Author:      Peter Tobias <tobias@et-inf.fho-emden.de>
15  *
16  * Changes:
17  *         {1.90}  Peter Tobias : Added -a and -i options.
18  *         {1.91}  Bernd Eckenfels : -v,-V rewritten, long_opts (major rewrite), usage.
19  *19960120 {1.95}  Bernd Eckenfels : -y/nisdomainname - support for get/setdomainname added 
20  *19960218 {1.96}  Bernd Eckenfels : netinet/in.h added
21  *19980629 {1.97}  Arnaldo Carvalho de Melo : gettext instead of catgets for i18n
22  *20000213 {1.99}  Arnaldo Carvalho de Melo : fixed some i18n strings
23  *20010404 {1.100} Arnaldo Carvalho de Melo: use setlocale
24  *20031011 {1.101} Maik Broemme: gcc 3.x fixes (default: break)
25  *
26  *              This program is free software; you can redistribute it
27  *              and/or  modify it under  the terms of  the GNU General
28  *              Public  License as  published  by  the  Free  Software
29  *              Foundation;  either  version 2 of the License, or  (at
30  *              your option) any later version.
31  */
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <getopt.h>
37 #include <string.h>
38 #include <netdb.h>
39 #include <errno.h>
40 #include <sys/param.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include "config.h"
44 #include "version.h"
45 #include "net-support.h"
46 #include "../intl.h"
47
48 #if HAVE_AFINET6
49 #include <sys/socket.h> /* for PF_INET6 */
50 #include <sys/types.h>  /* for inet_ntop */
51 #endif
52
53 #if HAVE_AFDECnet
54 #include <netdnet/dn.h>
55 #endif
56
57 char *Release = RELEASE, *Version = "hostname 1.100 (2001-04-14)";
58
59 static char *program_name;
60 static int opt_v;
61
62 static void sethname(char *);
63 static void setdname(char *);
64 static void showhname(char *, int);
65 static void usage(void);
66 static void version(void);
67 static void setfilename(char *, int);
68
69 #define SETHOST         1
70 #define SETDOMAIN       2
71 #define SETNODE         3
72
73 #if HAVE_AFDECnet
74 static void setnname(char *nname)
75 {
76     if (opt_v)
77         fprintf(stderr, _("Setting nodename to `%s'\n"),
78                 nname);
79     if (setnodename(nname, strlen(nname))) {
80         switch(errno) {
81         case EPERM:
82             fprintf(stderr, _("%s: you must be root to change the node name\n"), program_name);
83             break;
84         case EINVAL:
85             fprintf(stderr, _("%s: name too long\n"), program_name);
86             break;
87         default:
88             break;
89         }
90         exit(1);
91     }
92 }
93 #endif /* HAVE_AFDECnet */
94
95 static void sethname(char *hname)
96 {
97     if (opt_v)
98         fprintf(stderr, _("Setting hostname to `%s'\n"),
99                 hname);
100     if (sethostname(hname, strlen(hname))) {
101         switch (errno) {
102         case EPERM:
103             fprintf(stderr, _("%s: you must be root to change the host name\n"), program_name);
104             break;
105         case EINVAL:
106             fprintf(stderr, _("%s: name too long\n"), program_name);
107             break;
108         }
109         exit(1);
110     };
111 }
112
113 static void setdname(char *dname)
114 {
115     if (opt_v)
116         fprintf(stderr, _("Setting domainname to `%s'\n"),
117                 dname);
118     if (setdomainname(dname, strlen(dname))) {
119         switch (errno) {
120         case EPERM:
121             fprintf(stderr, _("%s: you must be root to change the domain name\n"), program_name);
122             break;
123         case EINVAL:
124             fprintf(stderr, _("%s: name too long\n"), program_name);
125             break;
126         }
127         exit(1);
128     };
129 }
130
131 static void showhname(char *hname, int c)
132 {
133     struct hostent *hp;
134 #if HAVE_AFINET6
135     struct in6_addr **ip6;
136 #endif
137     register char *p, **alias;
138     struct in_addr **ip;
139
140     if (opt_v)
141         fprintf(stderr, _("Resolving `%s' ...\n"), hname);
142     if (
143 #if HAVE_AFINET6
144         !(hp = gethostbyname2(hname, PF_INET6)) &&
145 #endif
146         !(hp = gethostbyname(hname))) {
147         herror(program_name);
148         exit(1);
149     }
150
151     if (opt_v) {
152         fprintf(stderr, _("Result: h_name=`%s'\n"),
153                 hp->h_name);
154
155         alias = hp->h_aliases;
156         while (alias[0])
157             fprintf(stderr, _("Result: h_aliases=`%s'\n"),
158                     *alias++);
159 #if HAVE_AFINET6
160             if (hp->h_addrtype == PF_INET6) {
161                 char addr[INET6_ADDRSTRLEN + 1];
162                 addr[INET6_ADDRSTRLEN] = '\0';
163                 ip6 = (struct in6_addr **) hp->h_addr_list;
164                 while (ip6[0]) {
165                     if (inet_ntop(PF_INET6, *ip6++, addr, INET6_ADDRSTRLEN))
166                         fprintf(stderr, _("Result: h_addr_list=`%s'\n"), addr);
167                     else if (errno == EAFNOSUPPORT)
168                         fprintf(stderr, _("%s: protocol family not supported\n"),
169                                 program_name);
170                     else if (errno == ENOSPC)
171                         fprintf(stderr, _("%s: name too long\n"), program_name);
172             }
173         } else
174 #endif
175         {
176             ip = (struct in_addr **) hp->h_addr_list;
177             while (ip[0])
178                 fprintf(stderr, _("Result: h_addr_list=`%s'\n"),
179                         inet_ntoa(**ip++));
180         }
181     }
182     if (!(p = strchr(hp->h_name, '.')) && (c == 'd'))
183         return;
184
185     switch (c) {
186     case 'a':
187         while (hp->h_aliases[0])
188             printf("%s ", *hp->h_aliases++);
189         printf("\n");
190         break;
191     case 'i':
192 #if HAVE_AFINET6
193         if (hp->h_addrtype == PF_INET6) {
194             char addr[INET6_ADDRSTRLEN + 1];
195             addr[INET6_ADDRSTRLEN] = '\0';
196             while (hp->h_addr_list[0]) {
197                 if (inet_ntop(PF_INET6, (struct in6_addr *)*hp->h_addr_list++,
198                               addr, INET6_ADDRSTRLEN)) {
199                     printf("%s ", addr);
200                 } else if (errno == EAFNOSUPPORT) {
201                     fprintf(stderr, _("\n%s: protocol family not supported\n"),
202                             program_name);
203                     exit(1);
204                 } else if (errno == ENOSPC) {
205                     fprintf(stderr, _("\n%s: name too long\n"), program_name);
206                     exit(1);
207                 }
208             }
209         } else
210 #endif
211         {
212             while (hp->h_addr_list[0])
213                 printf("%s ", inet_ntoa(*(struct in_addr *)*hp->h_addr_list++));
214         }
215         printf("\n");
216         break;
217     case 'd':
218         printf("%s\n", ++p);
219         break;
220     case 'f':
221         printf("%s\n", hp->h_name);
222         break;
223     case 's':
224         if (p != NULL)
225             *p = '\0';
226         printf("%s\n", hp->h_name);
227         break;
228     }
229 }
230
231 static void setfilename(char *name, int what)
232 {
233     register FILE *fd;
234     register char *p;
235     char fline[MAXHOSTNAMELEN];
236
237     if ((fd = fopen(name, "r")) != NULL) {
238         while (fgets(fline, sizeof(fline), fd) != NULL) {
239             if ((p = index(fline, '\n')) != NULL)
240                 *p = '\0';
241             if (opt_v)
242                 fprintf(stderr, ">> %s\n", fline);
243             if (fline[0] == '#')
244                 continue;
245             switch(what) {
246             case SETHOST:
247                 sethname(fline);
248                 break;
249             case SETDOMAIN:
250                 setdname(fline);
251                 break;
252 #if HAVE_AFDECnet
253             case SETNODE:
254                 setnname(fline);
255                 break;
256 #endif /* HAVE_AFDECnet */
257             }
258         }
259         (void) fclose(fd);
260     } else {
261         fprintf(stderr, _("%s: can't open `%s'\n"),
262                 program_name, name);
263         exit(1);
264     }
265 }
266
267 static void version(void)
268 {
269     fprintf(stderr, "%s\n%s\n", Release, Version);
270     exit(E_VERSION);
271 }
272
273 static void usage(void)
274 {
275     fprintf(stderr, _("Usage: hostname [-v] {hostname|-F file}      set hostname (from file)\n"));
276     fprintf(stderr, _("       domainname [-v] {nisdomain|-F file}   set NIS domainname (from file)\n"));
277 #if HAVE_AFDECnet
278     fprintf(stderr, _("       nodename [-v] {nodename|-F file}      set DECnet node name (from file)\n"));
279 #endif
280     fprintf(stderr, _("       hostname [-v] [-d|-f|-s|-a|-i|-y|-n]  display formatted name\n"));
281     fprintf(stderr, _("       hostname [-v]                         display hostname\n\n"));
282     fprintf(stderr, _("       hostname -V|--version|-h|--help       print info and exit\n\n"));
283     fprintf(stderr, _("    dnsdomainname=hostname -d, {yp,nis,}domainname=hostname -y\n\n"));
284     fprintf(stderr, _("    -s, --short           short host name\n"));
285     fprintf(stderr, _("    -a, --alias           alias names\n"));
286     fprintf(stderr, _("    -i, --ip-address      addresses for the hostname\n"));
287     fprintf(stderr, _("    -f, --fqdn, --long    long host name (FQDN)\n"));
288     fprintf(stderr, _("    -d, --domain          DNS domain name\n"));
289     fprintf(stderr, _("    -y, --yp, --nis       NIS/YP domainname\n"));
290 #if HAVE_AFDECnet
291     fprintf(stderr, _("    -n, --node            DECnet node name\n"));
292 #endif /* HAVE_AFDECnet */
293     fprintf(stderr, _("    -F, --file            read hostname or NIS domainname from given file\n\n"));
294     fprintf(stderr, _(
295 "   This command can read or set the hostname or the NIS domainname. You can\n"
296 "   also read the DNS domain or the FQDN (fully qualified domain name).\n"
297 "   Unless you are using bind or NIS for host lookups you can change the\n"
298 "   FQDN (Fully Qualified Domain Name) and the DNS domain name (which is\n"
299 "   part of the FQDN) in the /etc/hosts file.\n"));
300
301     exit(E_USAGE);
302 }
303
304
305 int main(int argc, char **argv)
306 {
307     int c;
308     char type = '\0';
309     int option_index = 0;
310     int what = 0;
311     char myname[MAXHOSTNAMELEN + 1] =
312     {0};
313     char *file = NULL;
314
315     static const struct option long_options[] =
316     {
317         {"domain", no_argument, 0, 'd'},
318         {"file", required_argument, 0, 'F'},
319         {"fqdn", no_argument, 0, 'f'},
320         {"help", no_argument, 0, 'h'},
321         {"long", no_argument, 0, 'f'},
322         {"short", no_argument, 0, 's'},
323         {"version", no_argument, 0, 'V'},
324         {"verbose", no_argument, 0, 'v'},
325         {"alias", no_argument, 0, 'a'},
326         {"ip-address", no_argument, 0, 'i'},
327         {"nis", no_argument, 0, 'y'},
328         {"yp", no_argument, 0, 'y'},
329 #if HAVE_AFDECnet
330         {"node", no_argument, 0, 'n'},
331 #endif /* HAVE_AFDECnet */
332         {0, 0, 0, 0}
333     };
334 #if I18N
335     setlocale (LC_ALL, "");
336     bindtextdomain("net-tools", "/usr/share/locale");
337     textdomain("net-tools");
338 #endif
339     program_name = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0];
340
341     if (!strcmp(program_name, "ypdomainname") ||
342         !strcmp(program_name, "domainname") ||
343         !strcmp(program_name, "nisdomainname"))
344         what = 3;
345     if (!strcmp(program_name, "dnsdomainname"))
346         what = 2;
347 #if HAVE_AFDECnet
348     if (!strcmp(program_name, "nodename"))
349         what = 4;
350 #endif /* HAVE_AFDECnet */
351
352     while ((c = getopt_long(argc, argv, "adfF:h?isVvyn", long_options, &option_index)) != EOF)
353         switch (c) {
354         case 'd':
355             what = 2;
356             break;
357         case 'a':
358         case 'f':
359         case 'i':
360         case 's':
361             what = 1;
362             type = c;
363             break;
364         case 'y':
365             what = 3;
366             break;
367 #if HAVE_AFDECnet
368         case 'n':
369             what = 4;
370             break;
371 #endif /* HAVE_AFDECnet */
372         case 'F':
373             file = optarg;
374             break;
375         case 'v':
376             opt_v++;
377             break;
378         case 'V':
379             version();
380             break; // not reached
381         case '?':
382         case 'h':
383         default:
384             usage();
385             break; // not reached
386         };
387
388
389     switch (what) {
390     case 2:
391         if (file || (optind < argc)) {
392             fprintf(stderr, _("%s: You can't change the DNS domain name with this command\n"), program_name);
393             fprintf(stderr, _("\nUnless you are using bind or NIS for host lookups you can change the DNS\n"));
394             fprintf(stderr, _("domain name (which is part of the FQDN) in the /etc/hosts file.\n"));
395             exit(1);
396         }
397         type = 'd';
398         /* NOBREAK */
399     case 0:
400         if (file) {
401             setfilename(file, SETHOST);
402             break;
403         }
404         if (optind < argc) {
405             sethname(argv[optind]);
406             break;
407         }
408     case 1:
409         gethostname(myname, sizeof(myname));
410         if (opt_v)
411             fprintf(stderr, _("gethostname()=`%s'\n"), myname);
412         if (!type)
413             printf("%s\n", myname);
414         else
415             showhname(myname, type);
416         break;
417     case 3:
418         if (file) {
419             setfilename(file, SETDOMAIN);
420             break;
421         }
422         if (optind < argc) {
423             setdname(argv[optind]);
424             break;
425         }
426         if (getdomainname(myname, sizeof(myname)) < 0) {
427             perror("getdomainname()");
428             exit(1);
429         }
430         if (opt_v)
431             fprintf(stderr, _("getdomainname()=`%s'\n"), myname);
432         printf("%s\n", myname);
433         break;
434 #if HAVE_AFDECnet
435     case 4:
436         if (file) {
437             setfilename(file, SETNODE);
438             break;
439         }
440         if (optind < argc) {
441             setnname(argv[optind]);
442             break;
443         }
444         getnodename(myname, sizeof(myname));
445         if (opt_v)
446             fprintf(stderr, _("getnodename()=`%s'\n"), myname);
447         printf("%s\n", myname);
448         break;
449 #endif /* HAVE_AFDECnet */
450     }
451     exit(0);
452 }