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