Package: hostname
Version: 2.95
Severity: wishlist
Tags: patch
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu jaunty ubuntu-patch

In Ubuntu, we've applied the attached patch to achieve the following:

  * Add -b option that allows the file specified by -F to be non-existant
    or empty, in which case the default hostname of "localhost" will be set
    if none is set currently.

We thought you might be interested in doing the same. 


This patch removes the need for the logic in /etc/init.d/hostname.sh,
replacing it with a simple "hostname -b -F /etc/hostname" call.  This
has a significant performance improvement (0.15s -> 0.001s)

-- System Information:
Debian Release: 5.0
  APT prefers jaunty-updates
  APT policy: (500, 'jaunty-updates'), (500, 'jaunty-security'), (500, 
'jaunty-proposed'), (500, 'jaunty')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.28-15-generic (SMP w/2 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -Nru hostname-2.95/hostname.c hostname-2.95ubuntu1/hostname.c
--- hostname-2.95/hostname.c	2007-12-27 11:45:12.000000000 +0000
+++ hostname-2.95ubuntu1/hostname.c	2009-08-26 13:21:18.000000000 +0100
@@ -5,7 +5,7 @@
  *
  * Usage:	hostname [-d|-f|-s|-a|-i|-y]
  *		hostname [-h|-V]
- *		hostname {name|-F file}
+ *		hostname [-b] {name|-F file}
  *		dnsdomainname
  *
  * Authors:	Peter Tobias <tob...@et-inf.fho-emden.de>
@@ -115,7 +115,7 @@
 usage(FILE *stream)
 {
 	fprintf(stream,
-		"Usage: hostname [-v] {hostname|-F file}      set host name (from file)\n"
+		"Usage: hostname [-v] [-b] {hostname|-F file} set host name (from file)\n"
 		"       domainname [-v] {nisdomain|-F file}   set NIS domain name (from file)\n"
 		"       hostname [-v] [-d|-f|-s|-a|-i|-y]     display formated name\n"
 		"       hostname [-v]                         display host name\n\n"
@@ -127,6 +127,7 @@
 		"    -f, --fqdn, --long    long host name (FQDN)\n"
 		"    -d, --domain          DNS domain name\n"
 		"    -y, --yp, --nis       NIS/YP domain name\n"
+		"    -b, --boot            set default hostname if none available\n"
 		"    -F, --file            read host name or NIS domain name from given file\n\n"
 		"   This command can get or set the host name or the NIS domain name. You can\n"
 		"   also get the DNS domain or the FQDN (fully qualified domain name).\n"
@@ -261,13 +262,20 @@
 }
 
 char *
-read_file(char *filename)
+read_file(char *filename, int boot)
 {
 	struct stat st;
   	FILE *fp;
 	char *buf;
 
-	if ((fp = fopen(filename, "r")) == NULL || fstat(fileno(fp), &st) == -1
+	if ((fp = fopen(filename, "r")) == NULL) {
+		if (boot)
+			return NULL;
+		else
+			err(1, NULL);
+	}
+
+	if (fstat(fileno(fp), &st) == -1
 	   || (buf = (char *) malloc(st.st_size + 1)) == NULL)
 		err(1, NULL);
 
@@ -289,13 +297,15 @@
 int
 main(int argc, char **argv)
 {
-	char *progname, *name = NULL;
+	char *progname, *file = NULL, *name = NULL;
 	enum type_t type = DEFAULT;
+	int boot = 0;
 	int o;
 
 	static const struct option long_options[] =
 	{
 		{"domain", no_argument, 0, 'd'},
+		{"boot", no_argument, 0, 'b'},
 		{"file", required_argument, 0, 'F'},
 		{"fqdn", no_argument, 0, 'f'},
 		{"help", no_argument, 0, 'h'},
@@ -315,7 +325,7 @@
 	if (!strcmp(progname, "dnsdomainname"))
 		type = DNS;
 
-	while((o = getopt_long(argc, argv, "adfF:h?isVvy", long_options, NULL)) != -1)
+	while((o = getopt_long(argc, argv, "adfbF:h?isVvy", long_options, NULL)) != -1)
 		switch (o) {
 		case 'd':
 			type = DNS;
@@ -335,10 +345,11 @@
 		case 'y':
 			type = NIS;
 			break;
+		case 'b':
+			boot = 1;
+			break;
 		case 'F':
-			if (name)
-				free(name);
-			name = read_file(optarg);
+			file = optarg;
 			break;
 		case 'v':
 			/* Does not do anything. */
@@ -354,7 +365,23 @@
 			usage(stderr);
 		}
 
-	/* The hostname is the first non-option argument. */
+	/*
+	 * Hostname may be read from a file, it's ok for this file to not
+	 * exist or be empty if -b is given in which case we default to
+	 * "localhost" if there is not one already set.
+	 */
+	if (file) {
+		name = read_file(file, boot);
+		if (boot && (name == NULL || name[0] == '\0')) {
+			free(name);
+
+			name = localhost();
+			if (name[0] == '\0')
+				strcpy(name, "localhost");
+		}
+	}
+
+	/* Otherwise the hostname is the first non-option argument. */
 	if (optind < argc) {
 		/*
 		 * It is an error to specify a host name as an argument, and to
diff -Nru hostname-2.95/hostname.1 hostname-2.95ubuntu1/hostname.1
--- hostname-2.95/hostname.1	2007-11-14 22:22:58.000000000 +0000
+++ hostname-2.95ubuntu1/hostname.1	2009-08-26 13:25:16.000000000 +0100
@@ -26,6 +26,8 @@
 .PP
 .B hostname
 .RB [ \-v ]
+.RB [ \-b ]
+.RB [ \-\-boot ]
 .RB [ \-F\ filename ]
 .RB [ \-\-file\ filename ]
 .RB [ hostname ]
@@ -110,6 +112,11 @@
 .I "\-a, \-\-alias"
 Display the alias name of the host (if used).
 .TP
+.I "\-b, \-\-boot"
+Always set a hostname; this allows the file specified by \fI-F\fR to be
+non-existant or empty, in which case the default hostname \fIlocalhost\fR
+will be used if none is yet set.
+.TP
 .I "\-d, \-\-domain"
 Display the name of the DNS domain.  Don't use the command
 .B domainname

Reply via email to