Bug 16657

Summary: /bin/hostname: New feature to return subcomponents of hostname
Product: Base System Reporter: Ryan Thompson <ryan>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 3.4-STABLE   
Hardware: Any   
OS: Any   

Description Ryan Thompson 2000-02-11 22:40:02 UTC
	/bin/hostname's default behaviour is rather basic, and requires
	copious kludging to produce useful output in shell scripts and
	the like, when only part of the domain name is desired.

	For example, given the domain ftp.inner.host.com, perhaps a
	mail address is desired, and an automated way to fetch only the
	host.com portion is desired.  Or, perhaps only the host and
	inner subdomain is desired, i.e, ftp.inner.  See the fix below
	for examples.

Fix: 

Apply the following patches and use the [-l number] option.  Note
	that the current functionality of /bin/hostname is preserved; the
	output (and, indeed, most of the executed code) only differs if the 
	-l option is used.

	Example usage of new options, given domain ftp.inner.host.com:

	# hostname
	ftp.inner.host.com
	# hostname -l 2
	host.com
	# hostname -l 3
	inner.host.com
	# hostname -l 1048576
	ftp.inner.host.com
	# hostname -s
	ftp
	# hostname -s -l 2
	ftp.inner
	# hostname -s -l 65536
	ftp.inner.host.com

	
===================================================================
RCS file: hostname.c,v
retrieving revision 1.1
diff -r1.1 hostname.c
63,64c63,69
< 	int ch, sflag;
< 	char *p, hostname[MAXHOSTNAMELEN];
---
> 	int  	ch,    
> 		sflag, 
> 		level, /* Domain context level */
> 		i;
>              
>              
> 	char *p, hostname[MAXHOSTNAMELEN], *ep;
65a71
> 	level = -1; /* Indefinite levels */
67c73
< 	while ((ch = getopt(argc, argv, "s")) != -1)
---
> 	while ((ch = getopt(argc, argv, "sl:")) != -1)
70a77,90
>                         if (level == -1) /* Don't clobber anything set by -l */
>                             level = 1;
>                             
> 			break;
>                 case 'l':
> 			level = strtol(optarg, &ep, 10);
> 			if (level <= 0) 
> 				level = -1;
> 
> 			/* Optimize against unnecessarily complex levels */
>            
> 			if (level > MAXHOSTNAMELEN)
> 				level = MAXHOSTNAMELEN; 
>                             
88,89c108,137
< 		if (sflag && (p = strchr(hostname, '.')))
< 			*p = '\0';
---
> 
> 		if (level != -1)
> 		{
> 			if (sflag)
> 			{
> 			    p = hostname;
> 			    for (i = 0; i < level; i++)
> 			    {
> 			        if (!(p = strchr(p, '.')))
> 			            p = strchr(hostname, '\0');
> 			        p += 1;
>   			    }
>   			    if (p > hostname)
>    			        p -= 1;
>   			    *p = '\0';
> 			}
> 			else
> 			{
> 			    i = 0;
> 			    for (p = strchr(hostname, '\0') - 1; 
> 			         (i < level) && (p > hostname); p--)
> 			    {
> 			        if (p == strchr(p, '.'))
> 			            i++;
> 			    }
> 			    if (p != hostname)
> 			        p += 2;
> 			    strcpy(hostname, p);
> 			}
> 		}
99c147
< 	(void)fprintf(stderr, "usage: hostname [-s] [name-of-host]\n");
---
> 	(void)fprintf(stderr, "usage: hostname [-s] [-l #] [name-of-host]\n");

===================================================================
RCS file: hostname.1,v
retrieving revision 1.1
diff -r1.1 hostname.1
43a44
> .Op Fl l Ar number
62a64,71
> .It Fl l Ar number
> Display only the first
> .Ar number
> levels of the domain name.  (Or the last
> .Ar number
> levels of the domain name, if used with the
> .Fl s 
> option).
Comment 1 iedowse freebsd_committer freebsd_triage 2002-01-22 23:23:10 UTC
State Changed
From-To: open->closed


Such an option to hostname would be of extremely limited use, and 
it is just not the unix way of doing things; we have utilities such 
as sed, awk, cut etc. for this very reason. In your case, you could 
use 

hostname | awk -F. '{print $(NF-1) "." $(NF)}' 

and as always, there are many other ways that work too.