xref: /csrg-svn/usr.sbin/sendmail/src/daemon.c (revision 58798)
1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #include <errno.h>
10 #include <signal.h>
11 #include "sendmail.h"
12 
13 #ifndef lint
14 #ifdef DAEMON
15 static char sccsid[] = "@(#)daemon.c	6.25 (Berkeley) 03/24/93 (with daemon mode)";
16 #else
17 static char sccsid[] = "@(#)daemon.c	6.25 (Berkeley) 03/24/93 (without daemon mode)";
18 #endif
19 #endif /* not lint */
20 
21 #ifdef DAEMON
22 
23 # include <netdb.h>
24 # include <sys/wait.h>
25 # include <sys/time.h>
26 
27 #ifdef NETISO
28 # include <netiso/iso.h>
29 #endif
30 
31 /*
32 **  DAEMON.C -- routines to use when running as a daemon.
33 **
34 **	This entire file is highly dependent on the 4.2 BSD
35 **	interprocess communication primitives.  No attempt has
36 **	been made to make this file portable to Version 7,
37 **	Version 6, MPX files, etc.  If you should try such a
38 **	thing yourself, I recommend chucking the entire file
39 **	and starting from scratch.  Basic semantics are:
40 **
41 **	getrequests()
42 **		Opens a port and initiates a connection.
43 **		Returns in a child.  Must set InChannel and
44 **		OutChannel appropriately.
45 **	clrdaemon()
46 **		Close any open files associated with getting
47 **		the connection; this is used when running the queue,
48 **		etc., to avoid having extra file descriptors during
49 **		the queue run and to avoid confusing the network
50 **		code (if it cares).
51 **	makeconnection(host, port, outfile, infile, usesecureport)
52 **		Make a connection to the named host on the given
53 **		port.  Set *outfile and *infile to the files
54 **		appropriate for communication.  Returns zero on
55 **		success, else an exit status describing the
56 **		error.
57 **	maphostname(map, hbuf, hbufsiz, avp)
58 **		Convert the entry in hbuf into a canonical form.
59 */
60 
61 extern char	*anynet_ntoa();
62 /*
63 **  GETREQUESTS -- open mail IPC port and get requests.
64 **
65 **	Parameters:
66 **		none.
67 **
68 **	Returns:
69 **		none.
70 **
71 **	Side Effects:
72 **		Waits until some interesting activity occurs.  When
73 **		it does, a child is created to process it, and the
74 **		parent waits for completion.  Return from this
75 **		routine is always in the child.  The file pointers
76 **		"InChannel" and "OutChannel" should be set to point
77 **		to the communication channel.
78 */
79 
80 int	DaemonSocket	= -1;		/* fd describing socket */
81 
82 getrequests()
83 {
84 	int t;
85 	register struct servent *sp;
86 	int on = 1;
87 	bool refusingconnections = TRUE;
88 	FILE *pidf;
89 	SOCKADDR srvraddr;
90 	extern void reapchild();
91 
92 	/*
93 	**  Set up the address for the mailer.
94 	*/
95 
96 	sp = getservbyname("smtp", "tcp");
97 	if (sp == NULL)
98 	{
99 		syserr("554 server \"smtp\" unknown");
100 		goto severe;
101 	}
102 	srvraddr.sin.sin_family = AF_INET;
103 	srvraddr.sin.sin_addr.s_addr = INADDR_ANY;
104 	srvraddr.sin.sin_port = sp->s_port;
105 
106 	/*
107 	**  Try to actually open the connection.
108 	*/
109 
110 	if (tTd(15, 1))
111 		printf("getrequests: port 0x%x\n", srvraddr.sin.sin_port);
112 
113 	/* get a socket for the SMTP connection */
114 	DaemonSocket = socket(AF_INET, SOCK_STREAM, 0);
115 	if (DaemonSocket < 0)
116 	{
117 		/* probably another daemon already */
118 		syserr("getrequests: can't create socket");
119 	  severe:
120 # ifdef LOG
121 		if (LogLevel > 0)
122 			syslog(LOG_ALERT, "problem creating SMTP socket");
123 # endif /* LOG */
124 		finis();
125 	}
126 
127 	/* turn on network debugging? */
128 	if (tTd(15, 101))
129 		(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
130 
131 	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
132 	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
133 
134 	if (bind(DaemonSocket, &srvraddr.sa, sizeof srvraddr) < 0)
135 	{
136 		syserr("getrequests: cannot bind");
137 		(void) close(DaemonSocket);
138 		goto severe;
139 	}
140 
141 	(void) signal(SIGCHLD, reapchild);
142 
143 	/* write the pid to the log file for posterity */
144 	pidf = fopen(PidFile, "w");
145 	if (pidf != NULL)
146 	{
147 		fprintf(pidf, "%d\n", getpid());
148 		fclose(pidf);
149 	}
150 
151 
152 	if (tTd(15, 1))
153 		printf("getrequests: %d\n", DaemonSocket);
154 
155 	for (;;)
156 	{
157 		register int pid;
158 		auto int lotherend;
159 		extern bool refuseconnections();
160 
161 		/* see if we are rejecting connections */
162 		CurrentLA = getla();
163 		if (refuseconnections())
164 		{
165 			if (!refusingconnections)
166 			{
167 				/* don't queue so peer will fail quickly */
168 				(void) listen(DaemonSocket, 0);
169 				refusingconnections = TRUE;
170 			}
171 			setproctitle("rejecting connections: load average: %d",
172 				CurrentLA);
173 			sleep(5);
174 			continue;
175 		}
176 
177 		if (refusingconnections)
178 		{
179 			/* start listening again */
180 			if (listen(DaemonSocket, 10) < 0)
181 			{
182 				syserr("getrequests: cannot listen");
183 				(void) close(DaemonSocket);
184 				goto severe;
185 			}
186 			setproctitle("accepting connections");
187 			refusingconnections = FALSE;
188 		}
189 
190 		/* wait for a connection */
191 		do
192 		{
193 			errno = 0;
194 			lotherend = sizeof RealHostAddr;
195 			t = accept(DaemonSocket,
196 			    (struct sockaddr *)&RealHostAddr, &lotherend);
197 		} while (t < 0 && errno == EINTR);
198 		if (t < 0)
199 		{
200 			syserr("getrequests: accept");
201 			sleep(5);
202 			continue;
203 		}
204 
205 		/*
206 		**  Create a subprocess to process the mail.
207 		*/
208 
209 		if (tTd(15, 2))
210 			printf("getrequests: forking (fd = %d)\n", t);
211 
212 		pid = fork();
213 		if (pid < 0)
214 		{
215 			syserr("daemon: cannot fork");
216 			sleep(10);
217 			(void) close(t);
218 			continue;
219 		}
220 
221 		if (pid == 0)
222 		{
223 			extern struct hostent *gethostbyaddr();
224 			register struct hostent *hp;
225 			char buf[MAXNAME];
226 
227 			/*
228 			**  CHILD -- return to caller.
229 			**	Collect verified idea of sending host.
230 			**	Verify calling user id if possible here.
231 			*/
232 
233 			(void) signal(SIGCHLD, SIG_DFL);
234 
235 			/* determine host name */
236 			switch (RealHostAddr.sa.sa_family)
237 			{
238 #ifdef NETINET
239 			  case AF_INET:
240 				hp = gethostbyaddr((char *) &RealHostAddr.sin.sin_addr,
241 					sizeof RealHostAddr.sin.sin_addr,
242 					AF_INET);
243 				break;
244 #endif
245 
246 #ifdef NETISO
247 			  case AF_ISO:
248 				hp = gethostbyaddr((char *) &RealHostAddr.siso.siso_addr,
249 					sizeof RealHostAddr.siso.siso_addr,
250 					AF_ISO);
251 				break;
252 #endif
253 
254 			  default:
255 				hp = gethostbyaddr(RealHostAddr.sa.sa_data,
256 					   sizeof RealHostAddr.sa.sa_data,
257 					   RealHostAddr.sa.sa_family);
258 				break;
259 			}
260 
261 			if (hp != NULL)
262 				(void) strcpy(buf, hp->h_name);
263 			else
264 			{
265 				/* produce a dotted quad */
266 				(void) sprintf(buf, "[%s]",
267 					anynet_ntoa(&RealHostAddr));
268 			}
269 
270 #ifdef LOG
271 			if (LogLevel > 10)
272 			{
273 				/* log connection information */
274 				syslog(LOG_INFO, "connect from %s (%s)",
275 					buf, anynet_ntoa(&RealHostAddr));
276 			}
277 #endif
278 
279 			/* should we check for illegal connection here? XXX */
280 
281 			RealHostName = newstr(buf);
282 
283 			(void) close(DaemonSocket);
284 			InChannel = fdopen(t, "r");
285 			OutChannel = fdopen(dup(t), "w");
286 			if (tTd(15, 2))
287 				printf("getreq: returning\n");
288 			return;
289 		}
290 
291 		/* close the port so that others will hang (for a while) */
292 		(void) close(t);
293 	}
294 	/*NOTREACHED*/
295 }
296 /*
297 **  CLRDAEMON -- reset the daemon connection
298 **
299 **	Parameters:
300 **		none.
301 **
302 **	Returns:
303 **		none.
304 **
305 **	Side Effects:
306 **		releases any resources used by the passive daemon.
307 */
308 
309 clrdaemon()
310 {
311 	if (DaemonSocket >= 0)
312 		(void) close(DaemonSocket);
313 	DaemonSocket = -1;
314 }
315 /*
316 **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
317 **
318 **	Parameters:
319 **		host -- the name of the host.
320 **		port -- the port number to connect to.
321 **		mci -- a pointer to the mail connection information
322 **			structure to be filled in.
323 **		usesecureport -- if set, use a low numbered (reserved)
324 **			port to provide some rudimentary authentication.
325 **
326 **	Returns:
327 **		An exit code telling whether the connection could be
328 **			made and if not why not.
329 **
330 **	Side Effects:
331 **		none.
332 */
333 
334 SOCKADDR	CurHostAddr;		/* address of current host */
335 
336 int
337 makeconnection(host, port, mci, usesecureport)
338 	char *host;
339 	u_short port;
340 	register MCI *mci;
341 	bool usesecureport;
342 {
343 	register int i, s;
344 	register struct hostent *hp = (struct hostent *)NULL;
345 	SOCKADDR addr;
346 	int sav_errno;
347 	int addrlen;
348 #ifdef NAMED_BIND
349 	extern int h_errno;
350 #endif
351 
352 	/*
353 	**  Set up the address for the mailer.
354 	**	Accept "[a.b.c.d]" syntax for host name.
355 	*/
356 
357 #ifdef NAMED_BIND
358 	h_errno = 0;
359 #endif
360 	errno = 0;
361 
362 	if (host[0] == '[')
363 	{
364 		long hid;
365 		register char *p = strchr(host, ']');
366 
367 		if (p != NULL)
368 		{
369 			*p = '\0';
370 			hid = inet_addr(&host[1]);
371 			if (hid == -1)
372 			{
373 				/* try it as a host name (avoid MX lookup) */
374 				hp = gethostbyname(&host[1]);
375 				*p = ']';
376 				goto gothostent;
377 			}
378 			*p = ']';
379 		}
380 		if (p == NULL)
381 		{
382 			usrerr("553 Invalid numeric domain spec \"%s\"", host);
383 			return (EX_NOHOST);
384 		}
385 		addr.sin.sin_family = AF_INET;
386 		addr.sin.sin_addr.s_addr = hid;
387 	}
388 	else
389 	{
390 		hp = gethostbyname(host);
391 gothostent:
392 		if (hp == NULL)
393 		{
394 #ifdef NAMED_BIND
395 			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN)
396 				return (EX_TEMPFAIL);
397 
398 			/* if name server is specified, assume temp fail */
399 			if (errno == ECONNREFUSED && UseNameServer)
400 				return (EX_TEMPFAIL);
401 #endif
402 			return (EX_NOHOST);
403 		}
404 		addr.sa.sa_family = hp->h_addrtype;
405 		switch (hp->h_addrtype)
406 		{
407 #ifdef NETINET
408 		  case AF_INET:
409 			bcopy(hp->h_addr,
410 				&addr.sin.sin_addr,
411 				hp->h_length);
412 			break;
413 #endif
414 
415 		  default:
416 			bcopy(hp->h_addr,
417 				addr.sa.sa_data,
418 				hp->h_length);
419 			break;
420 		}
421 		i = 1;
422 	}
423 
424 	/*
425 	**  Determine the port number.
426 	*/
427 
428 	if (port != 0)
429 		port = htons(port);
430 	else
431 	{
432 		register struct servent *sp = getservbyname("smtp", "tcp");
433 
434 		if (sp == NULL)
435 		{
436 			syserr("554 makeconnection: server \"smtp\" unknown");
437 			return (EX_OSERR);
438 		}
439 		port = sp->s_port;
440 	}
441 
442 	switch (addr.sa.sa_family)
443 	{
444 	  case AF_INET:
445 		addr.sin.sin_port = port;
446 		addrlen = sizeof (struct sockaddr_in);
447 		break;
448 
449 #ifdef NETISO
450 	  case AF_ISO:
451 		/* assume two byte transport selector */
452 		bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2);
453 		addrlen = sizeof (struct sockaddr_iso);
454 		break;
455 #endif
456 
457 	  default:
458 		syserr("Can't connect to address family %d", addr.sa.sa_family);
459 		return (EX_NOHOST);
460 	}
461 
462 	/*
463 	**  Try to actually open the connection.
464 	*/
465 
466 	for (;;)
467 	{
468 		if (tTd(16, 1))
469 			printf("makeconnection (%s [%s])\n",
470 				host, anynet_ntoa(&addr));
471 
472 		/* save for logging */
473 		CurHostAddr = addr;
474 
475 		if (usesecureport)
476 		{
477 			int rport = IPPORT_RESERVED - 1;
478 
479 			s = rresvport(&rport);
480 		}
481 		else
482 		{
483 			s = socket(AF_INET, SOCK_STREAM, 0);
484 		}
485 		if (s < 0)
486 		{
487 			sav_errno = errno;
488 			syserr("makeconnection: no socket");
489 			goto failure;
490 		}
491 
492 		if (tTd(16, 1))
493 			printf("makeconnection: fd=%d\n", s);
494 
495 		/* turn on network debugging? */
496 		if (tTd(16, 101))
497 		{
498 			int on = 1;
499 			(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG,
500 					  (char *)&on, sizeof on);
501 		}
502 		if (CurEnv->e_xfp != NULL)
503 			(void) fflush(CurEnv->e_xfp);		/* for debugging */
504 		errno = 0;					/* for debugging */
505 		if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
506 			break;
507 
508 		/* couldn't connect.... figure out why */
509 		sav_errno = errno;
510 		(void) close(s);
511 		if (hp && hp->h_addr_list[i])
512 		{
513 			extern char *errstring();
514 
515 			if (tTd(16, 1))
516 				printf("Connect failed (%s); trying new address....\n",
517 					errstring(sav_errno));
518 			switch (addr.sa.sa_family)
519 			{
520 #ifdef NETINET
521 			  case AF_INET:
522 				bcopy(hp->h_addr_list[i++],
523 				      &addr.sin.sin_addr,
524 				      hp->h_length);
525 				break;
526 #endif
527 
528 			  default:
529 				bcopy(hp->h_addr_list[i++],
530 					addr.sa.sa_data,
531 					hp->h_length);
532 				break;
533 			}
534 			continue;
535 		}
536 
537 		/* failure, decide if temporary or not */
538 	failure:
539 		if (transienterror(sav_errno))
540 			return EX_TEMPFAIL;
541 		else
542 		{
543 			extern char *errstring();
544 
545 			message("%s", errstring(sav_errno));
546 			return (EX_UNAVAILABLE);
547 		}
548 	}
549 
550 	/* connection ok, put it into canonical form */
551 	mci->mci_out = fdopen(s, "w");
552 	mci->mci_in = fdopen(dup(s), "r");
553 
554 	return (EX_OK);
555 }
556 /*
557 **  MYHOSTNAME -- return the name of this host.
558 **
559 **	Parameters:
560 **		hostbuf -- a place to return the name of this host.
561 **		size -- the size of hostbuf.
562 **
563 **	Returns:
564 **		A list of aliases for this host.
565 **
566 **	Side Effects:
567 **		Sets the MyIpAddrs buffer to a list of my IP addresses.
568 */
569 
570 struct in_addr	MyIpAddrs[MAXIPADDR + 1];
571 
572 char **
573 myhostname(hostbuf, size)
574 	char hostbuf[];
575 	int size;
576 {
577 	register struct hostent *hp;
578 	extern struct hostent *gethostbyname();
579 
580 	if (gethostname(hostbuf, size) < 0)
581 	{
582 		(void) strcpy(hostbuf, "localhost");
583 	}
584 	hp = gethostbyname(hostbuf);
585 	if (hp != NULL)
586 	{
587 		(void) strncpy(hostbuf, hp->h_name, size - 1);
588 		hostbuf[size - 1] = '\0';
589 
590 		if (hp->h_addrtype == AF_INET && hp->h_length == 4)
591 		{
592 			register int i;
593 
594 			for (i = 0; i < MAXIPADDR; i++)
595 			{
596 				if (hp->h_addr_list[i] == NULL)
597 					break;
598 				MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i];
599 			}
600 			MyIpAddrs[i].s_addr = 0;
601 		}
602 
603 		return (hp->h_aliases);
604 	}
605 	else
606 		return (NULL);
607 }
608 /*
609 **  GETREALHOSTNAME -- get the real host name asociated with a file descriptor
610 **
611 **	Parameters:
612 **		fd -- the descriptor
613 **
614 **	Returns:
615 **		The host name associated with this descriptor, if it can
616 **			be determined.
617 **		NULL otherwise.
618 **
619 **	Side Effects:
620 **		none
621 */
622 
623 char *
624 getrealhostname(fd)
625 	int fd;
626 {
627 	register struct hostent *hp;
628 	SOCKADDR sa;
629 	int salen;
630 	char hbuf[MAXNAME];
631 	extern struct hostent *gethostbyaddr();
632 
633 	salen = sizeof sa;
634 	if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0)
635 		return NULL;
636 	hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family);
637 	if (hp != NULL)
638 		(void) strcpy(hbuf, hp->h_name);
639 	else
640 		(void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa));
641 	return hbuf;
642 }
643 /*
644 **  MAPHOSTNAME -- turn a hostname into canonical form
645 **
646 **	Parameters:
647 **		map -- a pointer to this map (unused).
648 **		hbuf -- a buffer containing a hostname.
649 **		hbsize -- the size of hbuf.
650 **		avp -- unused -- for compatibility with other mapping
651 **			functions.
652 **
653 **	Returns:
654 **		The mapping, if found.
655 **		NULL if no mapping found.
656 **
657 **	Side Effects:
658 **		Looks up the host specified in hbuf.  If it is not
659 **		the canonical name for that host, return the canonical
660 **		name.
661 */
662 
663 char *
664 maphostname(map, hbuf, hbsize, avp)
665 	MAP *map;
666 	char *hbuf;
667 	int hbsize;
668 	char **avp;
669 {
670 	register struct hostent *hp;
671 	u_long in_addr;
672 	char *cp;
673 	int i;
674 	struct hostent *gethostbyaddr();
675 
676 	/* allow room for null */
677 	hbsize--;
678 
679 	/*
680 	 * If first character is a bracket, then it is an address
681 	 * lookup.  Address is copied into a temporary buffer to
682 	 * strip the brackets and to preserve hbuf if address is
683 	 * unknown.
684 	 */
685 
686 	if (*hbuf != '[')
687 	{
688 		extern bool getcanonname();
689 
690 		if (tTd(9, 1))
691 			printf("maphostname(%s, %d) => ", hbuf, hbsize);
692 		if (getcanonname(hbuf, hbsize))
693 		{
694 			if (tTd(9, 1))
695 				printf("%s\n", hbuf);
696 			return hbuf;
697 		}
698 		else
699 		{
700 			if (tTd(9, 1))
701 				printf("FAIL\n");
702 			return NULL;
703 		}
704 	}
705 	if ((cp = strchr(hbuf, ']')) == NULL)
706 		return (NULL);
707 	*cp = '\0';
708 	in_addr = inet_addr(&hbuf[1]);
709 
710 	/* check to see if this is one of our addresses */
711 	for (i = 0; MyIpAddrs[i].s_addr != 0; i++)
712 	{
713 		if (MyIpAddrs[i].s_addr == in_addr)
714 		{
715 			strncpy(hbuf, MyHostName, hbsize);
716 			hbuf[hbsize] = '\0';
717 			return hbuf;
718 		}
719 	}
720 
721 	/* nope -- ask the name server */
722 	hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET);
723 	if (hp == NULL)
724 		return (NULL);
725 
726 	/* found a match -- copy out */
727 	if (strlen(hp->h_name) > hbsize)
728 		hp->h_name[hbsize] = '\0';
729 	(void) strcpy(hbuf, hp->h_name);
730 	return hbuf;
731 }
732 /*
733 **  ANYNET_NTOA -- convert a network address to printable form.
734 **
735 **	Parameters:
736 **		sap -- a pointer to a sockaddr structure.
737 **
738 **	Returns:
739 **		A printable version of that sockaddr.
740 */
741 
742 char *
743 anynet_ntoa(sap)
744 	register SOCKADDR *sap;
745 {
746 	register char *bp;
747 	register char *ap;
748 	int l;
749 	static char buf[80];
750 
751 	/* check for null/zero family */
752 	if (sap == NULL)
753 		return "NULLADDR";
754 	if (sap->sa.sa_family == 0)
755 		return "0";
756 
757 #ifdef NETINET
758 	if (sap->sa.sa_family == AF_INET)
759 	{
760 		extern char *inet_ntoa();
761 
762 		return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr);
763 	}
764 #endif
765 
766 	/* unknown family -- just dump bytes */
767 	(void) sprintf(buf, "Family %d: ", sap->sa.sa_family);
768 	bp = &buf[strlen(buf)];
769 	ap = sap->sa.sa_data;
770 	for (l = sizeof sap->sa.sa_data; --l >= 0; )
771 	{
772 		(void) sprintf(bp, "%02x:", *ap++ & 0377);
773 		bp += 3;
774 	}
775 	*--bp = '\0';
776 	return buf;
777 }
778 
779 # else /* DAEMON */
780 /* code for systems without sophisticated networking */
781 
782 /*
783 **  MYHOSTNAME -- stub version for case of no daemon code.
784 **
785 **	Can't convert to upper case here because might be a UUCP name.
786 **
787 **	Mark, you can change this to be anything you want......
788 */
789 
790 char **
791 myhostname(hostbuf, size)
792 	char hostbuf[];
793 	int size;
794 {
795 	register FILE *f;
796 
797 	hostbuf[0] = '\0';
798 	f = fopen("/usr/include/whoami", "r");
799 	if (f != NULL)
800 	{
801 		(void) fgets(hostbuf, size, f);
802 		fixcrlf(hostbuf, TRUE);
803 		(void) fclose(f);
804 	}
805 	return (NULL);
806 }
807 /*
808 **  GETREALHOSTNAME -- get the real host name asociated with a file descriptor
809 **
810 **	Parameters:
811 **		fd -- the descriptor
812 **
813 **	Returns:
814 **		The host name associated with this descriptor, if it can
815 **			be determined.
816 **		NULL otherwise.
817 **
818 **	Side Effects:
819 **		none
820 */
821 
822 char *
823 getrealhostname(fd)
824 	int fd;
825 {
826 	return NULL;
827 }
828 /*
829 **  MAPHOSTNAME -- turn a hostname into canonical form
830 **
831 **	Parameters:
832 **		map -- a pointer to the database map.
833 **		hbuf -- a buffer containing a hostname.
834 **		avp -- a pointer to a (cf file defined) argument vector.
835 **
836 **	Returns:
837 **		mapped host name
838 **		FALSE otherwise.
839 **
840 **	Side Effects:
841 **		Looks up the host specified in hbuf.  If it is not
842 **		the canonical name for that host, replace it with
843 **		the canonical name.  If the name is unknown, or it
844 **		is already the canonical name, leave it unchanged.
845 */
846 
847 /*ARGSUSED*/
848 char *
849 maphostname(map, hbuf, hbsize, avp)
850 	MAP *map;
851 	char *hbuf;
852 	int hbsize;
853 	char **avp;
854 {
855 	return NULL;
856 }
857 
858 #endif /* DAEMON */
859