xref: /original-bsd/usr.sbin/sendmail/src/daemon.c (revision e2de2524)
1939f5b94Sdist /*
20942ea6aSbostic  * Copyright (c) 1983 Eric P. Allman
3da1c6175Sbostic  * Copyright (c) 1988 Regents of the University of California.
4da1c6175Sbostic  * All rights reserved.
5da1c6175Sbostic  *
63bc94712Sbostic  * %sccs.include.redist.c%
7939f5b94Sdist  */
8939f5b94Sdist 
97aa493c5Seric #include <errno.h>
10a8c080f0Seric #include <signal.h>
116c05f684Sbostic #include "sendmail.h"
127fa39d90Seric 
13af5e902cSeric #ifndef lint
14da1c6175Sbostic #ifdef DAEMON
15*e2de2524Seric static char sccsid[] = "@(#)daemon.c	6.15 (Berkeley) 03/07/93 (with daemon mode)";
16d0a9e852Seric #else
17*e2de2524Seric static char sccsid[] = "@(#)daemon.c	6.15 (Berkeley) 03/07/93 (without daemon mode)";
18da1c6175Sbostic #endif
19da1c6175Sbostic #endif /* not lint */
20da1c6175Sbostic 
21da1c6175Sbostic #ifdef DAEMON
22d0a9e852Seric 
231c71e510Seric # include <netdb.h>
241e1663f7Swnj # include <sys/wait.h>
25af5e902cSeric # include <sys/time.h>
26d0a9e852Seric 
277fa39d90Seric /*
287fa39d90Seric **  DAEMON.C -- routines to use when running as a daemon.
2947b12ae1Seric **
3047b12ae1Seric **	This entire file is highly dependent on the 4.2 BSD
3147b12ae1Seric **	interprocess communication primitives.  No attempt has
3247b12ae1Seric **	been made to make this file portable to Version 7,
3347b12ae1Seric **	Version 6, MPX files, etc.  If you should try such a
3447b12ae1Seric **	thing yourself, I recommend chucking the entire file
3547b12ae1Seric **	and starting from scratch.  Basic semantics are:
3647b12ae1Seric **
3747b12ae1Seric **	getrequests()
3847b12ae1Seric **		Opens a port and initiates a connection.
3947b12ae1Seric **		Returns in a child.  Must set InChannel and
4047b12ae1Seric **		OutChannel appropriately.
41b7d7afcbSeric **	clrdaemon()
42b7d7afcbSeric **		Close any open files associated with getting
43b7d7afcbSeric **		the connection; this is used when running the queue,
44b7d7afcbSeric **		etc., to avoid having extra file descriptors during
45b7d7afcbSeric **		the queue run and to avoid confusing the network
46b7d7afcbSeric **		code (if it cares).
47914346b1Seric **	makeconnection(host, port, outfile, infile, usesecureport)
4847b12ae1Seric **		Make a connection to the named host on the given
4947b12ae1Seric **		port.  Set *outfile and *infile to the files
5047b12ae1Seric **		appropriate for communication.  Returns zero on
5147b12ae1Seric **		success, else an exit status describing the
5247b12ae1Seric **		error.
5305b57da8Seric **	maphostname(map, hbuf, hbufsiz, avp)
5405b57da8Seric **		Convert the entry in hbuf into a canonical form.
557fa39d90Seric */
567fa39d90Seric /*
577fa39d90Seric **  GETREQUESTS -- open mail IPC port and get requests.
587fa39d90Seric **
597fa39d90Seric **	Parameters:
607fa39d90Seric **		none.
617fa39d90Seric **
627fa39d90Seric **	Returns:
637fa39d90Seric **		none.
647fa39d90Seric **
657fa39d90Seric **	Side Effects:
667fa39d90Seric **		Waits until some interesting activity occurs.  When
677fa39d90Seric **		it does, a child is created to process it, and the
687fa39d90Seric **		parent waits for completion.  Return from this
69147303b1Seric **		routine is always in the child.  The file pointers
70147303b1Seric **		"InChannel" and "OutChannel" should be set to point
71147303b1Seric **		to the communication channel.
727fa39d90Seric */
737fa39d90Seric 
74b7d7afcbSeric int	DaemonSocket	= -1;		/* fd describing socket */
751c71e510Seric 
767fa39d90Seric getrequests()
777fa39d90Seric {
781c71e510Seric 	int t;
791c71e510Seric 	register struct servent *sp;
807868dfc2Seric 	int on = 1;
8115d084d5Seric 	bool refusingconnections = TRUE;
820aae1086Seric 	FILE *pidf;
83914346b1Seric 	struct sockaddr_in srvraddr;
849b100374Sbostic 	extern void reapchild();
85eb889047Seric 
86a8268164Seric 	/*
871c71e510Seric 	**  Set up the address for the mailer.
88eb889047Seric 	*/
89eb889047Seric 
901c71e510Seric 	sp = getservbyname("smtp", "tcp");
911c71e510Seric 	if (sp == NULL)
92d0a9e852Seric 	{
9308b25121Seric 		syserr("554 server \"smtp\" unknown");
94a1961f2aSeric 		goto severe;
951c71e510Seric 	}
96914346b1Seric 	srvraddr.sin_family = AF_INET;
97914346b1Seric 	srvraddr.sin_addr.s_addr = INADDR_ANY;
98914346b1Seric 	srvraddr.sin_port = sp->s_port;
991c71e510Seric 
1001c71e510Seric 	/*
1011c71e510Seric 	**  Try to actually open the connection.
1021c71e510Seric 	*/
1031c71e510Seric 
1041c71e510Seric 	if (tTd(15, 1))
105914346b1Seric 		printf("getrequests: port 0x%x\n", srvraddr.sin_port);
1061c71e510Seric 
1071c71e510Seric 	/* get a socket for the SMTP connection */
108af5e902cSeric 	DaemonSocket = socket(AF_INET, SOCK_STREAM, 0);
109b7d7afcbSeric 	if (DaemonSocket < 0)
1101c71e510Seric 	{
1111c71e510Seric 		/* probably another daemon already */
1121c71e510Seric 		syserr("getrequests: can't create socket");
1131c71e510Seric 	  severe:
114b0ba8827Seric # ifdef LOG
115b0ba8827Seric 		if (LogLevel > 0)
1160c034190Seric 			syslog(LOG_ALERT, "problem creating SMTP socket");
1176c2c3107Seric # endif /* LOG */
11847b12ae1Seric 		finis();
119d0a9e852Seric 	}
1201b6e4a15Seric 
1211b6e4a15Seric 	/* turn on network debugging? */
122a2ef5fa4Seric 	if (tTd(15, 101))
12352308a50Seric 		(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
1241b6e4a15Seric 
1257868dfc2Seric 	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
1267868dfc2Seric 	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
1277868dfc2Seric 
128914346b1Seric 	if (bind(DaemonSocket, (struct sockaddr *)&srvraddr, sizeof srvraddr) < 0)
1291c71e510Seric 	{
1301c71e510Seric 		syserr("getrequests: cannot bind");
131b7d7afcbSeric 		(void) close(DaemonSocket);
1321c71e510Seric 		goto severe;
1331c71e510Seric 	}
1341c71e510Seric 
1351cd247eeSeric 	(void) signal(SIGCHLD, reapchild);
13652308a50Seric 
1370aae1086Seric 	/* write the pid to the log file for posterity */
1380aae1086Seric 	pidf = fopen(PidFile, "w");
1390aae1086Seric 	if (pidf != NULL)
1400aae1086Seric 	{
1410aae1086Seric 		fprintf(pidf, "%d\n", getpid());
1420aae1086Seric 		fclose(pidf);
1430aae1086Seric 	}
1440aae1086Seric 
1450aae1086Seric 
1461c71e510Seric 	if (tTd(15, 1))
147b7d7afcbSeric 		printf("getrequests: %d\n", DaemonSocket);
1481c71e510Seric 
1491c71e510Seric 	for (;;)
1501c71e510Seric 	{
1513a099713Seric 		register int pid;
152a44d5a5eSeric 		auto int lotherend;
15315d084d5Seric 		extern bool refuseconnections();
1543a099713Seric 
1553a099713Seric 		/* see if we are rejecting connections */
15615d084d5Seric 		CurrentLA = getla();
15715d084d5Seric 		if (refuseconnections())
1586775ec03Sbostic 		{
15915d084d5Seric 			if (!refusingconnections)
16015d084d5Seric 			{
16115d084d5Seric 				/* don't queue so peer will fail quickly */
16215d084d5Seric 				(void) listen(DaemonSocket, 0);
16315d084d5Seric 				refusingconnections = TRUE;
16415d084d5Seric 			}
16571e5e267Seric 			setproctitle("rejecting connections: load average: %d",
16671e5e267Seric 				CurrentLA);
1673a099713Seric 			sleep(5);
16815d084d5Seric 			continue;
16915d084d5Seric 		}
17015d084d5Seric 
17115d084d5Seric 		if (refusingconnections)
17215d084d5Seric 		{
17315d084d5Seric 			/* start listening again */
17415d084d5Seric 			if (listen(DaemonSocket, 10) < 0)
17515d084d5Seric 			{
17615d084d5Seric 				syserr("getrequests: cannot listen");
17715d084d5Seric 				(void) close(DaemonSocket);
17815d084d5Seric 				goto severe;
17915d084d5Seric 			}
18015d084d5Seric 			setproctitle("accepting connections");
18115d084d5Seric 			refusingconnections = FALSE;
1826775ec03Sbostic 		}
183a44d5a5eSeric 
1841c71e510Seric 		/* wait for a connection */
1851c71e510Seric 		do
1861c71e510Seric 		{
1871c71e510Seric 			errno = 0;
1889f9a15b6Skarels 			lotherend = sizeof RealHostAddr;
1899b100374Sbostic 			t = accept(DaemonSocket,
1909b100374Sbostic 			    (struct sockaddr *)&RealHostAddr, &lotherend);
1911c71e510Seric 		} while (t < 0 && errno == EINTR);
1921c71e510Seric 		if (t < 0)
1931c71e510Seric 		{
1941c71e510Seric 			syserr("getrequests: accept");
1951c71e510Seric 			sleep(5);
1961c71e510Seric 			continue;
1971c71e510Seric 		}
198d0a9e852Seric 
199d0a9e852Seric 		/*
200d0a9e852Seric 		**  Create a subprocess to process the mail.
201d0a9e852Seric 		*/
202d0a9e852Seric 
20361e4310fSeric 		if (tTd(15, 2))
2041c71e510Seric 			printf("getrequests: forking (fd = %d)\n", t);
205eb889047Seric 
206a8268164Seric 		pid = fork();
207a8268164Seric 		if (pid < 0)
208a8268164Seric 		{
209a8268164Seric 			syserr("daemon: cannot fork");
210a8268164Seric 			sleep(10);
2111c71e510Seric 			(void) close(t);
212a8268164Seric 			continue;
213a8268164Seric 		}
214a8268164Seric 
215a8268164Seric 		if (pid == 0)
216a8268164Seric 		{
217a44d5a5eSeric 			extern struct hostent *gethostbyaddr();
218a44d5a5eSeric 			register struct hostent *hp;
219a44d5a5eSeric 			char buf[MAXNAME];
220f067e11eSeric 			extern char *inet_ntoa();
221a44d5a5eSeric 
222a8268164Seric 			/*
223a8268164Seric 			**  CHILD -- return to caller.
224a44d5a5eSeric 			**	Collect verified idea of sending host.
225a8268164Seric 			**	Verify calling user id if possible here.
226a8268164Seric 			*/
227a8268164Seric 
2281cd247eeSeric 			(void) signal(SIGCHLD, SIG_DFL);
229779ac194Seric 
230a44d5a5eSeric 			/* determine host name */
2319f9a15b6Skarels 			hp = gethostbyaddr((char *) &RealHostAddr.sin_addr, sizeof RealHostAddr.sin_addr, AF_INET);
232a44d5a5eSeric 			if (hp != NULL)
233fefbbe29Seric 				(void) strcpy(buf, hp->h_name);
234a44d5a5eSeric 			else
23529dcf4baSeric 			{
23629dcf4baSeric 				/* produce a dotted quad */
23729dcf4baSeric 				(void) sprintf(buf, "[%s]",
2389f9a15b6Skarels 					inet_ntoa(RealHostAddr.sin_addr));
23929dcf4baSeric 			}
24029dcf4baSeric 
2412a6bc25bSeric #ifdef LOG
242845e533cSeric 			if (LogLevel > 10)
2432a6bc25bSeric 			{
2442a6bc25bSeric 				/* log connection information */
2452a6bc25bSeric 				syslog(LOG_INFO, "connect from %s (%s)",
2462a6bc25bSeric 					buf, inet_ntoa(RealHostAddr.sin_addr));
2472a6bc25bSeric 			}
2482a6bc25bSeric #endif
2492a6bc25bSeric 
25029dcf4baSeric 			/* should we check for illegal connection here? XXX */
25129dcf4baSeric 
252a44d5a5eSeric 			RealHostName = newstr(buf);
253a44d5a5eSeric 
254b7d7afcbSeric 			(void) close(DaemonSocket);
2551c71e510Seric 			InChannel = fdopen(t, "r");
2561d5bd586Seric 			OutChannel = fdopen(dup(t), "w");
25761e4310fSeric 			if (tTd(15, 2))
258d0a9e852Seric 				printf("getreq: returning\n");
259252c8a22Seric # ifdef LOG
260252c8a22Seric 			if (LogLevel > 11)
261252c8a22Seric 				syslog(LOG_DEBUG, "connected, pid=%d", getpid());
2626c2c3107Seric # endif /* LOG */
263a8268164Seric 			return;
264a8268164Seric 		}
265a8268164Seric 
2663c154354Seric 		/* close the port so that others will hang (for a while) */
2673c154354Seric 		(void) close(t);
2688e3e4b17Seric 	}
2693c154354Seric 	/*NOTREACHED*/
2703c154354Seric }
2718e3e4b17Seric /*
272b7d7afcbSeric **  CLRDAEMON -- reset the daemon connection
273b7d7afcbSeric **
274b7d7afcbSeric **	Parameters:
275b7d7afcbSeric **		none.
276b7d7afcbSeric **
277b7d7afcbSeric **	Returns:
278b7d7afcbSeric **		none.
279b7d7afcbSeric **
280b7d7afcbSeric **	Side Effects:
281b7d7afcbSeric **		releases any resources used by the passive daemon.
282b7d7afcbSeric */
283b7d7afcbSeric 
284b7d7afcbSeric clrdaemon()
285b7d7afcbSeric {
286b7d7afcbSeric 	if (DaemonSocket >= 0)
287b7d7afcbSeric 		(void) close(DaemonSocket);
288b7d7afcbSeric 	DaemonSocket = -1;
289b7d7afcbSeric }
290b7d7afcbSeric /*
2917aa493c5Seric **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
2927aa493c5Seric **
2937aa493c5Seric **	Parameters:
2947aa493c5Seric **		host -- the name of the host.
29548ff0a9dSeric **		port -- the port number to connect to.
296655feedbSeric **		mci -- a pointer to the mail connection information
297655feedbSeric **			structure to be filled in.
298914346b1Seric **		usesecureport -- if set, use a low numbered (reserved)
299914346b1Seric **			port to provide some rudimentary authentication.
3007aa493c5Seric **
3017aa493c5Seric **	Returns:
3027aa493c5Seric **		An exit code telling whether the connection could be
3037aa493c5Seric **			made and if not why not.
3047aa493c5Seric **
3057aa493c5Seric **	Side Effects:
3067aa493c5Seric **		none.
3077aa493c5Seric */
3087aa493c5Seric 
30971ff6caaSeric struct sockaddr_in	CurHostAddr;		/* address of current host */
31071ff6caaSeric 
311b31e7f2bSeric int
312655feedbSeric makeconnection(host, port, mci, usesecureport)
3137aa493c5Seric 	char *host;
314210215eaSeric 	u_short port;
315b31e7f2bSeric 	register MCI *mci;
316914346b1Seric 	bool usesecureport;
3177aa493c5Seric {
31804344589Sbloom 	register int i, s;
31904344589Sbloom 	register struct hostent *hp = (struct hostent *)NULL;
320914346b1Seric 	struct sockaddr_in addr;
3216286bb75Sbloom 	int sav_errno;
322914346b1Seric 	extern char *inet_ntoa();
323134746fbSeric #ifdef NAMED_BIND
324134746fbSeric 	extern int h_errno;
325134746fbSeric #endif
3267aa493c5Seric 
3277aa493c5Seric 	/*
3287aa493c5Seric 	**  Set up the address for the mailer.
32971096d12Seric 	**	Accept "[a.b.c.d]" syntax for host name.
3307aa493c5Seric 	*/
3317aa493c5Seric 
332134746fbSeric #ifdef NAMED_BIND
333794bdbb9Smiriam 	h_errno = 0;
334134746fbSeric #endif
335794bdbb9Smiriam 	errno = 0;
336794bdbb9Smiriam 
33771096d12Seric 	if (host[0] == '[')
33871096d12Seric 	{
339a44d5a5eSeric 		long hid;
3406c2c3107Seric 		register char *p = strchr(host, ']');
34171096d12Seric 
342a44d5a5eSeric 		if (p != NULL)
34371096d12Seric 		{
344a44d5a5eSeric 			*p = '\0';
345a44d5a5eSeric 			hid = inet_addr(&host[1]);
346a7e21fe6Seric 			if (hid == -1)
347a7e21fe6Seric 			{
348a7e21fe6Seric 				/* try it as a host name (avoid MX lookup) */
349a7e21fe6Seric 				hp = gethostbyname(&host[1]);
350a7e21fe6Seric 				*p = ']';
351a7e21fe6Seric 				goto gothostent;
352a7e21fe6Seric 			}
353a44d5a5eSeric 			*p = ']';
35471096d12Seric 		}
355a7e21fe6Seric 		if (p == NULL)
35671096d12Seric 		{
35708b25121Seric 			usrerr("553 Invalid numeric domain spec \"%s\"", host);
35871096d12Seric 			return (EX_NOHOST);
35971096d12Seric 		}
360914346b1Seric 		addr.sin_addr.s_addr = hid;
36171096d12Seric 	}
3621c71e510Seric 	else
3631c71e510Seric 	{
36404344589Sbloom 		hp = gethostbyname(host);
365a7e21fe6Seric gothostent:
366794bdbb9Smiriam 		if (hp == NULL)
367794bdbb9Smiriam 		{
368134746fbSeric #ifdef NAMED_BIND
369794bdbb9Smiriam 			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN)
37052308a50Seric 				return (EX_TEMPFAIL);
37182e5d8ddSeric 
372134746fbSeric 			/* if name server is specified, assume temp fail */
373134746fbSeric 			if (errno == ECONNREFUSED && UseNameServer)
374134746fbSeric 				return (EX_TEMPFAIL);
375134746fbSeric #endif
3767aa493c5Seric 			return (EX_NOHOST);
377794bdbb9Smiriam 		}
378914346b1Seric 		bcopy(hp->h_addr, (char *) &addr.sin_addr, hp->h_length);
37904344589Sbloom 		i = 1;
3801c71e510Seric 	}
3811c71e510Seric 
3821c71e510Seric 	/*
3831c71e510Seric 	**  Determine the port number.
3841c71e510Seric 	*/
3851c71e510Seric 
386fd7c0790Seric 	if (port != 0)
387914346b1Seric 		addr.sin_port = htons(port);
388fd7c0790Seric 	else
3891c71e510Seric 	{
3901c71e510Seric 		register struct servent *sp = getservbyname("smtp", "tcp");
3911c71e510Seric 
3921c71e510Seric 		if (sp == NULL)
3931c71e510Seric 		{
39408b25121Seric 			syserr("554 makeconnection: server \"smtp\" unknown");
395845e533cSeric 			return (EX_OSERR);
3961c71e510Seric 		}
397914346b1Seric 		addr.sin_port = sp->s_port;
3981c71e510Seric 	}
3997aa493c5Seric 
4007aa493c5Seric 	/*
4017aa493c5Seric 	**  Try to actually open the connection.
4027aa493c5Seric 	*/
4037aa493c5Seric 
404aea02ca1Seric 	for (;;)
405aea02ca1Seric 	{
40661e4310fSeric 		if (tTd(16, 1))
40704344589Sbloom 			printf("makeconnection (%s [%s])\n", host,
408914346b1Seric 			    inet_ntoa(addr.sin_addr));
4097aa493c5Seric 
410914346b1Seric 		if (usesecureport)
411914346b1Seric 		{
412914346b1Seric 			int rport = IPPORT_RESERVED - 1;
413914346b1Seric 
414914346b1Seric 			s = rresvport(&rport);
415914346b1Seric 		}
416914346b1Seric 		else
417914346b1Seric 		{
418af5e902cSeric 			s = socket(AF_INET, SOCK_STREAM, 0);
419914346b1Seric 		}
4207aa493c5Seric 		if (s < 0)
4217aa493c5Seric 		{
4226286bb75Sbloom 			sav_errno = errno;
423914346b1Seric 			syserr("makeconnection: no socket");
4247aa493c5Seric 			goto failure;
4257aa493c5Seric 		}
4267aa493c5Seric 
42761e4310fSeric 		if (tTd(16, 1))
428b31e7f2bSeric 			printf("makeconnection: fd=%d\n", s);
4291b6e4a15Seric 
4301b6e4a15Seric 		/* turn on network debugging? */
431a2ef5fa4Seric 		if (tTd(16, 101))
43252308a50Seric 		{
43352308a50Seric 			int on = 1;
434aea02ca1Seric 			(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG,
435aea02ca1Seric 					  (char *)&on, sizeof on);
43652308a50Seric 		}
43787d6e633Srick 		if (CurEnv->e_xfp != NULL)
438877a6142Seric 			(void) fflush(CurEnv->e_xfp);		/* for debugging */
4394bd6a662Seric 		errno = 0;					/* for debugging */
440914346b1Seric 		addr.sin_family = AF_INET;
441aea02ca1Seric 		if (connect(s, (struct sockaddr *) &addr, sizeof addr) >= 0)
442aea02ca1Seric 			break;
443aea02ca1Seric 
444aea02ca1Seric 		/* couldn't connect.... figure out why */
4456286bb75Sbloom 		sav_errno = errno;
4466286bb75Sbloom 		(void) close(s);
44704344589Sbloom 		if (hp && hp->h_addr_list[i])
44804344589Sbloom 		{
449aea02ca1Seric 			if (tTd(16, 1))
450aea02ca1Seric 				printf("Connect failed; trying new address....\n");
451914346b1Seric 			bcopy(hp->h_addr_list[i++], (char *) &addr.sin_addr,
452914346b1Seric 					hp->h_length);
453aea02ca1Seric 			continue;
45404344589Sbloom 		}
45504344589Sbloom 
4567aa493c5Seric 		/* failure, decide if temporary or not */
4577aa493c5Seric 	failure:
458*e2de2524Seric 		if (transienterror(sav_errno))
459*e2de2524Seric 			return EX_TEMPFAIL;
460*e2de2524Seric 		else if (sav_errno == EPERM)
4617aa493c5Seric 		{
462a44d5a5eSeric 			/* why is this happening? */
463a44d5a5eSeric 			syserr("makeconnection: funny failure, addr=%lx, port=%x",
464914346b1Seric 				addr.sin_addr.s_addr, addr.sin_port);
4654bd6a662Seric 			return (EX_TEMPFAIL);
466*e2de2524Seric 		}
467*e2de2524Seric 		else
46887d6e633Srick 		{
46987d6e633Srick 			extern char *errstring();
47087d6e633Srick 
47108b25121Seric 			message("%s", errstring(sav_errno));
4727aa493c5Seric 			return (EX_UNAVAILABLE);
4737aa493c5Seric 		}
4747aa493c5Seric 	}
4757aa493c5Seric 
4767aa493c5Seric 	/* connection ok, put it into canonical form */
477655feedbSeric 	mci->mci_out = fdopen(s, "w");
478655feedbSeric 	mci->mci_in = fdopen(dup(s), "r");
4797aa493c5Seric 
48071ff6caaSeric 	/* save for logging */
48171ff6caaSeric 	CurHostAddr = addr;
48271ff6caaSeric 
483dca8e1f7Seric 	return (EX_OK);
4847aa493c5Seric }
485444eaf03Seric /*
486444eaf03Seric **  MYHOSTNAME -- return the name of this host.
487444eaf03Seric **
488444eaf03Seric **	Parameters:
489444eaf03Seric **		hostbuf -- a place to return the name of this host.
490897f1869Seric **		size -- the size of hostbuf.
491444eaf03Seric **
492444eaf03Seric **	Returns:
493444eaf03Seric **		A list of aliases for this host.
494444eaf03Seric **
495444eaf03Seric **	Side Effects:
49638ad259dSeric **		Sets the MyIpAddrs buffer to a list of my IP addresses.
497444eaf03Seric */
498444eaf03Seric 
49938ad259dSeric struct in_addr	MyIpAddrs[MAXIPADDR + 1];
50038ad259dSeric 
501444eaf03Seric char **
502897f1869Seric myhostname(hostbuf, size)
503444eaf03Seric 	char hostbuf[];
504897f1869Seric 	int size;
505444eaf03Seric {
50638ad259dSeric 	register struct hostent *hp;
507444eaf03Seric 	extern struct hostent *gethostbyname();
508444eaf03Seric 
509af5e902cSeric 	if (gethostname(hostbuf, size) < 0)
510af5e902cSeric 	{
511af5e902cSeric 		(void) strcpy(hostbuf, "localhost");
512af5e902cSeric 	}
513a44d5a5eSeric 	hp = gethostbyname(hostbuf);
514a44d5a5eSeric 	if (hp != NULL)
5157364df9fSeric 	{
51638ad259dSeric 		(void) strncpy(hostbuf, hp->h_name, size - 1);
51738ad259dSeric 		hostbuf[size - 1] = '\0';
51838ad259dSeric 
51938ad259dSeric 		if (hp->h_addrtype == AF_INET && hp->h_length == 4)
52038ad259dSeric 		{
52138ad259dSeric 			register int i;
52238ad259dSeric 
52338ad259dSeric 			for (i = 0; i < MAXIPADDR; i++)
52438ad259dSeric 			{
52538ad259dSeric 				if (hp->h_addr_list[i] == NULL)
52638ad259dSeric 					break;
52738ad259dSeric 				MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i];
52838ad259dSeric 			}
52938ad259dSeric 			MyIpAddrs[i].s_addr = 0;
53038ad259dSeric 		}
53138ad259dSeric 
532a44d5a5eSeric 		return (hp->h_aliases);
5337364df9fSeric 	}
534444eaf03Seric 	else
535444eaf03Seric 		return (NULL);
536444eaf03Seric }
537cb452edcSeric /*
538320e0d1cSeric **  GETREALHOSTNAME -- get the real host name asociated with a file descriptor
539320e0d1cSeric **
540320e0d1cSeric **	Parameters:
541320e0d1cSeric **		fd -- the descriptor
542320e0d1cSeric **
543320e0d1cSeric **	Returns:
544320e0d1cSeric **		The host name associated with this descriptor, if it can
545320e0d1cSeric **			be determined.
546320e0d1cSeric **		NULL otherwise.
547320e0d1cSeric **
548320e0d1cSeric **	Side Effects:
549320e0d1cSeric **		none
550320e0d1cSeric */
551320e0d1cSeric 
552320e0d1cSeric char *
553320e0d1cSeric getrealhostname(fd)
554320e0d1cSeric 	int fd;
555320e0d1cSeric {
556320e0d1cSeric 	register struct hostent *hp;
557320e0d1cSeric 	struct sockaddr_in sin;
558320e0d1cSeric 	int sinlen;
559320e0d1cSeric 	char hbuf[MAXNAME];
560320e0d1cSeric 	extern struct hostent *gethostbyaddr();
561320e0d1cSeric 	extern char *inet_ntoa();
562320e0d1cSeric 
56328f70721Seric 	if (getsockname(fd, (struct sockaddr *) &sin, &sinlen) < 0 ||
56428f70721Seric 	    sinlen <= 0)
565320e0d1cSeric 		return NULL;
566320e0d1cSeric 	hp = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
567320e0d1cSeric 			   sin.sin_family);
568320e0d1cSeric 	if (hp != NULL)
569320e0d1cSeric 		(void) strcpy(hbuf, hp->h_name);
570320e0d1cSeric 	else
571320e0d1cSeric 		(void) sprintf(hbuf, "[%s]", inet_ntoa(sin.sin_addr));
572320e0d1cSeric 	return hbuf;
573320e0d1cSeric }
574320e0d1cSeric /*
57515d084d5Seric **  MAPHOSTNAME -- turn a hostname into canonical form
57615d084d5Seric **
57715d084d5Seric **	Parameters:
57805b57da8Seric **		map -- a pointer to this map (unused).
57915d084d5Seric **		hbuf -- a buffer containing a hostname.
58015d084d5Seric **		hbsize -- the size of hbuf.
581d798a1deSeric **		avp -- unused -- for compatibility with other mapping
582d798a1deSeric **			functions.
58315d084d5Seric **
58415d084d5Seric **	Returns:
58515d084d5Seric **		The mapping, if found.
58615d084d5Seric **		NULL if no mapping found.
58715d084d5Seric **
58815d084d5Seric **	Side Effects:
58915d084d5Seric **		Looks up the host specified in hbuf.  If it is not
59015d084d5Seric **		the canonical name for that host, return the canonical
59115d084d5Seric **		name.
592f36ede03Sbostic */
593cb452edcSeric 
59415d084d5Seric char *
59505b57da8Seric maphostname(map, hbuf, hbsize, avp)
59605b57da8Seric 	MAP *map;
59799f7cf32Seric 	char *hbuf;
59899f7cf32Seric 	int hbsize;
59915d084d5Seric 	char **avp;
60099f7cf32Seric {
60199f7cf32Seric 	register struct hostent *hp;
6025f78836eSmiriam 	u_long in_addr;
60305b57da8Seric 	char *cp;
60438ad259dSeric 	int i;
605f36ede03Sbostic 	struct hostent *gethostbyaddr();
6065f78836eSmiriam 
60799b358daSeric 	/* allow room for null */
60815d084d5Seric 	hbsize--;
60915d084d5Seric 
610f36ede03Sbostic 	/*
611f36ede03Sbostic 	 * If first character is a bracket, then it is an address
612f36ede03Sbostic 	 * lookup.  Address is copied into a temporary buffer to
613f36ede03Sbostic 	 * strip the brackets and to preserve hbuf if address is
614f36ede03Sbostic 	 * unknown.
615f36ede03Sbostic 	 */
61615d084d5Seric 
617cb452edcSeric 	if (*hbuf != '[')
61815d084d5Seric 	{
619d798a1deSeric 		extern bool getcanonname();
620d798a1deSeric 
62115d084d5Seric 		if (getcanonname(hbuf, hbsize))
62215d084d5Seric 			return hbuf;
62315d084d5Seric 		else
62415d084d5Seric 			return NULL;
62515d084d5Seric 	}
62605b57da8Seric 	if ((cp = strchr(hbuf, ']')) == NULL)
62715d084d5Seric 		return (NULL);
62834e39927Sbostic 	*cp = '\0';
62905b57da8Seric 	in_addr = inet_addr(&hbuf[1]);
63038ad259dSeric 
63138ad259dSeric 	/* check to see if this is one of our addresses */
63238ad259dSeric 	for (i = 0; MyIpAddrs[i].s_addr != 0; i++)
63338ad259dSeric 	{
63438ad259dSeric 		if (MyIpAddrs[i].s_addr == in_addr)
63538ad259dSeric 		{
63638ad259dSeric 			strncpy(hbuf, MyHostName, hbsize);
63738ad259dSeric 			hbuf[hbsize] = '\0';
63838ad259dSeric 			return hbuf;
63938ad259dSeric 		}
64038ad259dSeric 	}
64138ad259dSeric 
64238ad259dSeric 	/* nope -- ask the name server */
64331601fa7Seric 	hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET);
6445f78836eSmiriam 	if (hp == NULL)
64515d084d5Seric 		return (NULL);
64615d084d5Seric 
64738ad259dSeric 	/* found a match -- copy out */
64805b57da8Seric 	if (strlen(hp->h_name) > hbsize)
64905b57da8Seric 		hp->h_name[hbsize] = '\0';
650fefbbe29Seric 	(void) strcpy(hbuf, hp->h_name);
65115d084d5Seric 	return hbuf;
65299f7cf32Seric }
653f36ede03Sbostic 
6546c2c3107Seric # else /* DAEMON */
65599f7cf32Seric /* code for systems without sophisticated networking */
656444eaf03Seric 
657444eaf03Seric /*
658444eaf03Seric **  MYHOSTNAME -- stub version for case of no daemon code.
65921e9914dSeric **
66021e9914dSeric **	Can't convert to upper case here because might be a UUCP name.
661897f1869Seric **
662897f1869Seric **	Mark, you can change this to be anything you want......
663444eaf03Seric */
664444eaf03Seric 
665444eaf03Seric char **
666897f1869Seric myhostname(hostbuf, size)
667444eaf03Seric 	char hostbuf[];
668897f1869Seric 	int size;
669444eaf03Seric {
670444eaf03Seric 	register FILE *f;
671444eaf03Seric 
672444eaf03Seric 	hostbuf[0] = '\0';
673444eaf03Seric 	f = fopen("/usr/include/whoami", "r");
674444eaf03Seric 	if (f != NULL)
675444eaf03Seric 	{
676897f1869Seric 		(void) fgets(hostbuf, size, f);
677444eaf03Seric 		fixcrlf(hostbuf, TRUE);
678444eaf03Seric 		(void) fclose(f);
679444eaf03Seric 	}
680444eaf03Seric 	return (NULL);
681444eaf03Seric }
68299f7cf32Seric /*
683320e0d1cSeric **  GETREALHOSTNAME -- get the real host name asociated with a file descriptor
684320e0d1cSeric **
685320e0d1cSeric **	Parameters:
686320e0d1cSeric **		fd -- the descriptor
687320e0d1cSeric **
688320e0d1cSeric **	Returns:
689320e0d1cSeric **		The host name associated with this descriptor, if it can
690320e0d1cSeric **			be determined.
691320e0d1cSeric **		NULL otherwise.
692320e0d1cSeric **
693320e0d1cSeric **	Side Effects:
694320e0d1cSeric **		none
695320e0d1cSeric */
696320e0d1cSeric 
697320e0d1cSeric char *
698320e0d1cSeric getrealhostname(fd)
699320e0d1cSeric 	int fd;
700320e0d1cSeric {
701320e0d1cSeric 	return NULL;
702320e0d1cSeric }
703320e0d1cSeric /*
70499f7cf32Seric **  MAPHOSTNAME -- turn a hostname into canonical form
70599f7cf32Seric **
70699f7cf32Seric **	Parameters:
70705b57da8Seric **		map -- a pointer to the database map.
70899f7cf32Seric **		hbuf -- a buffer containing a hostname.
70915d084d5Seric **		avp -- a pointer to a (cf file defined) argument vector.
71099f7cf32Seric **
71199f7cf32Seric **	Returns:
71215d084d5Seric **		mapped host name
713cb452edcSeric **		FALSE otherwise.
71499f7cf32Seric **
71599f7cf32Seric **	Side Effects:
71699f7cf32Seric **		Looks up the host specified in hbuf.  If it is not
71799f7cf32Seric **		the canonical name for that host, replace it with
71899f7cf32Seric **		the canonical name.  If the name is unknown, or it
71999f7cf32Seric **		is already the canonical name, leave it unchanged.
72099f7cf32Seric */
72199f7cf32Seric 
72299f7cf32Seric /*ARGSUSED*/
72315d084d5Seric char *
72405b57da8Seric maphostname(map, hbuf, hbsize, avp)
72505b57da8Seric 	MAP *map;
72699f7cf32Seric 	char *hbuf;
72799f7cf32Seric 	int hbsize;
72815d084d5Seric 	char **avp;
72999f7cf32Seric {
73015d084d5Seric 	return NULL;
73199f7cf32Seric }
73299f7cf32Seric 
7336c2c3107Seric #endif /* DAEMON */
734