122700Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333780Sbostic * Copyright (c) 1988 Regents of the University of California. 433780Sbostic * All rights reserved. 533780Sbostic * 642825Sbostic * %sccs.include.redist.c% 733780Sbostic */ 822700Sdist 933932Sbostic #include <errno.h> 1058153Seric #include <signal.h> 1140962Sbostic #include "sendmail.h" 124535Seric 1333780Sbostic #ifndef lint 1433780Sbostic #ifdef DAEMON 15*60009Seric static char sccsid[] = "@(#)daemon.c 6.48 (Berkeley) 05/14/93 (with daemon mode)"; 1633780Sbostic #else 17*60009Seric static char sccsid[] = "@(#)daemon.c 6.48 (Berkeley) 05/14/93 (without daemon mode)"; 1833780Sbostic #endif 1933780Sbostic #endif /* not lint */ 204535Seric 2133780Sbostic #ifdef DAEMON 2233780Sbostic 2323120Seric # include <netdb.h> 2423120Seric # include <sys/wait.h> 2523120Seric # include <sys/time.h> 265978Seric 2759042Seric #ifdef NAMED_BIND 2859042Seric # include <arpa/nameser.h> 2959042Seric # include <resolv.h> 3059042Seric #endif 3159042Seric 324535Seric /* 334535Seric ** DAEMON.C -- routines to use when running as a daemon. 347556Seric ** 357556Seric ** This entire file is highly dependent on the 4.2 BSD 367556Seric ** interprocess communication primitives. No attempt has 377556Seric ** been made to make this file portable to Version 7, 387556Seric ** Version 6, MPX files, etc. If you should try such a 397556Seric ** thing yourself, I recommend chucking the entire file 407556Seric ** and starting from scratch. Basic semantics are: 417556Seric ** 427556Seric ** getrequests() 437556Seric ** Opens a port and initiates a connection. 447556Seric ** Returns in a child. Must set InChannel and 457556Seric ** OutChannel appropriately. 4610206Seric ** clrdaemon() 4710206Seric ** Close any open files associated with getting 4810206Seric ** the connection; this is used when running the queue, 4910206Seric ** etc., to avoid having extra file descriptors during 5010206Seric ** the queue run and to avoid confusing the network 5110206Seric ** code (if it cares). 5252106Seric ** makeconnection(host, port, outfile, infile, usesecureport) 537556Seric ** Make a connection to the named host on the given 547556Seric ** port. Set *outfile and *infile to the files 557556Seric ** appropriate for communication. Returns zero on 567556Seric ** success, else an exit status describing the 577556Seric ** error. 5856823Seric ** maphostname(map, hbuf, hbufsiz, avp) 5956823Seric ** Convert the entry in hbuf into a canonical form. 604535Seric */ 6158755Seric 6258755Seric extern char *anynet_ntoa(); 634535Seric /* 644535Seric ** GETREQUESTS -- open mail IPC port and get requests. 654535Seric ** 664535Seric ** Parameters: 674535Seric ** none. 684535Seric ** 694535Seric ** Returns: 704535Seric ** none. 714535Seric ** 724535Seric ** Side Effects: 734535Seric ** Waits until some interesting activity occurs. When 744535Seric ** it does, a child is created to process it, and the 754535Seric ** parent waits for completion. Return from this 769886Seric ** routine is always in the child. The file pointers 779886Seric ** "InChannel" and "OutChannel" should be set to point 789886Seric ** to the communication channel. 794535Seric */ 804535Seric 8158849Seric int DaemonSocket = -1; /* fd describing socket */ 8258849Seric SOCKADDR DaemonAddr; /* socket for incoming */ 8359783Seric int ListenQueueSize = 10; /* size of listen queue */ 8416144Seric 854535Seric getrequests() 864535Seric { 879610Seric int t; 889610Seric register struct servent *sp; 8925027Seric int on = 1; 9053751Seric bool refusingconnections = TRUE; 9158419Seric FILE *pidf; 9246928Sbostic extern void reapchild(); 937117Seric 949610Seric /* 959610Seric ** Set up the address for the mailer. 969610Seric */ 979610Seric 9858849Seric if (DaemonAddr.sin.sin_family == 0) 9958849Seric DaemonAddr.sin.sin_family = AF_INET; 10058849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 10158849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10258849Seric if (DaemonAddr.sin.sin_port == 0) 1039610Seric { 10458849Seric sp = getservbyname("smtp", "tcp"); 10558849Seric if (sp == NULL) 10658849Seric { 10758909Seric syserr("554 service \"smtp\" unknown"); 10858849Seric goto severe; 10958849Seric } 11058849Seric DaemonAddr.sin.sin_port = sp->s_port; 1119610Seric } 1129610Seric 1139610Seric /* 1149610Seric ** Try to actually open the connection. 1159610Seric */ 1169610Seric 1179610Seric if (tTd(15, 1)) 11858849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1199610Seric 1209610Seric /* get a socket for the SMTP connection */ 12159041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12210206Seric if (DaemonSocket < 0) 1239610Seric { 1249610Seric /* probably another daemon already */ 1259610Seric syserr("getrequests: can't create socket"); 1269610Seric severe: 1279610Seric # ifdef LOG 1289610Seric if (LogLevel > 0) 12957663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 13056795Seric # endif /* LOG */ 1319610Seric finis(); 1329610Seric } 13310347Seric 13410347Seric /* turn on network debugging? */ 13556328Seric if (tTd(15, 101)) 13624945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13710347Seric 13825027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13925027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 14025027Seric 14159041Seric switch (DaemonAddr.sa.sa_family) 1429610Seric { 14359041Seric # ifdef NETINET 14459041Seric case AF_INET: 14559041Seric t = sizeof DaemonAddr.sin; 14659041Seric break; 14759041Seric # endif 14859041Seric 14959041Seric # ifdef NETISO 15059041Seric case AF_ISO: 15159041Seric t = sizeof DaemonAddr.siso; 15259041Seric break; 15359041Seric # endif 15459041Seric 15559041Seric default: 15659041Seric t = sizeof DaemonAddr; 15759041Seric break; 15859041Seric } 15959041Seric 16059041Seric if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0) 16159041Seric { 1629610Seric syserr("getrequests: cannot bind"); 16310206Seric (void) close(DaemonSocket); 1649610Seric goto severe; 1659610Seric } 1669610Seric 16724955Seric (void) signal(SIGCHLD, reapchild); 16824945Seric 16958419Seric /* write the pid to the log file for posterity */ 17058419Seric pidf = fopen(PidFile, "w"); 17158419Seric if (pidf != NULL) 17258419Seric { 17358419Seric fprintf(pidf, "%d\n", getpid()); 17458419Seric fclose(pidf); 17558419Seric } 17658419Seric 17758419Seric 1789610Seric if (tTd(15, 1)) 17910206Seric printf("getrequests: %d\n", DaemonSocket); 1809610Seric 1814631Seric for (;;) 1824631Seric { 18314875Seric register int pid; 18411147Seric auto int lotherend; 18553751Seric extern bool refuseconnections(); 18611147Seric 18714875Seric /* see if we are rejecting connections */ 18853751Seric CurrentLA = getla(); 18953751Seric if (refuseconnections()) 19036584Sbostic { 19153751Seric if (!refusingconnections) 19253751Seric { 19353751Seric /* don't queue so peer will fail quickly */ 19453751Seric (void) listen(DaemonSocket, 0); 19553751Seric refusingconnections = TRUE; 19653751Seric } 19757385Seric setproctitle("rejecting connections: load average: %d", 19857385Seric CurrentLA); 19914875Seric sleep(5); 20053751Seric continue; 20136584Sbostic } 20214875Seric 20353751Seric if (refusingconnections) 20453751Seric { 20553751Seric /* start listening again */ 20659783Seric if (listen(DaemonSocket, ListenQueueSize) < 0) 20753751Seric { 20853751Seric syserr("getrequests: cannot listen"); 20953751Seric (void) close(DaemonSocket); 21053751Seric goto severe; 21153751Seric } 21253751Seric setproctitle("accepting connections"); 21353751Seric refusingconnections = FALSE; 21453751Seric } 21553751Seric 2169610Seric /* wait for a connection */ 2179610Seric do 2189610Seric { 2199610Seric errno = 0; 22036230Skarels lotherend = sizeof RealHostAddr; 22146928Sbostic t = accept(DaemonSocket, 22246928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2239610Seric } while (t < 0 && errno == EINTR); 2249610Seric if (t < 0) 2255978Seric { 2269610Seric syserr("getrequests: accept"); 2279610Seric sleep(5); 2289610Seric continue; 2295978Seric } 2304631Seric 2315978Seric /* 2325978Seric ** Create a subprocess to process the mail. 2335978Seric */ 2345978Seric 2357677Seric if (tTd(15, 2)) 2369610Seric printf("getrequests: forking (fd = %d)\n", t); 2375978Seric 2384636Seric pid = fork(); 2394636Seric if (pid < 0) 2404631Seric { 2414636Seric syserr("daemon: cannot fork"); 2424636Seric sleep(10); 2439610Seric (void) close(t); 2444636Seric continue; 2454631Seric } 2464631Seric 2474636Seric if (pid == 0) 2484631Seric { 24958951Seric extern char *hostnamebyanyaddr(); 25011147Seric 2514636Seric /* 2524636Seric ** CHILD -- return to caller. 25311147Seric ** Collect verified idea of sending host. 2544636Seric ** Verify calling user id if possible here. 2554636Seric */ 2564631Seric 25724955Seric (void) signal(SIGCHLD, SIG_DFL); 25859156Seric OpMode = MD_SMTP; 25924950Seric 26011147Seric /* determine host name */ 26158951Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 26258778Seric 26355173Seric #ifdef LOG 26457977Seric if (LogLevel > 10) 26555173Seric { 26655173Seric /* log connection information */ 26755173Seric syslog(LOG_INFO, "connect from %s (%s)", 26858951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 26955173Seric } 27055173Seric #endif 27155173Seric 27259254Seric (void) close(DaemonSocket); 27359254Seric InChannel = fdopen(t, "r"); 27459254Seric OutChannel = fdopen(dup(t), "w"); 27559254Seric 27616884Seric /* should we check for illegal connection here? XXX */ 27759156Seric #ifdef XLA 27859156Seric if (!xla_host_ok(RealHostName)) 27959156Seric { 28059254Seric message("421 Too many SMTP sessions for this host"); 28159156Seric exit(0); 28259156Seric } 28359156Seric #endif 28416884Seric 2857677Seric if (tTd(15, 2)) 2865978Seric printf("getreq: returning\n"); 2874636Seric return; 2884631Seric } 2894631Seric 2907117Seric /* close the port so that others will hang (for a while) */ 2919610Seric (void) close(t); 2924631Seric } 2939886Seric /*NOTREACHED*/ 2944631Seric } 2955978Seric /* 29610206Seric ** CLRDAEMON -- reset the daemon connection 29710206Seric ** 29810206Seric ** Parameters: 29910206Seric ** none. 30010206Seric ** 30110206Seric ** Returns: 30210206Seric ** none. 30310206Seric ** 30410206Seric ** Side Effects: 30510206Seric ** releases any resources used by the passive daemon. 30610206Seric */ 30710206Seric 30810206Seric clrdaemon() 30910206Seric { 31010206Seric if (DaemonSocket >= 0) 31110206Seric (void) close(DaemonSocket); 31210206Seric DaemonSocket = -1; 31310206Seric } 31410206Seric /* 31558849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 31658849Seric ** 31758849Seric ** Parameters: 31858849Seric ** p -- the options line. 31958849Seric ** 32058849Seric ** Returns: 32158849Seric ** none. 32258849Seric */ 32358849Seric 32458849Seric setdaemonoptions(p) 32558849Seric register char *p; 32658849Seric { 32758873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 32858873Seric DaemonAddr.sa.sa_family = AF_INET; 32958873Seric 33058849Seric while (p != NULL) 33158849Seric { 33258849Seric register char *f; 33358849Seric register char *v; 33458849Seric 33558849Seric while (isascii(*p) && isspace(*p)) 33658849Seric p++; 33758849Seric if (*p == '\0') 33858849Seric break; 33958849Seric f = p; 34058849Seric p = strchr(p, ','); 34158849Seric if (p != NULL) 34258849Seric *p++ = '\0'; 34358849Seric v = strchr(f, '='); 34458849Seric if (v == NULL) 34558849Seric continue; 34658849Seric while (isascii(*++v) && isspace(*v)) 34758849Seric continue; 34858849Seric 34958849Seric switch (*f) 35058849Seric { 35158873Seric case 'F': /* address family */ 35258849Seric if (isascii(*v) && isdigit(*v)) 35358873Seric DaemonAddr.sa.sa_family = atoi(v); 35458873Seric #ifdef NETINET 35558873Seric else if (strcasecmp(v, "inet") == 0) 35658873Seric DaemonAddr.sa.sa_family = AF_INET; 35758873Seric #endif 35858873Seric #ifdef NETISO 35958873Seric else if (strcasecmp(v, "iso") == 0) 36058873Seric DaemonAddr.sa.sa_family = AF_ISO; 36158873Seric #endif 36258873Seric #ifdef NETNS 36358873Seric else if (strcasecmp(v, "ns") == 0) 36458873Seric DaemonAddr.sa.sa_family = AF_NS; 36558873Seric #endif 36658873Seric #ifdef NETX25 36758873Seric else if (strcasecmp(v, "x.25") == 0) 36858873Seric DaemonAddr.sa.sa_family = AF_CCITT; 36958873Seric #endif 37058849Seric else 37158873Seric syserr("554 Unknown address family %s in Family=option", v); 37258873Seric break; 37358873Seric 37458873Seric case 'A': /* address */ 37558873Seric switch (DaemonAddr.sa.sa_family) 37658849Seric { 37758873Seric #ifdef NETINET 37858873Seric case AF_INET: 37958873Seric if (isascii(*v) && isdigit(*v)) 38058873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 38158873Seric else 38258873Seric { 38358873Seric register struct netent *np; 38458849Seric 38558873Seric np = getnetbyname(v); 38658873Seric if (np == NULL) 38758873Seric syserr("554 network \"%s\" unknown", v); 38858873Seric else 38958873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 39058873Seric } 39158873Seric break; 39258873Seric #endif 39358873Seric 39458873Seric default: 39558873Seric syserr("554 Address= option unsupported for family %d", 39658873Seric DaemonAddr.sa.sa_family); 39758873Seric break; 39858849Seric } 39958849Seric break; 40058849Seric 40158873Seric case 'P': /* port */ 40258873Seric switch (DaemonAddr.sa.sa_family) 40358849Seric { 40458873Seric short port; 40558849Seric 40658873Seric #ifdef NETINET 40758873Seric case AF_INET: 40858873Seric if (isascii(*v) && isdigit(*v)) 40958873Seric DaemonAddr.sin.sin_port = atoi(v); 41058849Seric else 41158873Seric { 41258873Seric register struct servent *sp; 41358873Seric 41458873Seric sp = getservbyname(v, "tcp"); 41558873Seric if (sp == NULL) 41658909Seric syserr("554 service \"%s\" unknown", v); 41758873Seric else 41858873Seric DaemonAddr.sin.sin_port = sp->s_port; 41958873Seric } 42058873Seric break; 42158873Seric #endif 42258873Seric 42358873Seric #ifdef NETISO 42458873Seric case AF_ISO: 42558873Seric /* assume two byte transport selector */ 42658873Seric if (isascii(*v) && isdigit(*v)) 42758873Seric port = atoi(v); 42858873Seric else 42958873Seric { 43058873Seric register struct servent *sp; 43158873Seric 43258873Seric sp = getservbyname(v, "tcp"); 43358873Seric if (sp == NULL) 43458909Seric syserr("554 service \"%s\" unknown", v); 43558873Seric else 43658873Seric port = sp->s_port; 43758873Seric } 43858873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 43958873Seric break; 44058873Seric #endif 44158873Seric 44258873Seric default: 44358873Seric syserr("554 Port= option unsupported for family %d", 44458873Seric DaemonAddr.sa.sa_family); 44558873Seric break; 44658849Seric } 44758849Seric break; 44859783Seric 44959783Seric case 'L': /* listen queue size */ 45059783Seric ListenQueueSize = atoi(v); 45159783Seric break; 45258849Seric } 45358849Seric } 45458849Seric } 45558849Seric /* 4566039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4576039Seric ** 4586039Seric ** Parameters: 4596039Seric ** host -- the name of the host. 4606633Seric ** port -- the port number to connect to. 46153739Seric ** mci -- a pointer to the mail connection information 46253739Seric ** structure to be filled in. 46352106Seric ** usesecureport -- if set, use a low numbered (reserved) 46452106Seric ** port to provide some rudimentary authentication. 4656039Seric ** 4666039Seric ** Returns: 4676039Seric ** An exit code telling whether the connection could be 4686039Seric ** made and if not why not. 4696039Seric ** 4706039Seric ** Side Effects: 4716039Seric ** none. 4726039Seric */ 4735978Seric 47458755Seric SOCKADDR CurHostAddr; /* address of current host */ 47558305Seric 47654967Seric int 47753739Seric makeconnection(host, port, mci, usesecureport) 4786039Seric char *host; 4797286Seric u_short port; 48054967Seric register MCI *mci; 48152106Seric bool usesecureport; 4826039Seric { 48329430Sbloom register int i, s; 48429430Sbloom register struct hostent *hp = (struct hostent *)NULL; 48558755Seric SOCKADDR addr; 48652106Seric int sav_errno; 48758755Seric int addrlen; 48835651Seric #ifdef NAMED_BIND 48935651Seric extern int h_errno; 49035651Seric #endif 4916039Seric 4926039Seric /* 4936039Seric ** Set up the address for the mailer. 4949308Seric ** Accept "[a.b.c.d]" syntax for host name. 4956039Seric */ 4966039Seric 49735651Seric #ifdef NAMED_BIND 49825475Smiriam h_errno = 0; 49935651Seric #endif 50025475Smiriam errno = 0; 50158864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 50258906Seric CurHostName = host; 50325475Smiriam 5049308Seric if (host[0] == '[') 5059308Seric { 50611147Seric long hid; 50756795Seric register char *p = strchr(host, ']'); 5089308Seric 50911147Seric if (p != NULL) 5109308Seric { 51111147Seric *p = '\0'; 51259884Seric #ifdef NETINET 51311147Seric hid = inet_addr(&host[1]); 51458360Seric if (hid == -1) 51559884Seric #endif 51658360Seric { 51758360Seric /* try it as a host name (avoid MX lookup) */ 51858360Seric hp = gethostbyname(&host[1]); 51958360Seric *p = ']'; 52058360Seric goto gothostent; 52158360Seric } 52211147Seric *p = ']'; 5239308Seric } 52458360Seric if (p == NULL) 5259308Seric { 52658151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5279308Seric return (EX_NOHOST); 5289308Seric } 52959884Seric #ifdef NETINET 53059884Seric addr.sin.sin_family = AF_INET; /*XXX*/ 53158778Seric addr.sin.sin_addr.s_addr = hid; 53259884Seric #endif 5339308Seric } 5349610Seric else 5359610Seric { 53629430Sbloom hp = gethostbyname(host); 53758360Seric gothostent: 53825475Smiriam if (hp == NULL) 53924945Seric { 54035651Seric #ifdef NAMED_BIND 54125475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 54225475Smiriam return (EX_TEMPFAIL); 54325657Seric 54435651Seric /* if name server is specified, assume temp fail */ 54535651Seric if (errno == ECONNREFUSED && UseNameServer) 54635651Seric return (EX_TEMPFAIL); 54735651Seric #endif 54825475Smiriam return (EX_NOHOST); 54924945Seric } 55058778Seric addr.sa.sa_family = hp->h_addrtype; 55158778Seric switch (hp->h_addrtype) 55258778Seric { 55358778Seric #ifdef NETINET 55458778Seric case AF_INET: 55558755Seric bcopy(hp->h_addr, 55658778Seric &addr.sin.sin_addr, 55758755Seric hp->h_length); 55858778Seric break; 55958778Seric #endif 56058778Seric 56158778Seric default: 56258755Seric bcopy(hp->h_addr, 56358778Seric addr.sa.sa_data, 56458755Seric hp->h_length); 56558778Seric break; 56658778Seric } 56729430Sbloom i = 1; 5689610Seric } 5699610Seric 5709610Seric /* 5719610Seric ** Determine the port number. 5729610Seric */ 5739610Seric 57410011Seric if (port != 0) 57558755Seric port = htons(port); 57610011Seric else 5779610Seric { 5789610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5799610Seric 5809610Seric if (sp == NULL) 5819610Seric { 58258909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 58357977Seric return (EX_OSERR); 5849610Seric } 58558755Seric port = sp->s_port; 5869610Seric } 5876039Seric 58858778Seric switch (addr.sa.sa_family) 58958755Seric { 59059884Seric #ifdef NETINET 59158755Seric case AF_INET: 59258778Seric addr.sin.sin_port = port; 59358755Seric addrlen = sizeof (struct sockaddr_in); 59458755Seric break; 59559884Seric #endif 59658755Seric 59758755Seric #ifdef NETISO 59858755Seric case AF_ISO: 59958755Seric /* assume two byte transport selector */ 60058755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 60158755Seric addrlen = sizeof (struct sockaddr_iso); 60258755Seric break; 60358755Seric #endif 60458755Seric 60558755Seric default: 60658778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 60758755Seric return (EX_NOHOST); 60858755Seric } 60958755Seric 6106039Seric /* 6116039Seric ** Try to actually open the connection. 6126039Seric */ 6136039Seric 61459156Seric #ifdef XLA 61559156Seric /* if too many connections, don't bother trying */ 61659156Seric if (!xla_noqueue_ok(host)) 61759156Seric return EX_TEMPFAIL; 61859156Seric #endif 61959156Seric 62057736Seric for (;;) 62152106Seric { 62257736Seric if (tTd(16, 1)) 62358755Seric printf("makeconnection (%s [%s])\n", 62458755Seric host, anynet_ntoa(&addr)); 62552106Seric 62658588Seric /* save for logging */ 62758588Seric CurHostAddr = addr; 62858588Seric 62957736Seric if (usesecureport) 63057736Seric { 63157736Seric int rport = IPPORT_RESERVED - 1; 6326039Seric 63357736Seric s = rresvport(&rport); 63457736Seric } 63557736Seric else 63657736Seric { 63757736Seric s = socket(AF_INET, SOCK_STREAM, 0); 63857736Seric } 63957736Seric if (s < 0) 64057736Seric { 64157736Seric sav_errno = errno; 64257736Seric syserr("makeconnection: no socket"); 64357736Seric goto failure; 64457736Seric } 64510347Seric 64657736Seric if (tTd(16, 1)) 64757736Seric printf("makeconnection: fd=%d\n", s); 64857736Seric 64957736Seric /* turn on network debugging? */ 65057736Seric if (tTd(16, 101)) 65157736Seric { 65257736Seric int on = 1; 65357736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 65457736Seric (char *)&on, sizeof on); 65557736Seric } 65657736Seric if (CurEnv->e_xfp != NULL) 65757736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 65857736Seric errno = 0; /* for debugging */ 65958755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 66057736Seric break; 66157736Seric 66257736Seric /* couldn't connect.... figure out why */ 66327744Sbloom sav_errno = errno; 66427744Sbloom (void) close(s); 66529430Sbloom if (hp && hp->h_addr_list[i]) 66629430Sbloom { 66758755Seric extern char *errstring(); 66858755Seric 66957736Seric if (tTd(16, 1)) 67058755Seric printf("Connect failed (%s); trying new address....\n", 67158755Seric errstring(sav_errno)); 67258778Seric switch (addr.sa.sa_family) 67358778Seric { 67458778Seric #ifdef NETINET 67558778Seric case AF_INET: 67658755Seric bcopy(hp->h_addr_list[i++], 67758778Seric &addr.sin.sin_addr, 67858755Seric hp->h_length); 67958778Seric break; 68058778Seric #endif 68158778Seric 68258778Seric default: 68358755Seric bcopy(hp->h_addr_list[i++], 68458778Seric addr.sa.sa_data, 68552106Seric hp->h_length); 68658778Seric break; 68758778Seric } 68857736Seric continue; 68929430Sbloom } 69029430Sbloom 6916039Seric /* failure, decide if temporary or not */ 6926039Seric failure: 69359254Seric #ifdef XLA 69459254Seric xla_host_end(host); 69559254Seric #endif 69658542Seric if (transienterror(sav_errno)) 69758542Seric return EX_TEMPFAIL; 69858542Seric else 69958542Seric { 70058542Seric extern char *errstring(); 70111147Seric 70258542Seric message("%s", errstring(sav_errno)); 70358542Seric return (EX_UNAVAILABLE); 7046039Seric } 7056039Seric } 7066039Seric 7076039Seric /* connection ok, put it into canonical form */ 70853739Seric mci->mci_out = fdopen(s, "w"); 70953739Seric mci->mci_in = fdopen(dup(s), "r"); 7106039Seric 71110098Seric return (EX_OK); 7126039Seric } 71310758Seric /* 71410758Seric ** MYHOSTNAME -- return the name of this host. 71510758Seric ** 71610758Seric ** Parameters: 71710758Seric ** hostbuf -- a place to return the name of this host. 71812313Seric ** size -- the size of hostbuf. 71910758Seric ** 72010758Seric ** Returns: 72110758Seric ** A list of aliases for this host. 72210758Seric ** 72310758Seric ** Side Effects: 72458110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 72510758Seric */ 7266039Seric 72758110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 72858110Seric 72910758Seric char ** 73012313Seric myhostname(hostbuf, size) 73110758Seric char hostbuf[]; 73212313Seric int size; 73310758Seric { 73458110Seric register struct hostent *hp; 73510758Seric extern struct hostent *gethostbyname(); 73610758Seric 73723120Seric if (gethostname(hostbuf, size) < 0) 73823120Seric { 73923120Seric (void) strcpy(hostbuf, "localhost"); 74023120Seric } 74111147Seric hp = gethostbyname(hostbuf); 74211147Seric if (hp != NULL) 74316877Seric { 74458110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 74558110Seric hostbuf[size - 1] = '\0'; 74658110Seric 74758110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 74858110Seric { 74958110Seric register int i; 75058110Seric 75158110Seric for (i = 0; i < MAXIPADDR; i++) 75258110Seric { 75358110Seric if (hp->h_addr_list[i] == NULL) 75458110Seric break; 75558110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 75658110Seric } 75758110Seric MyIpAddrs[i].s_addr = 0; 75858110Seric } 75958110Seric 76011147Seric return (hp->h_aliases); 76116877Seric } 76210758Seric else 76310758Seric return (NULL); 76410758Seric } 76551315Seric /* 76658951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 76758308Seric ** 76858951Seric ** Uses RFC1413 protocol to try to get info from the other end. 76958951Seric ** 77058308Seric ** Parameters: 77158308Seric ** fd -- the descriptor 77258308Seric ** 77358308Seric ** Returns: 77458951Seric ** The user@host information associated with this descriptor. 77558308Seric ** 77658308Seric ** Side Effects: 77758951Seric ** Sets RealHostName to the name of the host at the other end. 77858308Seric */ 77958308Seric 78058951Seric #ifdef IDENTPROTO 78158951Seric 78258951Seric static jmp_buf CtxAuthTimeout; 78358951Seric 78458951Seric static 78558951Seric authtimeout() 78658951Seric { 78758951Seric longjmp(CtxAuthTimeout, 1); 78858951Seric } 78958951Seric 79058951Seric #endif 79158951Seric 79258308Seric char * 79358951Seric getauthinfo(fd) 79458308Seric int fd; 79558308Seric { 79658951Seric SOCKADDR fa; 79758951Seric int falen; 79859104Seric register char *p; 79958951Seric #ifdef IDENTPROTO 80058951Seric SOCKADDR la; 80158951Seric int lalen; 80258951Seric register struct servent *sp; 80358951Seric int s; 80458951Seric int i; 80558951Seric EVENT *ev; 80658951Seric #endif 80758951Seric static char hbuf[MAXNAME * 2 + 2]; 80858951Seric extern char *hostnamebyanyaddr(); 80958951Seric extern char RealUserName[]; /* main.c */ 81058308Seric 81158951Seric falen = sizeof fa; 81258951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 81358951Seric { 81458951Seric RealHostName = "localhost"; 81558951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 81658957Seric if (tTd(9, 1)) 81758951Seric printf("getauthinfo: %s\n", hbuf); 81858951Seric return hbuf; 81958951Seric } 82058951Seric 82158951Seric RealHostName = newstr(hostnamebyanyaddr(&fa)); 82258951Seric RealHostAddr = fa; 82358951Seric 82458951Seric #ifdef IDENTPROTO 82558951Seric lalen = sizeof la; 82658951Seric if (fa.sa.sa_family != AF_INET || 82758951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 82858951Seric la.sa.sa_family != AF_INET) 82958951Seric { 83058951Seric /* no ident info */ 83158951Seric goto noident; 83258951Seric } 83358951Seric 83458951Seric /* create ident query */ 83558951Seric (void) sprintf(hbuf, "%d,%d\r\n", fa.sin.sin_port, la.sin.sin_port); 83658951Seric 83758951Seric /* create local address */ 83858951Seric bzero(&la, sizeof la); 83958951Seric 84058951Seric /* create foreign address */ 84158951Seric sp = getservbyname("auth", "tcp"); 84258951Seric if (sp != NULL) 84358951Seric fa.sin.sin_port = sp->s_port; 84458308Seric else 84559097Seric fa.sin.sin_port = htons(113); 84658951Seric 84758951Seric s = -1; 84858951Seric if (setjmp(CtxAuthTimeout) != 0) 84958951Seric { 85058951Seric if (s >= 0) 85158951Seric (void) close(s); 85258951Seric goto noident; 85358951Seric } 85458951Seric 85558951Seric /* put a timeout around the whole thing */ 85658951Seric ev = setevent((time_t) 30, authtimeout, 0); 85758951Seric 85858951Seric /* connect to foreign IDENT server */ 85958951Seric s = socket(AF_INET, SOCK_STREAM, 0); 86058951Seric if (s < 0) 86158951Seric { 86258951Seric clrevent(ev); 86358951Seric goto noident; 86458951Seric } 86558951Seric if (connect(s, &fa.sa, sizeof fa.sin) < 0) 86658951Seric { 86758951Seric closeident: 86858951Seric (void) close(s); 86958951Seric clrevent(ev); 87058951Seric goto noident; 87158951Seric } 87258951Seric 87358957Seric if (tTd(9, 10)) 87458951Seric printf("getauthinfo: sent %s", hbuf); 87558951Seric 87658951Seric /* send query */ 87758951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 87858951Seric goto closeident; 87958951Seric 88058951Seric /* get result */ 88158951Seric i = read(s, hbuf, sizeof hbuf); 88258951Seric (void) close(s); 88358951Seric clrevent(ev); 88458951Seric if (i <= 0) 88558951Seric goto noident; 88658951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 88758951Seric i--; 88858951Seric hbuf[++i] = '\0'; 88958951Seric 89058957Seric if (tTd(9, 3)) 89158951Seric printf("getauthinfo: got %s\n", hbuf); 89258951Seric 89358951Seric /* parse result */ 89458951Seric p = strchr(hbuf, ':'); 89558951Seric if (p == NULL) 89658951Seric { 89758951Seric /* malformed response */ 89858951Seric goto noident; 89958951Seric } 90058951Seric while (isascii(*++p) && isspace(*p)) 90158951Seric continue; 90258951Seric if (strncasecmp(p, "userid", 6) != 0) 90358951Seric { 90458951Seric /* presumably an error string */ 90558951Seric goto noident; 90658951Seric } 90758951Seric p += 6; 90858951Seric while (isascii(*p) && isspace(*p)) 90958951Seric p++; 91058951Seric if (*p++ != ':') 91158951Seric { 91258951Seric /* either useridxx or malformed response */ 91358951Seric goto noident; 91458951Seric } 91558951Seric 91658951Seric /* p now points to the OSTYPE field */ 91758951Seric p = strchr(p, ':'); 91858951Seric if (p == NULL) 91958951Seric { 92058951Seric /* malformed response */ 92158951Seric goto noident; 92258951Seric } 92358951Seric 92458957Seric /* 1413 says don't do this -- but it's broken otherwise */ 92558957Seric while (isascii(*++p) && isspace(*p)) 92658957Seric continue; 92758957Seric 92858951Seric /* p now points to the authenticated name */ 92958951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 93058957Seric goto finish; 93158957Seric 93258957Seric #endif /* IDENTPROTO */ 93358957Seric 93458957Seric noident: 93558957Seric (void) strcpy(hbuf, RealHostName); 93658957Seric 93758957Seric finish: 93858951Seric if (RealHostName[0] != '[') 93958951Seric { 94058951Seric p = &hbuf[strlen(hbuf)]; 94158951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 94258951Seric } 94358957Seric if (tTd(9, 1)) 94458951Seric printf("getauthinfo: %s\n", hbuf); 94558308Seric return hbuf; 94658308Seric } 94758308Seric /* 94853751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 94953751Seric ** 95053751Seric ** Parameters: 95156823Seric ** map -- a pointer to this map (unused). 95253751Seric ** hbuf -- a buffer containing a hostname. 95353751Seric ** hbsize -- the size of hbuf. 95455019Seric ** avp -- unused -- for compatibility with other mapping 95555019Seric ** functions. 95659084Seric ** statp -- an exit status (out parameter) -- set to 95759084Seric ** EX_TEMPFAIL if the name server is unavailable. 95853751Seric ** 95953751Seric ** Returns: 96053751Seric ** The mapping, if found. 96153751Seric ** NULL if no mapping found. 96253751Seric ** 96353751Seric ** Side Effects: 96453751Seric ** Looks up the host specified in hbuf. If it is not 96553751Seric ** the canonical name for that host, return the canonical 96653751Seric ** name. 96753751Seric */ 96851315Seric 96953751Seric char * 97059084Seric maphostname(map, hbuf, hbsize, avp, statp) 97156823Seric MAP *map; 97216911Seric char *hbuf; 97316911Seric int hbsize; 97453751Seric char **avp; 97559084Seric int *statp; 97616911Seric { 97716911Seric register struct hostent *hp; 97833932Sbostic u_long in_addr; 97956823Seric char *cp; 98058110Seric int i; 98159671Seric register STAB *s; 98259671Seric extern struct hostent *gethostbyaddr(); 98359671Seric extern int h_errno; 98416911Seric 98556836Seric /* allow room for null */ 98656823Seric hbsize--; 98753751Seric 98825574Smiriam /* 98959671Seric ** See if we have already looked up this name. If so, just 99059671Seric ** return it. 99159671Seric */ 99253751Seric 99359671Seric s = stab(hbuf, ST_NAMECANON, ST_ENTER); 99459671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 99559671Seric { 99659986Seric if (tTd(9, 1)) 99759986Seric printf("maphostname(%s, %d) => CACHE %s\n", 99859986Seric hbuf, hbsize, s->s_namecanon.nc_cname); 99959671Seric errno = s->s_namecanon.nc_errno; 100059671Seric h_errno = s->s_namecanon.nc_herrno; 100159671Seric *statp = s->s_namecanon.nc_stat; 100259671Seric return s->s_namecanon.nc_cname; 100359671Seric } 100459671Seric 100559671Seric /* 100659671Seric ** If first character is a bracket, then it is an address 100759671Seric ** lookup. Address is copied into a temporary buffer to 100859671Seric ** strip the brackets and to preserve hbuf if address is 100959671Seric ** unknown. 101059671Seric */ 101159671Seric 101251315Seric if (*hbuf != '[') 101353751Seric { 101455019Seric extern bool getcanonname(); 101555019Seric 101658798Seric if (tTd(9, 1)) 101758798Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 101859671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 101958674Seric if (getcanonname(hbuf, hbsize)) 102058796Seric { 102158796Seric if (tTd(9, 1)) 102258796Seric printf("%s\n", hbuf); 102359671Seric s->s_namecanon.nc_cname = newstr(hbuf); 102453751Seric return hbuf; 102558796Seric } 102653751Seric else 102758796Seric { 102859084Seric register struct hostent *hp; 102959084Seric 103058796Seric if (tTd(9, 1)) 103159084Seric printf("FAIL (%d)\n", h_errno); 103259671Seric s->s_namecanon.nc_errno = errno; 103359671Seric s->s_namecanon.nc_herrno = h_errno; 103459084Seric switch (h_errno) 103559084Seric { 103659084Seric case TRY_AGAIN: 103759596Seric if (UseNameServer) 103859734Seric { 103959734Seric char *msg = "Recipient domain nameserver timed out"; 104059734Seric 104159734Seric message(msg); 104259734Seric if (CurEnv->e_message == NULL) 1043*60009Seric CurEnv->e_message = newstr(msg); 104459734Seric } 104559084Seric *statp = EX_TEMPFAIL; 104659084Seric break; 104759084Seric 104859084Seric case HOST_NOT_FOUND: 104959084Seric *statp = EX_NOHOST; 105059084Seric break; 105159084Seric 105259084Seric case NO_RECOVERY: 105359084Seric *statp = EX_SOFTWARE; 105459084Seric break; 105559084Seric 105659084Seric default: 105759084Seric *statp = EX_UNAVAILABLE; 105859084Seric break; 105959084Seric } 106059671Seric s->s_namecanon.nc_stat = *statp; 106159084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 106259084Seric return NULL; 106359084Seric 106459084Seric /* 106559084Seric ** Try to look it up in /etc/hosts 106659084Seric */ 106759084Seric 106859084Seric hp = gethostbyname(hbuf); 106959084Seric if (hp == NULL) 107059084Seric { 107159084Seric /* no dice there either */ 107259671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 107359084Seric return NULL; 107459084Seric } 107559084Seric 107659671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 107759671Seric s->s_namecanon.nc_cname = newstr(hp->h_name); 107859084Seric return hp->h_name; 107958796Seric } 108053751Seric } 108156823Seric if ((cp = strchr(hbuf, ']')) == NULL) 108253751Seric return (NULL); 108340994Sbostic *cp = '\0'; 108456823Seric in_addr = inet_addr(&hbuf[1]); 108558110Seric 108658110Seric /* check to see if this is one of our addresses */ 108758110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 108858110Seric { 108958110Seric if (MyIpAddrs[i].s_addr == in_addr) 109058110Seric { 109158110Seric strncpy(hbuf, MyHostName, hbsize); 109258110Seric hbuf[hbsize] = '\0'; 109358110Seric return hbuf; 109458110Seric } 109558110Seric } 109658110Seric 109758110Seric /* nope -- ask the name server */ 109833932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 109959671Seric s->s_namecanon.nc_errno = errno; 110059671Seric s->s_namecanon.nc_herrno = h_errno; 110159671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 110233932Sbostic if (hp == NULL) 110359671Seric { 110459671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 110553751Seric return (NULL); 110659671Seric } 110753751Seric 110858110Seric /* found a match -- copy out */ 110959671Seric s->s_namecanon.nc_cname = newstr(hp->h_name); 111056823Seric if (strlen(hp->h_name) > hbsize) 111156823Seric hp->h_name[hbsize] = '\0'; 111253751Seric (void) strcpy(hbuf, hp->h_name); 111359671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 111453751Seric return hbuf; 111533932Sbostic } 111658755Seric /* 111758755Seric ** ANYNET_NTOA -- convert a network address to printable form. 111858755Seric ** 111958755Seric ** Parameters: 112058755Seric ** sap -- a pointer to a sockaddr structure. 112158755Seric ** 112258755Seric ** Returns: 112358755Seric ** A printable version of that sockaddr. 112458755Seric */ 112516911Seric 112658755Seric char * 112758755Seric anynet_ntoa(sap) 112858755Seric register SOCKADDR *sap; 112958755Seric { 113058755Seric register char *bp; 113158755Seric register char *ap; 113258755Seric int l; 113358755Seric static char buf[80]; 113458755Seric 113558798Seric /* check for null/zero family */ 113658798Seric if (sap == NULL) 113758798Seric return "NULLADDR"; 113858798Seric if (sap->sa.sa_family == 0) 113958798Seric return "0"; 114058798Seric 114158778Seric #ifdef NETINET 114258778Seric if (sap->sa.sa_family == AF_INET) 114358755Seric { 114458755Seric extern char *inet_ntoa(); 114558755Seric 114658755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 114758755Seric } 114858778Seric #endif 114958755Seric 115058755Seric /* unknown family -- just dump bytes */ 115158778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 115258755Seric bp = &buf[strlen(buf)]; 115358778Seric ap = sap->sa.sa_data; 115458778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 115558755Seric { 115658755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 115758755Seric bp += 3; 115858755Seric } 115958755Seric *--bp = '\0'; 116058755Seric return buf; 116158755Seric } 116258951Seric /* 116358951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 116458951Seric ** 116558951Seric ** Parameters: 116658951Seric ** sap -- SOCKADDR pointer 116758951Seric ** 116858951Seric ** Returns: 116958951Seric ** text representation of host name. 117058951Seric ** 117158951Seric ** Side Effects: 117258951Seric ** none. 117358951Seric */ 117458755Seric 117558951Seric char * 117658951Seric hostnamebyanyaddr(sap) 117758951Seric register SOCKADDR *sap; 117858951Seric { 117958951Seric register struct hostent *hp; 118058951Seric 118159042Seric #ifdef NAMED_BIND 118259042Seric int saveretry; 118359042Seric 118459042Seric /* shorten name server timeout to avoid higher level timeouts */ 118559042Seric saveretry = _res.retry; 118659042Seric _res.retry = 3; 118759042Seric #endif /* NAMED_BIND */ 118859042Seric 118958951Seric switch (sap->sa.sa_family) 119058951Seric { 119158951Seric #ifdef NETINET 119258951Seric case AF_INET: 119358951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 119458951Seric sizeof sap->sin.sin_addr, 119558951Seric AF_INET); 119658951Seric break; 119758951Seric #endif 119858951Seric 119958951Seric #ifdef NETISO 120058951Seric case AF_ISO: 120158951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 120258951Seric sizeof sap->siso.siso_addr, 120358951Seric AF_ISO); 120458951Seric break; 120558951Seric #endif 120658951Seric 120758951Seric default: 120858951Seric hp = gethostbyaddr(sap->sa.sa_data, 120958951Seric sizeof sap->sa.sa_data, 121058951Seric sap->sa.sa_family); 121158951Seric break; 121258951Seric } 121358951Seric 121459042Seric #ifdef NAMED_BIND 121559042Seric _res.retry = saveretry; 121659042Seric #endif /* NAMED_BIND */ 121759042Seric 121858951Seric if (hp != NULL) 121958951Seric return hp->h_name; 122058951Seric else 122158951Seric { 122258951Seric /* produce a dotted quad */ 122358951Seric static char buf[512]; 122458951Seric 122558951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 122658951Seric return buf; 122758951Seric } 122858951Seric } 122958951Seric 123056795Seric # else /* DAEMON */ 123116911Seric /* code for systems without sophisticated networking */ 123210758Seric 123310758Seric /* 123410758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 123511297Seric ** 123611297Seric ** Can't convert to upper case here because might be a UUCP name. 123712313Seric ** 123812313Seric ** Mark, you can change this to be anything you want...... 123910758Seric */ 124010758Seric 124110758Seric char ** 124212313Seric myhostname(hostbuf, size) 124310758Seric char hostbuf[]; 124412313Seric int size; 124510758Seric { 124610758Seric register FILE *f; 124710758Seric 124810758Seric hostbuf[0] = '\0'; 124910758Seric f = fopen("/usr/include/whoami", "r"); 125010758Seric if (f != NULL) 125110758Seric { 125212313Seric (void) fgets(hostbuf, size, f); 125310758Seric fixcrlf(hostbuf, TRUE); 125410758Seric (void) fclose(f); 125510758Seric } 125610758Seric return (NULL); 125710758Seric } 125816911Seric /* 125958951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 126058308Seric ** 126158308Seric ** Parameters: 126258308Seric ** fd -- the descriptor 126358308Seric ** 126458308Seric ** Returns: 126558308Seric ** The host name associated with this descriptor, if it can 126658308Seric ** be determined. 126758308Seric ** NULL otherwise. 126858308Seric ** 126958308Seric ** Side Effects: 127058308Seric ** none 127158308Seric */ 127258308Seric 127358308Seric char * 127458951Seric getauthinfo(fd) 127558308Seric int fd; 127658308Seric { 127758308Seric return NULL; 127858308Seric } 127958308Seric /* 128016911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 128116911Seric ** 128216911Seric ** Parameters: 128356823Seric ** map -- a pointer to the database map. 128416911Seric ** hbuf -- a buffer containing a hostname. 128559084Seric ** hbsize -- size of hbuf. 128653751Seric ** avp -- a pointer to a (cf file defined) argument vector. 128759084Seric ** statp -- an exit status (out parameter). 128816911Seric ** 128916911Seric ** Returns: 129053751Seric ** mapped host name 129151315Seric ** FALSE otherwise. 129216911Seric ** 129316911Seric ** Side Effects: 129416911Seric ** Looks up the host specified in hbuf. If it is not 129516911Seric ** the canonical name for that host, replace it with 129616911Seric ** the canonical name. If the name is unknown, or it 129716911Seric ** is already the canonical name, leave it unchanged. 129816911Seric */ 129910758Seric 130016911Seric /*ARGSUSED*/ 130153751Seric char * 130259084Seric maphostname(map, hbuf, hbsize, avp, statp) 130356823Seric MAP *map; 130416911Seric char *hbuf; 130516911Seric int hbsize; 130653751Seric char **avp; 130759084Seric char *statp; 130816911Seric { 130959084Seric register struct hostent *hp; 131059084Seric 131159084Seric hp = gethostbyname(hbuf); 131259084Seric if (hp != NULL) 131359084Seric return hp->h_name; 131459084Seric *statp = EX_NOHOST; 131553751Seric return NULL; 131616911Seric } 131716911Seric 131856795Seric #endif /* DAEMON */ 1319