174266Speter/*-
274288Sbrian * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
374288Sbrian *   Based on original work by Atsushi Murai <amurai@FreeBSD.org>
474288Sbrian * All rights reserved.
574266Speter *
674266Speter * Redistribution and use in source and binary forms, with or without
774266Speter * modification, are permitted provided that the following conditions
874266Speter * are met:
974266Speter * 1. Redistributions of source code must retain the above copyright
1074266Speter *    notice, this list of conditions and the following disclaimer.
1174266Speter * 2. Redistributions in binary form must reproduce the above copyright
1274266Speter *    notice, this list of conditions and the following disclaimer in the
1374266Speter *    documentation and/or other materials provided with the distribution.
1474266Speter *
1574288Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1674266Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1774266Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1874288Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1974266Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2074266Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2174266Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2274266Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2374266Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2474266Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2574266Speter * SUCH DAMAGE.
2674288Sbrian *
2774266Speter */
2874266Speter
2984225Sdillon#include <sys/cdefs.h>
3084225Sdillon__FBSDID("$FreeBSD$");
3174386Sbrian
3274266Speter#include <sys/param.h>
3374266Speter
3474266Speter#include <libutil.h>
3574266Speter#include <string.h>
3674266Speter#include <unistd.h>
3774266Speter
3874288Sbrianstatic int	isDISP(const char *);
3974288Sbrian
4074288Sbrian/*-
4174288Sbrian * Trim the current domain name from fullhost, but only if the result
4274288Sbrian * is less than or equal to hostsize in length.
4374288Sbrian *
4474288Sbrian * This function understands $DISPLAY type fullhosts.
4574288Sbrian *
4674288Sbrian * For example:
4774288Sbrian *
4874288Sbrian *     trimdomain("abcde.my.domain", 5)       ->   "abcde"
4974288Sbrian *     trimdomain("abcde.my.domain", 4)       ->   "abcde.my.domain"
5074288Sbrian *     trimdomain("abcde.my.domain:0.0", 9)   ->   "abcde:0.0"
5174288Sbrian *     trimdomain("abcde.my.domain:0.0", 8)   ->   "abcde.my.domain:0.0"
5274288Sbrian */
5374266Spetervoid
5474266Spetertrimdomain(char *fullhost, int hostsize)
5574266Speter{
5674386Sbrian	static size_t dlen;
5774386Sbrian	static int first = 1;
5874386Sbrian	static char domain[MAXHOSTNAMELEN];
5974386Sbrian	char *end, *s;
6074386Sbrian	size_t len;
6174266Speter
6274288Sbrian	if (first) {
6374288Sbrian		/* XXX: Should we assume that our domain is this persistent ? */
6474288Sbrian		first = 0;
6574288Sbrian		if (gethostname(domain, sizeof(domain) - 1) == 0 &&
6674288Sbrian		    (s = strchr(domain, '.')) != NULL)
6774288Sbrian			memmove(domain, s + 1, strlen(s + 1) + 1);
6874288Sbrian		else
6974288Sbrian			domain[0] = '\0';
7074288Sbrian		dlen = strlen(domain);
7174288Sbrian	}
7274266Speter
7374288Sbrian	if (domain[0] == '\0')
7474288Sbrian		return;
7574288Sbrian
7674266Speter	s = fullhost;
7774288Sbrian	end = s + hostsize + 1;
78150955Sbrooks	if ((s = memchr(s, '.', (size_t)(end - s))) != NULL) {
7974288Sbrian		if (strncasecmp(s + 1, domain, dlen) == 0) {
8074288Sbrian			if (s[dlen + 1] == '\0') {
8174288Sbrian				/* Found -- lose the domain. */
8274288Sbrian				*s = '\0';
8374288Sbrian			} else if (s[dlen + 1] == ':' &&
8474288Sbrian			    isDISP(s + dlen + 2) &&
85121193Smarkm			    (len = strlen(s + dlen + 1)) < (size_t)(end - s)) {
8674288Sbrian				/* Found -- shuffle the DISPLAY back. */
8774288Sbrian				memmove(s, s + dlen + 1, len + 1);
8874288Sbrian			}
8974288Sbrian		}
9074288Sbrian	}
9174266Speter}
9274288Sbrian
9374288Sbrian/*
9474288Sbrian * Is the given string NN or NN.NN where ``NN'' is an all-numeric string ?
9574288Sbrian */
9674288Sbrianstatic int
9774288SbrianisDISP(const char *disp)
9874288Sbrian{
99121193Smarkm	size_t w;
100121193Smarkm	int res;
10174288Sbrian
10274288Sbrian	w = strspn(disp, "0123456789");
10374288Sbrian	res = 0;
10474288Sbrian	if (w > 0) {
10574288Sbrian		if (disp[w] == '\0')
10674288Sbrian			res = 1;	/* NN */
10774288Sbrian		else if (disp[w] == '.') {
10874288Sbrian			disp += w + 1;
10974288Sbrian			w = strspn(disp, "0123456789");
11074288Sbrian			if (w > 0 && disp[w] == '\0')
11174288Sbrian				res = 1;	/* NN.NN */
11274288Sbrian		}
11374288Sbrian	}
11474288Sbrian	return (res);
11574288Sbrian}
116