From Arnaldo Carvalho de Melo (acme@conectiva.com.br):
[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.96 (1996-02-18)
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 
19  *                                      (major rewrite), usage.
20  *960120 {1.95} Bernd Eckenfels :       -y/nisdomainname - support for get/
21  *                                      setdomainname added 
22  *960218 {1.96} Bernd Eckenfels :       netinet/in.h added
23  *980629 {1.97} Arnaldo Carvalho de Melo : gettext instead of catgets for i18n
24  *20000213 {1.99} Arnaldo Carvalho de Melo : fixed some i18n strings
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 <unistd.h>
34 #include <getopt.h>
35 #include <string.h>
36 #include <netdb.h>
37 #include <errno.h>
38 #include <sys/param.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include "config.h"
42 #include "version.h"
43 #include "../intl.h"
44
45 #if HAVE_AFDECnet
46 #include <netdnet/dn.h>
47 #endif
48
49 char *Release = RELEASE, *Version = "hostname 1.99 (2000-02-13)";
50
51 static char *program_name;
52 static int opt_v;
53
54 static void sethname(char *);
55 static void setdname(char *);
56 static void showhname(char *, int);
57 static void usage(void);
58 static void version(void);
59 static void setfilename(char *, int);
60
61 #define SETHOST         1
62 #define SETDOMAIN       2
63 #define SETNODE         3
64
65 #if HAVE_AFDECnet
66 static void setnname(char *nname)
67 {
68     if (opt_v)
69         fprintf(stderr, _("Setting nodename to `%s'\n"),
70                 nname);
71     if (setnodename(nname, strlen(nname))) {
72         switch(errno) {
73         case EPERM:
74             fprintf(stderr, _("%s: you must be root to change the node name\n"), program_name);
75             break;
76         case EINVAL:
77             fprintf(stderr, _("%s: name too long\n"), program_name);
78             break;
79         default:
80         }
81         exit(1);
82     }
83 }
84 #endif /* HAVE_AFDECnet */
85
86 static void sethname(char *hname)
87 {
88     if (opt_v)
89         fprintf(stderr, _("Setting hostname to `%s'\n"),
90                 hname);
91     if (sethostname(hname, strlen(hname))) {
92         switch (errno) {
93         case EPERM:
94             fprintf(stderr, _("%s: you must be root to change the host name\n"), program_name);
95             break;
96         case EINVAL:
97             fprintf(stderr, _("%s: name too long\n"), program_name);
98             break;
99         default:
100         }
101         exit(1);
102     };
103 }
104
105 static void setdname(char *dname)
106 {
107     if (opt_v)
108         fprintf(stderr, _("Setting domainname to `%s'\n"),
109                 dname);
110     if (setdomainname(dname, strlen(dname))) {
111         switch (errno) {
112         case EPERM:
113             fprintf(stderr, _("%s: you must be root to change the domain name\n"), program_name);
114             break;
115         case EINVAL:
116             fprintf(stderr, _("%s: name too long\n"), program_name);
117             break;
118         default:
119         }
120         exit(1);
121     };
122 }
123
124 static void showhname(char *hname, int c)
125 {
126     struct hostent *hp;
127     register char *p, **alias;
128     struct in_addr **ip;
129
130     if (opt_v)
131         fprintf(stderr, _("Resolving `%s' ...\n"), hname);
132     if (!(hp = gethostbyname(hname))) {
133         herror(program_name);
134         exit(1);
135     }
136     if (opt_v) {
137         fprintf(stderr, _("Result: h_name=`%s'\n"),
138                 hp->h_name);
139
140         alias = hp->h_aliases;
141         while (alias[0])
142             fprintf(stderr, _("Result: h_aliases=`%s'\n"),
143                     *alias++);
144
145         ip = (struct in_addr **) hp->h_addr_list;
146         while (ip[0])
147             fprintf(stderr, _("Result: h_addr_list=`%s'\n"),
148                     inet_ntoa(**ip++));
149     }
150     if (!(p = strchr(hp->h_name, '.')) && (c == 'd'))
151         return;
152
153     switch (c) {
154     case 'a':
155         while (hp->h_aliases[0])
156             printf("%s ", *hp->h_aliases++);
157         printf("\n");
158         break;
159     case 'i':
160         while (hp->h_addr_list[0])
161             printf("%s ", inet_ntoa(*(struct in_addr *) *hp->h_addr_list++));
162         printf("\n");
163         break;
164     case 'd':
165         printf("%s\n", ++p);
166         break;
167     case 'f':
168         printf("%s\n", hp->h_name);
169         break;
170     case 's':
171         if (p != NULL)
172             *p = '\0';
173         printf("%s\n", hp->h_name);
174         break;
175     default:
176     }
177 }
178
179 static void setfilename(char *name, int what)
180 {
181     register FILE *fd;
182     register char *p;
183     char fline[MAXHOSTNAMELEN];
184
185     if ((fd = fopen(name, "r")) != NULL) {
186         while (fgets(fline, sizeof(fline), fd) != NULL) {
187             if ((p = index(fline, '\n')) != NULL)
188                 *p = '\0';
189             if (opt_v)
190                 fprintf(stderr, ">> %s\n", fline);
191             if (fline[0] == '#')
192                 continue;
193             switch(what) {
194             case SETHOST:
195                 sethname(fline);
196                 break;
197             case SETDOMAIN:
198                 setdname(fline);
199                 break;
200 #if HAVE_AFDECnet
201             case SETNODE:
202                 setnname(fline);
203                 break;
204 #endif /* HAVE_AFDECnet */
205             }
206         }
207         (void) fclose(fd);
208     } else {
209         fprintf(stderr, _("%s: can't open `%s'\n"),
210                 program_name, name);
211         exit(1);
212     }
213 }
214
215 static void version(void)
216 {
217     fprintf(stderr, "%s\n%s\n", Release, Version);
218     exit(5); /* E_VERSION */
219 }
220
221 static void usage(void)
222 {
223     fprintf(stderr, _("Usage: hostname [-v] {hostname|-F file}      set hostname (from file)\n"));
224     fprintf(stderr, _("       domainname [-v] {nisdomain|-F file}   set NIS domainname (from file)\n"));
225 #if HAVE_AFDECnet
226     fprintf(stderr, _("       nodename [-v] {nodename|-F file}      set DECnet node name (from file)\n"));
227 #endif
228     fprintf(stderr, _("       hostname [-v] [-d|-f|-s|-a|-i|-y|-n]  display formatted name\n"));
229     fprintf(stderr, _("       hostname [-v]                         display hostname\n\n"));
230     fprintf(stderr, _("       hostname -V|--version|-h|--help       print info and exit\n\n"));
231     fprintf(stderr, _("    dnsdomainname=hostname -d, {yp,nis,}domainname=hostname -y\n\n"));
232     fprintf(stderr, _("    -s, --short           short host name\n"));
233     fprintf(stderr, _("    -a, --alias           alias names\n"));
234     fprintf(stderr, _("    -i, --ip-address      addresses for the hostname\n"));
235     fprintf(stderr, _("    -f, --fqdn, --long    long host name (FQDN)\n"));
236     fprintf(stderr, _("    -d, --domain          DNS domain name\n"));
237     fprintf(stderr, _("    -y, --yp, --nis       NIS/YP domainname\n"));
238 #if HAVE_AFDECnet
239     fprintf(stderr, _("    -n, --node            DECnet node name\n"));
240 #endif /* HAVE_AFDECnet */
241     fprintf(stderr, _("    -F, --file            read hostname or NIS domainname from given file\n\n"));
242     fprintf(stderr, _(
243 "   This command can read or set the hostname or the NIS domainname. You can\n"
244 "   also read the DNS domain or the FQDN (fully qualified domain name).\n"
245 "   Unless you are using bind or NIS for host lookups you can change the\n"
246 "   FQDN (Fully Qualified Domain Name) and the DNS domain name (which is\n"
247 "   part of the FQDN) in the /etc/hosts file.\n"));
248
249     exit(4); /* E_USAGE */
250 }
251
252
253 int main(int argc, char **argv)
254 {
255     int c;
256     char type = '\0';
257     int option_index = 0;
258     int what = 0;
259     char myname[MAXHOSTNAMELEN + 1] =
260     {0};
261     char *file = NULL;
262
263     static const struct option long_options[] =
264     {
265         {"domain", no_argument, 0, 'd'},
266         {"file", required_argument, 0, 'F'},
267         {"fqdn", no_argument, 0, 'f'},
268         {"help", no_argument, 0, 'h'},
269         {"long", no_argument, 0, 'f'},
270         {"short", no_argument, 0, 's'},
271         {"version", no_argument, 0, 'V'},
272         {"verbose", no_argument, 0, 'v'},
273         {"alias", no_argument, 0, 'a'},
274         {"ip-address", no_argument, 0, 'i'},
275         {"nis", no_argument, 0, 'y'},
276         {"yp", no_argument, 0, 'y'},
277 #if HAVE_AFDECnet
278         {"node", no_argument, 0, 'n'},
279 #endif /* HAVE_AFDECnet */
280         {0, 0, 0, 0}
281     };
282 #if I18N
283     bindtextdomain("net-tools", "/usr/share/locale");
284     textdomain("net-tools");
285 #endif
286     program_name = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0];
287
288     if (!strcmp(program_name, "ypdomainname") ||
289         !strcmp(program_name, "domainname") ||
290         !strcmp(program_name, "nisdomainname"))
291         what = 3;
292     if (!strcmp(program_name, "dnsdomainname"))
293         what = 2;
294 #if HAVE_AFDECnet
295     if (!strcmp(program_name, "nodename"))
296         what = 4;
297 #endif /* HAVE_AFDECnet */
298
299     while ((c = getopt_long(argc, argv, "adfF:h?isVvyn", long_options, &option_index)) != EOF)
300         switch (c) {
301         case 'd':
302             what = 2;
303             break;
304         case 'a':
305         case 'f':
306         case 'i':
307         case 's':
308             what = 1;
309             type = c;
310             break;
311         case 'y':
312             what = 3;
313             break;
314 #if HAVE_AFDECnet
315         case 'n':
316             what = 4;
317             break;
318 #endif /* HAVE_AFDECnet */
319         case 'F':
320             file = optarg;
321             break;
322         case 'v':
323             opt_v++;
324             break;
325         case 'V':
326             version();
327         case '?':
328         case 'h':
329         default:
330             usage();
331
332         };
333
334
335     switch (what) {
336     case 2:
337         if (file || (optind < argc)) {
338             fprintf(stderr, _("%s: You can't change the DNS domain name with this command\n"), program_name);
339             fprintf(stderr, _("\nUnless you are using bind or NIS for host lookups you can change the DNS\n"));
340             fprintf(stderr, _("domain name (which is part of the FQDN) in the /etc/hosts file.\n"));
341             exit(1);
342         }
343         type = 'd';
344         /* NOBREAK */
345     case 0:
346         if (file) {
347             setfilename(file, SETHOST);
348             break;
349         }
350         if (optind < argc) {
351             sethname(argv[optind]);
352             break;
353         }
354     case 1:
355         gethostname(myname, sizeof(myname));
356         if (opt_v)
357             fprintf(stderr, _("gethostname()=`%s'\n"), myname);
358         if (!type)
359             printf("%s\n", myname);
360         else
361             showhname(myname, type);
362         break;
363     case 3:
364         if (file) {
365             setfilename(file, SETDOMAIN);
366             break;
367         }
368         if (optind < argc) {
369             setdname(argv[optind]);
370             break;
371         }
372         getdomainname(myname, sizeof(myname));
373         if (opt_v)
374             fprintf(stderr, _("getdomainname()=`%s'\n"), myname);
375         printf("%s\n", myname);
376         break;
377 #if HAVE_AFDECnet
378     case 4:
379         if (file) {
380             setfilename(file, SETNODE);
381             break;
382         }
383         if (optind < argc) {
384             setnname(argv[optind]);
385             break;
386         }
387         getnodename(myname, sizeof(myname));
388         if (opt_v)
389             fprintf(stderr, _("getnodename()=`%s'\n"), myname);
390         printf("%s\n", myname);
391         break;
392 #endif /* HAVE_AFDECnet */
393     }
394     exit(0);
395 }