xref: /csrg-svn/libexec/rshd/rshd.c (revision 36700)
121176Sdist /*
236629Skarels  * Copyright (c) 1983, 1988 The Regents of the University of California.
335485Sbostic  * All rights reserved.
435485Sbostic  *
535485Sbostic  * Redistribution and use in source and binary forms are permitted
635485Sbostic  * provided that the above copyright notice and this paragraph are
735485Sbostic  * duplicated in all such forms and that any documentation,
835485Sbostic  * advertising materials, and other materials related to such
935485Sbostic  * distribution and use acknowledge that the software was developed
1035485Sbostic  * by the University of California, Berkeley.  The name of the
1135485Sbostic  * University may not be used to endorse or promote products derived
1235485Sbostic  * from this software without specific prior written permission.
1335485Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1435485Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1535485Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621176Sdist  */
1721176Sdist 
186454Swnj #ifndef lint
1921176Sdist char copyright[] =
2036629Skarels "@(#) Copyright (c) 1983, 1988 The Regents of the University of California.\n\
2121176Sdist  All rights reserved.\n";
2235485Sbostic #endif /* not lint */
236454Swnj 
2421176Sdist #ifndef lint
25*36700Skarels static char sccsid[] = "@(#)rshd.c	5.19 (Berkeley) 02/07/89";
2635485Sbostic #endif /* not lint */
2721176Sdist 
2816370Skarels /*
2916370Skarels  * remote shell server:
3036629Skarels  *	[port]\0
3116370Skarels  *	remuser\0
3216370Skarels  *	locuser\0
3316370Skarels  *	command\0
3416370Skarels  *	data
3516370Skarels  */
3636629Skarels #include <sys/param.h>
376454Swnj #include <sys/ioctl.h>
386454Swnj #include <sys/socket.h>
3931025Sbostic #include <sys/file.h>
4027901Slepreau #include <sys/time.h>
419212Ssam 
429212Ssam #include <netinet/in.h>
439212Ssam 
4424903Sbloom #include <arpa/inet.h>
4524903Sbloom 
469212Ssam #include <stdio.h>
476454Swnj #include <errno.h>
486454Swnj #include <pwd.h>
496454Swnj #include <signal.h>
508380Ssam #include <netdb.h>
5117187Sralph #include <syslog.h>
526454Swnj 
536454Swnj int	errno;
5436600Sbostic int	keepalive = 1;
5527901Slepreau char	*index(), *rindex(), *strncat();
5627901Slepreau /*VARARGS1*/
576454Swnj int	error();
5816370Skarels 
5936645Skfall #ifdef	KERBEROS
6036645Skfall #include <kerberos/krb.h>
6136645Skfall #define	VERSION_SIZE	9
6236645Skfall #define	OPTIONS		"lnkv"
6336645Skfall char	*strsave();
6436645Skfall char	authbuf[sizeof(AUTH_DAT)];
6536645Skfall char	tickbuf[sizeof(KTEXT_ST)];
6636645Skfall int	use_kerberos = 0, vacuous = 0;
6736645Skfall 
6836645Skfall #define	OLD_RCMD		0x00
6936645Skfall #define	KERB_RCMD		0x00
7036645Skfall #define	KERB_RCMD_MUTUAL	0x03
7136645Skfall 
7236645Skfall int	encrypt = 0;
7336645Skfall #else
7436645Skfall #define	OPTIONS	"ln"
7536645Skfall #endif
7636645Skfall 
7727901Slepreau /*ARGSUSED*/
786454Swnj main(argc, argv)
796454Swnj 	int argc;
806454Swnj 	char **argv;
816454Swnj {
8236318Sbostic 	extern int opterr, optind, _check_rhosts_file;
8317156Ssam 	struct linger linger;
8436318Sbostic 	int ch, on = 1, fromlen;
856454Swnj 	struct sockaddr_in from;
866454Swnj 
8724851Seric 	openlog("rsh", LOG_PID | LOG_ODELAY, LOG_DAEMON);
8836318Sbostic 
8936318Sbostic 	opterr = 0;
9036645Skfall 	while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
9136318Sbostic 		switch((char)ch) {
9236318Sbostic 		case 'l':
9336318Sbostic 			_check_rhosts_file = 0;
9436318Sbostic 			break;
9536600Sbostic 		case 'n':
9636600Sbostic 			keepalive = 0;
9736600Sbostic 			break;
9836645Skfall #ifdef	KERBEROS
9936645Skfall 		case 'k':
10036645Skfall 			use_kerberos = 1;
10136645Skfall 			break;
10236645Skfall 
10336645Skfall 		case 'v':
10436645Skfall 			vacuous = 1;
10536645Skfall 			break;
10636645Skfall #endif
10736318Sbostic 		case '?':
10836318Sbostic 		default:
10936318Sbostic 			syslog(LOG_ERR, "usage: rshd [-l]");
11036318Sbostic 			break;
11136318Sbostic 		}
11236611Skfall 
11336318Sbostic 	argc -= optind;
11436318Sbostic 	argv += optind;
11536318Sbostic 
11636645Skfall #ifdef	KERBEROS
11736645Skfall 	if (use_kerberos && vacuous) {
11836645Skfall 		syslog(LOG_ERR, "only one of -k and -v allowed");
11936645Skfall 		exit(1);
12036645Skfall 	}
12136645Skfall #endif
12236611Skfall 
12316370Skarels 	fromlen = sizeof (from);
12416370Skarels 	if (getpeername(0, &from, &fromlen) < 0) {
12516370Skarels 		fprintf(stderr, "%s: ", argv[0]);
12616370Skarels 		perror("getpeername");
12716370Skarels 		_exit(1);
1288380Ssam 	}
12936600Sbostic 	if (keepalive &&
13036600Sbostic 	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
13136600Sbostic 	    sizeof(on)) < 0)
13217187Sralph 		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
13317156Ssam 	linger.l_onoff = 1;
13417156Ssam 	linger.l_linger = 60;			/* XXX */
13527901Slepreau 	if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
13627901Slepreau 	    sizeof (linger)) < 0)
13717187Sralph 		syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
138*36700Skarels 	doit(&from);
1396454Swnj }
1406454Swnj 
1416454Swnj char	username[20] = "USER=";
1426454Swnj char	homedir[64] = "HOME=";
1436454Swnj char	shell[64] = "SHELL=";
1446454Swnj char	*envinit[] =
14536629Skarels 	    {homedir, shell, "PATH=/usr/ucb:/bin:/usr/bin:", username, 0};
1466454Swnj char	**environ;
1476454Swnj 
148*36700Skarels doit(fromp)
1496454Swnj 	struct sockaddr_in *fromp;
1506454Swnj {
1516454Swnj 	char cmdbuf[NCARGS+1], *cp;
1526454Swnj 	char locuser[16], remuser[16];
1536454Swnj 	struct passwd *pwd;
15427901Slepreau 	int s;
1558380Ssam 	struct hostent *hp;
15625985Skarels 	char *hostname;
1576454Swnj 	short port;
15835485Sbostic 	int pv[2], pid, cc;
15936629Skarels 	int nfd;
16036629Skarels 	fd_set ready, readfrom;
1616454Swnj 	char buf[BUFSIZ], sig;
1626454Swnj 	int one = 1;
16336629Skarels 	char remotehost[2 * MAXHOSTNAMELEN + 1];
1646454Swnj 
16536645Skfall #ifdef	KERBEROS
16636645Skfall 	AUTH_DAT	*kdata = (AUTH_DAT *) NULL;
16736645Skfall 	KTEXT		ticket = (KTEXT) NULL;
16836645Skfall 	char		instance[INST_SZ], version[VERSION_SIZE];
16936645Skfall 	char		*h_name;
17036645Skfall 	struct		sockaddr_in	fromaddr;
17136645Skfall 	int		rc;
17236645Skfall 	long		authopts;
17336645Skfall 
17436645Skfall 	fromaddr = *fromp;
17536645Skfall #endif
17636645Skfall 
1776454Swnj 	(void) signal(SIGINT, SIG_DFL);
1786454Swnj 	(void) signal(SIGQUIT, SIG_DFL);
1796454Swnj 	(void) signal(SIGTERM, SIG_DFL);
18010883Ssam #ifdef DEBUG
1816454Swnj 	{ int t = open("/dev/tty", 2);
1826454Swnj 	  if (t >= 0) {
1836454Swnj 		ioctl(t, TIOCNOTTY, (char *)0);
1846454Swnj 		(void) close(t);
1856454Swnj 	  }
1866454Swnj 	}
1876454Swnj #endif
1886454Swnj 	fromp->sin_port = ntohs((u_short)fromp->sin_port);
18932108Skarels 	if (fromp->sin_family != AF_INET) {
19017187Sralph 		syslog(LOG_ERR, "malformed from address\n");
1916454Swnj 		exit(1);
19210596Ssam 	}
193*36700Skarels #ifdef IP_OPTIONS
194*36700Skarels       {
195*36700Skarels 	u_char optbuf[BUFSIZ/3], *cp;
196*36700Skarels 	char lbuf[BUFSIZ], *lp;
197*36700Skarels 	int optsize = sizeof(optbuf), ipproto;
198*36700Skarels 	struct protoent *ip;
19936611Skfall 
200*36700Skarels 	if ((ip = getprotobyname("ip")) != NULL)
201*36700Skarels 		ipproto = ip->p_proto;
202*36700Skarels 	else
203*36700Skarels 		ipproto = IPPROTO_IP;
204*36700Skarels 	if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) == 0 &&
205*36700Skarels 	    optsize != 0) {
206*36700Skarels 		lp = lbuf;
207*36700Skarels 		for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
208*36700Skarels 			sprintf(lp, " %2.2x", *cp);
209*36700Skarels 		syslog(LOG_NOTICE,
210*36700Skarels 		    "Connection received using IP options (ignored):%s", lbuf);
211*36700Skarels 		if (setsockopt(0, ipproto, IP_OPTIONS,
212*36700Skarels 		    (char *)NULL, &optsize) != 0) {
213*36700Skarels 			syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
214*36700Skarels 			exit(1);
215*36700Skarels 		}
216*36700Skarels 	}
217*36700Skarels       }
218*36700Skarels #endif
219*36700Skarels 
22036645Skfall #ifndef	KERBEROS
22132108Skarels 	if (fromp->sin_port >= IPPORT_RESERVED ||
22232108Skarels 	    fromp->sin_port < IPPORT_RESERVED/2) {
22336611Skfall 		syslog(LOG_NOTICE, "Connection from %s on illegal port",
22436611Skfall 			inet_ntoa(fromp->sin_addr));
22532108Skarels 		exit(1);
22632108Skarels 	}
22736645Skfall #endif
22836611Skfall 
2296454Swnj 	(void) alarm(60);
2306454Swnj 	port = 0;
2316454Swnj 	for (;;) {
2326454Swnj 		char c;
233*36700Skarels 		if ((cc = read(0, &c, 1)) != 1) {
23432108Skarels 			if (cc < 0)
23532108Skarels 				syslog(LOG_NOTICE, "read: %m");
236*36700Skarels 			shutdown(0, 1+1);
2376454Swnj 			exit(1);
23810596Ssam 		}
23936645Skfall #ifdef	KERBEROS
24036645Skfall 		if (c == OLD_RCMD || c == KERB_RCMD)
24136645Skfall 			break;
24236645Skfall 
24336645Skfall 		if (c == KERB_RCMD_MUTUAL) {
24436645Skfall 			encrypt = 1;
24536645Skfall 			break;
24636645Skfall 		}
24736645Skfall #else
2486454Swnj 		if (c == 0)
2496454Swnj 			break;
25036645Skfall #endif
2516454Swnj 		port = port * 10 + c - '0';
2526454Swnj 	}
25336611Skfall 
2546454Swnj 	(void) alarm(0);
2556454Swnj 	if (port != 0) {
25627901Slepreau 		int lport = IPPORT_RESERVED - 1;
25710273Ssam 		s = rresvport(&lport);
25810596Ssam 		if (s < 0) {
25917187Sralph 			syslog(LOG_ERR, "can't get stderr port: %m");
2606454Swnj 			exit(1);
26110596Ssam 		}
26236645Skfall #ifndef	KERBEROS
26310596Ssam 		if (port >= IPPORT_RESERVED) {
26417187Sralph 			syslog(LOG_ERR, "2nd port not reserved\n");
26510596Ssam 			exit(1);
26610596Ssam 		}
26736645Skfall #endif
2689243Ssam 		fromp->sin_port = htons((u_short)port);
26927901Slepreau 		if (connect(s, fromp, sizeof (*fromp)) < 0) {
27025985Skarels 			syslog(LOG_INFO, "connect second port: %m");
2716454Swnj 			exit(1);
27210596Ssam 		}
2736454Swnj 	}
27436611Skfall 
27536645Skfall #ifdef	KERBEROS
27636645Skfall 	if (vacuous) {
27736645Skfall 		error("rshd: remote host requires Kerberos authentication\n");
27836645Skfall 		exit(1);
27936645Skfall 	}
28036645Skfall #endif
28136645Skfall 
28236629Skarels #ifdef notdef
283*36700Skarels 	/* from inetd, socket is already on 0, 1, 2 */
28410596Ssam 	dup2(f, 0);
28510596Ssam 	dup2(f, 1);
28610596Ssam 	dup2(f, 2);
28736629Skarels #endif
28827901Slepreau 	hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
2898380Ssam 		fromp->sin_family);
29036611Skfall 	if (hp) {
29136629Skarels 		/*
29236629Skarels 		 * If name returned by gethostbyaddr is in our domain,
29336629Skarels 		 * attempt to verify that we haven't been fooled by someone
29436629Skarels 		 * in a remote net; look up the name and check that this
29536629Skarels 		 * address corresponds to the name.
29636629Skarels 		 */
29736629Skarels 		if (local_domain(hp->h_name)) {
29836629Skarels 			strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
29936629Skarels 			remotehost[sizeof(remotehost) - 1] = 0;
30036611Skfall 			hp = gethostbyname(remotehost);
30136629Skarels 			if (hp == NULL) {
30236629Skarels 				syslog(LOG_INFO,
30336629Skarels 				    "Couldn't look up address for %s",
30436629Skarels 				    remotehost);
30536629Skarels 				error("Couldn't look up address for your host");
30636611Skfall 				exit(1);
30736629Skarels 			} else for (; ; hp->h_addr_list++) {
30836629Skarels 				if (!bcmp(hp->h_addr_list[0],
30936629Skarels 				    (caddr_t)&fromp->sin_addr,
31036629Skarels 				    sizeof(fromp->sin_addr)))
31136629Skarels 					break;
31236629Skarels 				if (hp->h_addr_list[0] == NULL) {
31336629Skarels 					syslog(LOG_NOTICE,
31436629Skarels 					  "Host addr %s not listed for host %s",
31536629Skarels 					    inet_ntoa(fromp->sin_addr),
31636629Skarels 					    hp->h_name);
31736611Skfall 					error("Host address mismatch");
31836611Skfall 					exit(1);
31936611Skfall 				}
32036611Skfall 			}
32136611Skfall 		}
32225985Skarels 		hostname = hp->h_name;
32336629Skarels 	} else
32425985Skarels 		hostname = inet_ntoa(fromp->sin_addr);
32536611Skfall 
32636645Skfall #ifdef	KERBEROS
32736645Skfall 	if (use_kerberos) {
32836645Skfall 		h_name = strsave(hp->h_name);
32936645Skfall 		kdata = (AUTH_DAT *) authbuf;
33036645Skfall 		ticket = (KTEXT) tickbuf;
33136645Skfall 		authopts = 0L;
33236645Skfall 		strcpy(instance, "*");
33336645Skfall 		version[VERSION_SIZE - 1] = '\0';
334*36700Skarels 		if (rc = krb_recvauth(authopts, 0, ticket, "rcmd",
33536645Skfall 			instance, &fromaddr,
33636645Skfall 			(struct sockaddr_in *) 0,
33736645Skfall 			kdata, "", (bit_64 *) 0, version)) {
33836645Skfall 			fprintf(stderr,
33936645Skfall 				"Kerberos authentication failure: %s\r\n",
34036645Skfall 				  krb_err_txt[rc]);
34136645Skfall 			exit(1);
34236645Skfall 		}
34336645Skfall 		free(h_name);
34436645Skfall 		h_name = NULL;
34536645Skfall 	} else
34636645Skfall #endif
34736645Skfall 		getstr(remuser, sizeof(remuser), "remuser");
34836645Skfall 
3496454Swnj 	getstr(locuser, sizeof(locuser), "locuser");
3506454Swnj 	getstr(cmdbuf, sizeof(cmdbuf), "command");
3516454Swnj 	setpwent();
3526454Swnj 	pwd = getpwnam(locuser);
3536454Swnj 	if (pwd == NULL) {
3546454Swnj 		error("Login incorrect.\n");
3556454Swnj 		exit(1);
3566454Swnj 	}
3576454Swnj 	endpwent();
3586454Swnj 	if (chdir(pwd->pw_dir) < 0) {
35927901Slepreau 		(void) chdir("/");
36016370Skarels #ifdef notdef
3616454Swnj 		error("No remote directory.\n");
3626454Swnj 		exit(1);
36316370Skarels #endif
3646454Swnj 	}
36536611Skfall 
36636645Skfall #ifdef	KERBEROS
36736645Skfall 	if (use_kerberos) {
36836645Skfall 		if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
36936645Skfall 			if (krb_kntoln(kdata, remuser) != KSUCCESS) {
37036645Skfall 				error("Permission denied.\n");
37136645Skfall 				exit(1);
37236645Skfall 			}
37336645Skfall 			if (kuserok(kdata, locuser) != 0) {
37436645Skfall 				syslog(LOG_NOTICE, "Kerberos rlogin denied to %s.%s@%s",
37536645Skfall 					kdata->pname, kdata->pinst, kdata->prealm);
37636645Skfall 				error("Permission denied.\n");
37736645Skfall 				exit(1);
37836645Skfall 			}
37936645Skfall 		}
38036645Skfall 	} else
38136645Skfall #endif
38236611Skfall 
38336645Skfall 		if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
38436645Skfall 		    ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
38536645Skfall 			error("Permission denied.\n");
38636645Skfall 			exit(1);
38736645Skfall 		}
38836645Skfall 
38934011Sbostic 	if (pwd->pw_uid && !access("/etc/nologin", F_OK)) {
39031025Sbostic 		error("Logins currently disabled.\n");
39131025Sbostic 		exit(1);
39231025Sbostic 	}
39336645Skfall #ifdef	KERBEROS
39436645Skfall 	if (encrypt) {
39536645Skfall 		char c = KERB_RCMD_MUTUAL;
39636645Skfall 		(void) write(2, &c, 1);
39736645Skfall 	} else {
39836645Skfall 		char c = KERB_RCMD;
39936645Skfall 		(void) write(2, &c, 1);
40036645Skfall 	}
40136645Skfall #else
4026454Swnj 	(void) write(2, "\0", 1);
40336645Skfall #endif
40436611Skfall 
4056454Swnj 	if (port) {
4066454Swnj 		if (pipe(pv) < 0) {
4076454Swnj 			error("Can't make pipe.\n");
4086454Swnj 			exit(1);
4096454Swnj 		}
4106454Swnj 		pid = fork();
4116454Swnj 		if (pid == -1)  {
4126454Swnj 			error("Try again.\n");
4136454Swnj 			exit(1);
4146454Swnj 		}
41536629Skarels 		if (pv[0] > s)
41636629Skarels 			nfd = pv[0];
41736629Skarels 		else
41836629Skarels 			nfd = s;
41936629Skarels 		nfd++;
4206454Swnj 		if (pid) {
4216454Swnj 			(void) close(0); (void) close(1); (void) close(2);
422*36700Skarels 			(void) close(pv[1]);
42336629Skarels 			FD_ZERO(&readfrom);
42436629Skarels 			FD_SET(s, &readfrom);
42536629Skarels 			FD_SET(pv[0], &readfrom);
42630265Smckusick 			ioctl(pv[0], FIONBIO, (char *)&one);
4276454Swnj 			/* should set s nbio! */
4286454Swnj 			do {
4296454Swnj 				ready = readfrom;
43036629Skarels 				if (select(nfd, &ready, (fd_set *)0,
43127901Slepreau 				    (fd_set *)0, (struct timeval *)0) < 0)
4329212Ssam 					break;
43336629Skarels 				if (FD_ISSET(s, &ready)) {
4346454Swnj 					if (read(s, &sig, 1) <= 0)
43536629Skarels 						FD_CLR(s, &readfrom);
4366454Swnj 					else
4376454Swnj 						killpg(pid, sig);
4386454Swnj 				}
43936629Skarels 				if (FD_ISSET(pv[0], &ready)) {
44011238Ssam 					errno = 0;
4416454Swnj 					cc = read(pv[0], buf, sizeof (buf));
4426454Swnj 					if (cc <= 0) {
44310194Ssam 						shutdown(s, 1+1);
44436629Skarels 						FD_CLR(pv[0], &readfrom);
4456454Swnj 					} else
4466454Swnj 						(void) write(s, buf, cc);
4476454Swnj 				}
44836629Skarels 			} while (FD_ISSET(s, &readfrom) ||
44936629Skarels 			    FD_ISSET(pv[0], &readfrom));
4506454Swnj 			exit(0);
4516454Swnj 		}
4526454Swnj 		setpgrp(0, getpid());
4536454Swnj 		(void) close(s); (void) close(pv[0]);
4546454Swnj 		dup2(pv[1], 2);
45536645Skfall 		close(pv[1]);
4566454Swnj 	}
4576454Swnj 	if (*pwd->pw_shell == '\0')
4586454Swnj 		pwd->pw_shell = "/bin/sh";
45927901Slepreau 	(void) setgid((gid_t)pwd->pw_gid);
4609212Ssam 	initgroups(pwd->pw_name, pwd->pw_gid);
46127901Slepreau 	(void) setuid((uid_t)pwd->pw_uid);
4626454Swnj 	environ = envinit;
4636454Swnj 	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
4646454Swnj 	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
4656454Swnj 	strncat(username, pwd->pw_name, sizeof(username)-6);
4666454Swnj 	cp = rindex(pwd->pw_shell, '/');
4676454Swnj 	if (cp)
4686454Swnj 		cp++;
4696454Swnj 	else
4706454Swnj 		cp = pwd->pw_shell;
4716454Swnj 	execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
4726454Swnj 	perror(pwd->pw_shell);
4736454Swnj 	exit(1);
4746454Swnj }
4756454Swnj 
47627901Slepreau /*VARARGS1*/
47725663Smckusick error(fmt, a1, a2, a3)
4786454Swnj 	char *fmt;
47925663Smckusick 	int a1, a2, a3;
4806454Swnj {
4816454Swnj 	char buf[BUFSIZ];
4826454Swnj 
4836454Swnj 	buf[0] = 1;
48425663Smckusick 	(void) sprintf(buf+1, fmt, a1, a2, a3);
4856454Swnj 	(void) write(2, buf, strlen(buf));
4866454Swnj }
4876454Swnj 
4886454Swnj getstr(buf, cnt, err)
4896454Swnj 	char *buf;
4906454Swnj 	int cnt;
4916454Swnj 	char *err;
4926454Swnj {
4936454Swnj 	char c;
4946454Swnj 
4956454Swnj 	do {
4966454Swnj 		if (read(0, &c, 1) != 1)
4976454Swnj 			exit(1);
4986454Swnj 		*buf++ = c;
4996454Swnj 		if (--cnt == 0) {
5006454Swnj 			error("%s too long\n", err);
5016454Swnj 			exit(1);
5026454Swnj 		}
5036454Swnj 	} while (c != 0);
5046454Swnj }
50536611Skfall 
50636629Skarels /*
50736629Skarels  * Check whether host h is in our local domain,
50836629Skarels  * as determined by the part of the name following
50936629Skarels  * the first '.' in its name and in ours.
51036629Skarels  * If either name is unqualified (contains no '.'),
51136629Skarels  * assume that the host is local, as it will be
51236629Skarels  * interpreted as such.
51336629Skarels  */
51436629Skarels local_domain(h)
51536629Skarels 	char *h;
51636611Skfall {
51736629Skarels 	char localhost[MAXHOSTNAMELEN];
51836629Skarels 	char *p1, *p2 = index(h, '.');
51936629Skarels 
52036629Skarels 	(void) gethostname(localhost, sizeof(localhost));
52136629Skarels 	p1 = index(localhost, '.');
52236629Skarels 	if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
52336611Skfall 		return(1);
52436611Skfall 	return(0);
52536611Skfall }
526