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*59734Seric static char sccsid[] = "@(#)daemon.c 6.44 (Berkeley) 05/04/93 (with daemon mode)"; 1633780Sbostic #else 17*59734Seric static char sccsid[] = "@(#)daemon.c 6.44 (Berkeley) 05/04/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 */ 8316144Seric 844535Seric getrequests() 854535Seric { 869610Seric int t; 879610Seric register struct servent *sp; 8825027Seric int on = 1; 8953751Seric bool refusingconnections = TRUE; 9058419Seric FILE *pidf; 9146928Sbostic extern void reapchild(); 927117Seric 939610Seric /* 949610Seric ** Set up the address for the mailer. 959610Seric */ 969610Seric 9758849Seric if (DaemonAddr.sin.sin_family == 0) 9858849Seric DaemonAddr.sin.sin_family = AF_INET; 9958849Seric if (DaemonAddr.sin.sin_addr.s_addr == 0) 10058849Seric DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 10158849Seric if (DaemonAddr.sin.sin_port == 0) 1029610Seric { 10358849Seric sp = getservbyname("smtp", "tcp"); 10458849Seric if (sp == NULL) 10558849Seric { 10658909Seric syserr("554 service \"smtp\" unknown"); 10758849Seric goto severe; 10858849Seric } 10958849Seric DaemonAddr.sin.sin_port = sp->s_port; 1109610Seric } 1119610Seric 1129610Seric /* 1139610Seric ** Try to actually open the connection. 1149610Seric */ 1159610Seric 1169610Seric if (tTd(15, 1)) 11758849Seric printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port); 1189610Seric 1199610Seric /* get a socket for the SMTP connection */ 12059041Seric DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 12110206Seric if (DaemonSocket < 0) 1229610Seric { 1239610Seric /* probably another daemon already */ 1249610Seric syserr("getrequests: can't create socket"); 1259610Seric severe: 1269610Seric # ifdef LOG 1279610Seric if (LogLevel > 0) 12857663Seric syslog(LOG_ALERT, "problem creating SMTP socket"); 12956795Seric # endif /* LOG */ 1309610Seric finis(); 1319610Seric } 13210347Seric 13310347Seric /* turn on network debugging? */ 13456328Seric if (tTd(15, 101)) 13524945Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 13610347Seric 13725027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 13825027Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 13925027Seric 14059041Seric switch (DaemonAddr.sa.sa_family) 1419610Seric { 14259041Seric # ifdef NETINET 14359041Seric case AF_INET: 14459041Seric t = sizeof DaemonAddr.sin; 14559041Seric break; 14659041Seric # endif 14759041Seric 14859041Seric # ifdef NETISO 14959041Seric case AF_ISO: 15059041Seric t = sizeof DaemonAddr.siso; 15159041Seric break; 15259041Seric # endif 15359041Seric 15459041Seric default: 15559041Seric t = sizeof DaemonAddr; 15659041Seric break; 15759041Seric } 15859041Seric 15959041Seric if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0) 16059041Seric { 1619610Seric syserr("getrequests: cannot bind"); 16210206Seric (void) close(DaemonSocket); 1639610Seric goto severe; 1649610Seric } 1659610Seric 16624955Seric (void) signal(SIGCHLD, reapchild); 16724945Seric 16858419Seric /* write the pid to the log file for posterity */ 16958419Seric pidf = fopen(PidFile, "w"); 17058419Seric if (pidf != NULL) 17158419Seric { 17258419Seric fprintf(pidf, "%d\n", getpid()); 17358419Seric fclose(pidf); 17458419Seric } 17558419Seric 17658419Seric 1779610Seric if (tTd(15, 1)) 17810206Seric printf("getrequests: %d\n", DaemonSocket); 1799610Seric 1804631Seric for (;;) 1814631Seric { 18214875Seric register int pid; 18311147Seric auto int lotherend; 18453751Seric extern bool refuseconnections(); 18511147Seric 18614875Seric /* see if we are rejecting connections */ 18753751Seric CurrentLA = getla(); 18853751Seric if (refuseconnections()) 18936584Sbostic { 19053751Seric if (!refusingconnections) 19153751Seric { 19253751Seric /* don't queue so peer will fail quickly */ 19353751Seric (void) listen(DaemonSocket, 0); 19453751Seric refusingconnections = TRUE; 19553751Seric } 19657385Seric setproctitle("rejecting connections: load average: %d", 19757385Seric CurrentLA); 19814875Seric sleep(5); 19953751Seric continue; 20036584Sbostic } 20114875Seric 20253751Seric if (refusingconnections) 20353751Seric { 20453751Seric /* start listening again */ 20553751Seric if (listen(DaemonSocket, 10) < 0) 20653751Seric { 20753751Seric syserr("getrequests: cannot listen"); 20853751Seric (void) close(DaemonSocket); 20953751Seric goto severe; 21053751Seric } 21153751Seric setproctitle("accepting connections"); 21253751Seric refusingconnections = FALSE; 21353751Seric } 21453751Seric 2159610Seric /* wait for a connection */ 2169610Seric do 2179610Seric { 2189610Seric errno = 0; 21936230Skarels lotherend = sizeof RealHostAddr; 22046928Sbostic t = accept(DaemonSocket, 22146928Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 2229610Seric } while (t < 0 && errno == EINTR); 2239610Seric if (t < 0) 2245978Seric { 2259610Seric syserr("getrequests: accept"); 2269610Seric sleep(5); 2279610Seric continue; 2285978Seric } 2294631Seric 2305978Seric /* 2315978Seric ** Create a subprocess to process the mail. 2325978Seric */ 2335978Seric 2347677Seric if (tTd(15, 2)) 2359610Seric printf("getrequests: forking (fd = %d)\n", t); 2365978Seric 2374636Seric pid = fork(); 2384636Seric if (pid < 0) 2394631Seric { 2404636Seric syserr("daemon: cannot fork"); 2414636Seric sleep(10); 2429610Seric (void) close(t); 2434636Seric continue; 2444631Seric } 2454631Seric 2464636Seric if (pid == 0) 2474631Seric { 24858951Seric extern char *hostnamebyanyaddr(); 24911147Seric 2504636Seric /* 2514636Seric ** CHILD -- return to caller. 25211147Seric ** Collect verified idea of sending host. 2534636Seric ** Verify calling user id if possible here. 2544636Seric */ 2554631Seric 25624955Seric (void) signal(SIGCHLD, SIG_DFL); 25759156Seric OpMode = MD_SMTP; 25824950Seric 25911147Seric /* determine host name */ 26058951Seric RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 26158778Seric 26255173Seric #ifdef LOG 26357977Seric if (LogLevel > 10) 26455173Seric { 26555173Seric /* log connection information */ 26655173Seric syslog(LOG_INFO, "connect from %s (%s)", 26758951Seric RealHostName, anynet_ntoa(&RealHostAddr)); 26855173Seric } 26955173Seric #endif 27055173Seric 27159254Seric (void) close(DaemonSocket); 27259254Seric InChannel = fdopen(t, "r"); 27359254Seric OutChannel = fdopen(dup(t), "w"); 27459254Seric 27516884Seric /* should we check for illegal connection here? XXX */ 27659156Seric #ifdef XLA 27759156Seric if (!xla_host_ok(RealHostName)) 27859156Seric { 27959254Seric message("421 Too many SMTP sessions for this host"); 28059156Seric exit(0); 28159156Seric } 28259156Seric #endif 28316884Seric 2847677Seric if (tTd(15, 2)) 2855978Seric printf("getreq: returning\n"); 2864636Seric return; 2874631Seric } 2884631Seric 2897117Seric /* close the port so that others will hang (for a while) */ 2909610Seric (void) close(t); 2914631Seric } 2929886Seric /*NOTREACHED*/ 2934631Seric } 2945978Seric /* 29510206Seric ** CLRDAEMON -- reset the daemon connection 29610206Seric ** 29710206Seric ** Parameters: 29810206Seric ** none. 29910206Seric ** 30010206Seric ** Returns: 30110206Seric ** none. 30210206Seric ** 30310206Seric ** Side Effects: 30410206Seric ** releases any resources used by the passive daemon. 30510206Seric */ 30610206Seric 30710206Seric clrdaemon() 30810206Seric { 30910206Seric if (DaemonSocket >= 0) 31010206Seric (void) close(DaemonSocket); 31110206Seric DaemonSocket = -1; 31210206Seric } 31310206Seric /* 31458849Seric ** SETDAEMONOPTIONS -- set options for running the daemon 31558849Seric ** 31658849Seric ** Parameters: 31758849Seric ** p -- the options line. 31858849Seric ** 31958849Seric ** Returns: 32058849Seric ** none. 32158849Seric */ 32258849Seric 32358849Seric setdaemonoptions(p) 32458849Seric register char *p; 32558849Seric { 32658873Seric if (DaemonAddr.sa.sa_family == AF_UNSPEC) 32758873Seric DaemonAddr.sa.sa_family = AF_INET; 32858873Seric 32958849Seric while (p != NULL) 33058849Seric { 33158849Seric register char *f; 33258849Seric register char *v; 33358849Seric 33458849Seric while (isascii(*p) && isspace(*p)) 33558849Seric p++; 33658849Seric if (*p == '\0') 33758849Seric break; 33858849Seric f = p; 33958849Seric p = strchr(p, ','); 34058849Seric if (p != NULL) 34158849Seric *p++ = '\0'; 34258849Seric v = strchr(f, '='); 34358849Seric if (v == NULL) 34458849Seric continue; 34558849Seric while (isascii(*++v) && isspace(*v)) 34658849Seric continue; 34758849Seric 34858849Seric switch (*f) 34958849Seric { 35058873Seric case 'F': /* address family */ 35158849Seric if (isascii(*v) && isdigit(*v)) 35258873Seric DaemonAddr.sa.sa_family = atoi(v); 35358873Seric #ifdef NETINET 35458873Seric else if (strcasecmp(v, "inet") == 0) 35558873Seric DaemonAddr.sa.sa_family = AF_INET; 35658873Seric #endif 35758873Seric #ifdef NETISO 35858873Seric else if (strcasecmp(v, "iso") == 0) 35958873Seric DaemonAddr.sa.sa_family = AF_ISO; 36058873Seric #endif 36158873Seric #ifdef NETNS 36258873Seric else if (strcasecmp(v, "ns") == 0) 36358873Seric DaemonAddr.sa.sa_family = AF_NS; 36458873Seric #endif 36558873Seric #ifdef NETX25 36658873Seric else if (strcasecmp(v, "x.25") == 0) 36758873Seric DaemonAddr.sa.sa_family = AF_CCITT; 36858873Seric #endif 36958849Seric else 37058873Seric syserr("554 Unknown address family %s in Family=option", v); 37158873Seric break; 37258873Seric 37358873Seric case 'A': /* address */ 37458873Seric switch (DaemonAddr.sa.sa_family) 37558849Seric { 37658873Seric #ifdef NETINET 37758873Seric case AF_INET: 37858873Seric if (isascii(*v) && isdigit(*v)) 37958873Seric DaemonAddr.sin.sin_addr.s_addr = inet_network(v); 38058873Seric else 38158873Seric { 38258873Seric register struct netent *np; 38358849Seric 38458873Seric np = getnetbyname(v); 38558873Seric if (np == NULL) 38658873Seric syserr("554 network \"%s\" unknown", v); 38758873Seric else 38858873Seric DaemonAddr.sin.sin_addr.s_addr = np->n_net; 38958873Seric } 39058873Seric break; 39158873Seric #endif 39258873Seric 39358873Seric default: 39458873Seric syserr("554 Address= option unsupported for family %d", 39558873Seric DaemonAddr.sa.sa_family); 39658873Seric break; 39758849Seric } 39858849Seric break; 39958849Seric 40058873Seric case 'P': /* port */ 40158873Seric switch (DaemonAddr.sa.sa_family) 40258849Seric { 40358873Seric short port; 40458849Seric 40558873Seric #ifdef NETINET 40658873Seric case AF_INET: 40758873Seric if (isascii(*v) && isdigit(*v)) 40858873Seric DaemonAddr.sin.sin_port = atoi(v); 40958849Seric else 41058873Seric { 41158873Seric register struct servent *sp; 41258873Seric 41358873Seric sp = getservbyname(v, "tcp"); 41458873Seric if (sp == NULL) 41558909Seric syserr("554 service \"%s\" unknown", v); 41658873Seric else 41758873Seric DaemonAddr.sin.sin_port = sp->s_port; 41858873Seric } 41958873Seric break; 42058873Seric #endif 42158873Seric 42258873Seric #ifdef NETISO 42358873Seric case AF_ISO: 42458873Seric /* assume two byte transport selector */ 42558873Seric if (isascii(*v) && isdigit(*v)) 42658873Seric port = atoi(v); 42758873Seric else 42858873Seric { 42958873Seric register struct servent *sp; 43058873Seric 43158873Seric sp = getservbyname(v, "tcp"); 43258873Seric if (sp == NULL) 43358909Seric syserr("554 service \"%s\" unknown", v); 43458873Seric else 43558873Seric port = sp->s_port; 43658873Seric } 43758873Seric bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 43858873Seric break; 43958873Seric #endif 44058873Seric 44158873Seric default: 44258873Seric syserr("554 Port= option unsupported for family %d", 44358873Seric DaemonAddr.sa.sa_family); 44458873Seric break; 44558849Seric } 44658849Seric break; 44758849Seric } 44858849Seric } 44958849Seric } 45058849Seric /* 4516039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 4526039Seric ** 4536039Seric ** Parameters: 4546039Seric ** host -- the name of the host. 4556633Seric ** port -- the port number to connect to. 45653739Seric ** mci -- a pointer to the mail connection information 45753739Seric ** structure to be filled in. 45852106Seric ** usesecureport -- if set, use a low numbered (reserved) 45952106Seric ** port to provide some rudimentary authentication. 4606039Seric ** 4616039Seric ** Returns: 4626039Seric ** An exit code telling whether the connection could be 4636039Seric ** made and if not why not. 4646039Seric ** 4656039Seric ** Side Effects: 4666039Seric ** none. 4676039Seric */ 4685978Seric 46958755Seric SOCKADDR CurHostAddr; /* address of current host */ 47058305Seric 47154967Seric int 47253739Seric makeconnection(host, port, mci, usesecureport) 4736039Seric char *host; 4747286Seric u_short port; 47554967Seric register MCI *mci; 47652106Seric bool usesecureport; 4776039Seric { 47829430Sbloom register int i, s; 47929430Sbloom register struct hostent *hp = (struct hostent *)NULL; 48058755Seric SOCKADDR addr; 48152106Seric int sav_errno; 48258755Seric int addrlen; 48335651Seric #ifdef NAMED_BIND 48435651Seric extern int h_errno; 48535651Seric #endif 4866039Seric 4876039Seric /* 4886039Seric ** Set up the address for the mailer. 4899308Seric ** Accept "[a.b.c.d]" syntax for host name. 4906039Seric */ 4916039Seric 49235651Seric #ifdef NAMED_BIND 49325475Smiriam h_errno = 0; 49435651Seric #endif 49525475Smiriam errno = 0; 49658864Seric bzero(&CurHostAddr, sizeof CurHostAddr); 49758906Seric CurHostName = host; 49825475Smiriam 4999308Seric if (host[0] == '[') 5009308Seric { 50111147Seric long hid; 50256795Seric register char *p = strchr(host, ']'); 5039308Seric 50411147Seric if (p != NULL) 5059308Seric { 50611147Seric *p = '\0'; 50711147Seric hid = inet_addr(&host[1]); 50858360Seric if (hid == -1) 50958360Seric { 51058360Seric /* try it as a host name (avoid MX lookup) */ 51158360Seric hp = gethostbyname(&host[1]); 51258360Seric *p = ']'; 51358360Seric goto gothostent; 51458360Seric } 51511147Seric *p = ']'; 5169308Seric } 51758360Seric if (p == NULL) 5189308Seric { 51958151Seric usrerr("553 Invalid numeric domain spec \"%s\"", host); 5209308Seric return (EX_NOHOST); 5219308Seric } 52258778Seric addr.sin.sin_family = AF_INET; 52358778Seric addr.sin.sin_addr.s_addr = hid; 5249308Seric } 5259610Seric else 5269610Seric { 52729430Sbloom hp = gethostbyname(host); 52858360Seric gothostent: 52925475Smiriam if (hp == NULL) 53024945Seric { 53135651Seric #ifdef NAMED_BIND 53225475Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 53325475Smiriam return (EX_TEMPFAIL); 53425657Seric 53535651Seric /* if name server is specified, assume temp fail */ 53635651Seric if (errno == ECONNREFUSED && UseNameServer) 53735651Seric return (EX_TEMPFAIL); 53835651Seric #endif 53925475Smiriam return (EX_NOHOST); 54024945Seric } 54158778Seric addr.sa.sa_family = hp->h_addrtype; 54258778Seric switch (hp->h_addrtype) 54358778Seric { 54458778Seric #ifdef NETINET 54558778Seric case AF_INET: 54658755Seric bcopy(hp->h_addr, 54758778Seric &addr.sin.sin_addr, 54858755Seric hp->h_length); 54958778Seric break; 55058778Seric #endif 55158778Seric 55258778Seric default: 55358755Seric bcopy(hp->h_addr, 55458778Seric addr.sa.sa_data, 55558755Seric hp->h_length); 55658778Seric break; 55758778Seric } 55829430Sbloom i = 1; 5599610Seric } 5609610Seric 5619610Seric /* 5629610Seric ** Determine the port number. 5639610Seric */ 5649610Seric 56510011Seric if (port != 0) 56658755Seric port = htons(port); 56710011Seric else 5689610Seric { 5699610Seric register struct servent *sp = getservbyname("smtp", "tcp"); 5709610Seric 5719610Seric if (sp == NULL) 5729610Seric { 57358909Seric syserr("554 makeconnection: service \"smtp\" unknown"); 57457977Seric return (EX_OSERR); 5759610Seric } 57658755Seric port = sp->s_port; 5779610Seric } 5786039Seric 57958778Seric switch (addr.sa.sa_family) 58058755Seric { 58158755Seric case AF_INET: 58258778Seric addr.sin.sin_port = port; 58358755Seric addrlen = sizeof (struct sockaddr_in); 58458755Seric break; 58558755Seric 58658755Seric #ifdef NETISO 58758755Seric case AF_ISO: 58858755Seric /* assume two byte transport selector */ 58958755Seric bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 59058755Seric addrlen = sizeof (struct sockaddr_iso); 59158755Seric break; 59258755Seric #endif 59358755Seric 59458755Seric default: 59558778Seric syserr("Can't connect to address family %d", addr.sa.sa_family); 59658755Seric return (EX_NOHOST); 59758755Seric } 59858755Seric 5996039Seric /* 6006039Seric ** Try to actually open the connection. 6016039Seric */ 6026039Seric 60359156Seric #ifdef XLA 60459156Seric /* if too many connections, don't bother trying */ 60559156Seric if (!xla_noqueue_ok(host)) 60659156Seric return EX_TEMPFAIL; 60759156Seric #endif 60859156Seric 60957736Seric for (;;) 61052106Seric { 61157736Seric if (tTd(16, 1)) 61258755Seric printf("makeconnection (%s [%s])\n", 61358755Seric host, anynet_ntoa(&addr)); 61452106Seric 61558588Seric /* save for logging */ 61658588Seric CurHostAddr = addr; 61758588Seric 61857736Seric if (usesecureport) 61957736Seric { 62057736Seric int rport = IPPORT_RESERVED - 1; 6216039Seric 62257736Seric s = rresvport(&rport); 62357736Seric } 62457736Seric else 62557736Seric { 62657736Seric s = socket(AF_INET, SOCK_STREAM, 0); 62757736Seric } 62857736Seric if (s < 0) 62957736Seric { 63057736Seric sav_errno = errno; 63157736Seric syserr("makeconnection: no socket"); 63257736Seric goto failure; 63357736Seric } 63410347Seric 63557736Seric if (tTd(16, 1)) 63657736Seric printf("makeconnection: fd=%d\n", s); 63757736Seric 63857736Seric /* turn on network debugging? */ 63957736Seric if (tTd(16, 101)) 64057736Seric { 64157736Seric int on = 1; 64257736Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 64357736Seric (char *)&on, sizeof on); 64457736Seric } 64557736Seric if (CurEnv->e_xfp != NULL) 64657736Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 64757736Seric errno = 0; /* for debugging */ 64858755Seric if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 64957736Seric break; 65057736Seric 65157736Seric /* couldn't connect.... figure out why */ 65227744Sbloom sav_errno = errno; 65327744Sbloom (void) close(s); 65429430Sbloom if (hp && hp->h_addr_list[i]) 65529430Sbloom { 65658755Seric extern char *errstring(); 65758755Seric 65857736Seric if (tTd(16, 1)) 65958755Seric printf("Connect failed (%s); trying new address....\n", 66058755Seric errstring(sav_errno)); 66158778Seric switch (addr.sa.sa_family) 66258778Seric { 66358778Seric #ifdef NETINET 66458778Seric case AF_INET: 66558755Seric bcopy(hp->h_addr_list[i++], 66658778Seric &addr.sin.sin_addr, 66758755Seric hp->h_length); 66858778Seric break; 66958778Seric #endif 67058778Seric 67158778Seric default: 67258755Seric bcopy(hp->h_addr_list[i++], 67358778Seric addr.sa.sa_data, 67452106Seric hp->h_length); 67558778Seric break; 67658778Seric } 67757736Seric continue; 67829430Sbloom } 67929430Sbloom 6806039Seric /* failure, decide if temporary or not */ 6816039Seric failure: 68259254Seric #ifdef XLA 68359254Seric xla_host_end(host); 68459254Seric #endif 68558542Seric if (transienterror(sav_errno)) 68658542Seric return EX_TEMPFAIL; 68758542Seric else 68858542Seric { 68958542Seric extern char *errstring(); 69011147Seric 69158542Seric message("%s", errstring(sav_errno)); 69258542Seric return (EX_UNAVAILABLE); 6936039Seric } 6946039Seric } 6956039Seric 6966039Seric /* connection ok, put it into canonical form */ 69753739Seric mci->mci_out = fdopen(s, "w"); 69853739Seric mci->mci_in = fdopen(dup(s), "r"); 6996039Seric 70010098Seric return (EX_OK); 7016039Seric } 70210758Seric /* 70310758Seric ** MYHOSTNAME -- return the name of this host. 70410758Seric ** 70510758Seric ** Parameters: 70610758Seric ** hostbuf -- a place to return the name of this host. 70712313Seric ** size -- the size of hostbuf. 70810758Seric ** 70910758Seric ** Returns: 71010758Seric ** A list of aliases for this host. 71110758Seric ** 71210758Seric ** Side Effects: 71358110Seric ** Sets the MyIpAddrs buffer to a list of my IP addresses. 71410758Seric */ 7156039Seric 71658110Seric struct in_addr MyIpAddrs[MAXIPADDR + 1]; 71758110Seric 71810758Seric char ** 71912313Seric myhostname(hostbuf, size) 72010758Seric char hostbuf[]; 72112313Seric int size; 72210758Seric { 72358110Seric register struct hostent *hp; 72410758Seric extern struct hostent *gethostbyname(); 72510758Seric 72623120Seric if (gethostname(hostbuf, size) < 0) 72723120Seric { 72823120Seric (void) strcpy(hostbuf, "localhost"); 72923120Seric } 73011147Seric hp = gethostbyname(hostbuf); 73111147Seric if (hp != NULL) 73216877Seric { 73358110Seric (void) strncpy(hostbuf, hp->h_name, size - 1); 73458110Seric hostbuf[size - 1] = '\0'; 73558110Seric 73658110Seric if (hp->h_addrtype == AF_INET && hp->h_length == 4) 73758110Seric { 73858110Seric register int i; 73958110Seric 74058110Seric for (i = 0; i < MAXIPADDR; i++) 74158110Seric { 74258110Seric if (hp->h_addr_list[i] == NULL) 74358110Seric break; 74458110Seric MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 74558110Seric } 74658110Seric MyIpAddrs[i].s_addr = 0; 74758110Seric } 74858110Seric 74911147Seric return (hp->h_aliases); 75016877Seric } 75110758Seric else 75210758Seric return (NULL); 75310758Seric } 75451315Seric /* 75558951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 75658308Seric ** 75758951Seric ** Uses RFC1413 protocol to try to get info from the other end. 75858951Seric ** 75958308Seric ** Parameters: 76058308Seric ** fd -- the descriptor 76158308Seric ** 76258308Seric ** Returns: 76358951Seric ** The user@host information associated with this descriptor. 76458308Seric ** 76558308Seric ** Side Effects: 76658951Seric ** Sets RealHostName to the name of the host at the other end. 76758308Seric */ 76858308Seric 76958951Seric #ifdef IDENTPROTO 77058951Seric 77158951Seric static jmp_buf CtxAuthTimeout; 77258951Seric 77358951Seric static 77458951Seric authtimeout() 77558951Seric { 77658951Seric longjmp(CtxAuthTimeout, 1); 77758951Seric } 77858951Seric 77958951Seric #endif 78058951Seric 78158308Seric char * 78258951Seric getauthinfo(fd) 78358308Seric int fd; 78458308Seric { 78558951Seric SOCKADDR fa; 78658951Seric int falen; 78759104Seric register char *p; 78858951Seric #ifdef IDENTPROTO 78958951Seric SOCKADDR la; 79058951Seric int lalen; 79158951Seric register struct servent *sp; 79258951Seric int s; 79358951Seric int i; 79458951Seric EVENT *ev; 79558951Seric #endif 79658951Seric static char hbuf[MAXNAME * 2 + 2]; 79758951Seric extern char *hostnamebyanyaddr(); 79858951Seric extern char RealUserName[]; /* main.c */ 79958308Seric 80058951Seric falen = sizeof fa; 80158951Seric if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0) 80258951Seric { 80358951Seric RealHostName = "localhost"; 80458951Seric (void) sprintf(hbuf, "%s@localhost", RealUserName); 80558957Seric if (tTd(9, 1)) 80658951Seric printf("getauthinfo: %s\n", hbuf); 80758951Seric return hbuf; 80858951Seric } 80958951Seric 81058951Seric RealHostName = newstr(hostnamebyanyaddr(&fa)); 81158951Seric RealHostAddr = fa; 81258951Seric 81358951Seric #ifdef IDENTPROTO 81458951Seric lalen = sizeof la; 81558951Seric if (fa.sa.sa_family != AF_INET || 81658951Seric getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 81758951Seric la.sa.sa_family != AF_INET) 81858951Seric { 81958951Seric /* no ident info */ 82058951Seric goto noident; 82158951Seric } 82258951Seric 82358951Seric /* create ident query */ 82458951Seric (void) sprintf(hbuf, "%d,%d\r\n", fa.sin.sin_port, la.sin.sin_port); 82558951Seric 82658951Seric /* create local address */ 82758951Seric bzero(&la, sizeof la); 82858951Seric 82958951Seric /* create foreign address */ 83058951Seric sp = getservbyname("auth", "tcp"); 83158951Seric if (sp != NULL) 83258951Seric fa.sin.sin_port = sp->s_port; 83358308Seric else 83459097Seric fa.sin.sin_port = htons(113); 83558951Seric 83658951Seric s = -1; 83758951Seric if (setjmp(CtxAuthTimeout) != 0) 83858951Seric { 83958951Seric if (s >= 0) 84058951Seric (void) close(s); 84158951Seric goto noident; 84258951Seric } 84358951Seric 84458951Seric /* put a timeout around the whole thing */ 84558951Seric ev = setevent((time_t) 30, authtimeout, 0); 84658951Seric 84758951Seric /* connect to foreign IDENT server */ 84858951Seric s = socket(AF_INET, SOCK_STREAM, 0); 84958951Seric if (s < 0) 85058951Seric { 85158951Seric clrevent(ev); 85258951Seric goto noident; 85358951Seric } 85458951Seric if (connect(s, &fa.sa, sizeof fa.sin) < 0) 85558951Seric { 85658951Seric closeident: 85758951Seric (void) close(s); 85858951Seric clrevent(ev); 85958951Seric goto noident; 86058951Seric } 86158951Seric 86258957Seric if (tTd(9, 10)) 86358951Seric printf("getauthinfo: sent %s", hbuf); 86458951Seric 86558951Seric /* send query */ 86658951Seric if (write(s, hbuf, strlen(hbuf)) < 0) 86758951Seric goto closeident; 86858951Seric 86958951Seric /* get result */ 87058951Seric i = read(s, hbuf, sizeof hbuf); 87158951Seric (void) close(s); 87258951Seric clrevent(ev); 87358951Seric if (i <= 0) 87458951Seric goto noident; 87558951Seric if (hbuf[--i] == '\n' && hbuf[--i] == '\r') 87658951Seric i--; 87758951Seric hbuf[++i] = '\0'; 87858951Seric 87958957Seric if (tTd(9, 3)) 88058951Seric printf("getauthinfo: got %s\n", hbuf); 88158951Seric 88258951Seric /* parse result */ 88358951Seric p = strchr(hbuf, ':'); 88458951Seric if (p == NULL) 88558951Seric { 88658951Seric /* malformed response */ 88758951Seric goto noident; 88858951Seric } 88958951Seric while (isascii(*++p) && isspace(*p)) 89058951Seric continue; 89158951Seric if (strncasecmp(p, "userid", 6) != 0) 89258951Seric { 89358951Seric /* presumably an error string */ 89458951Seric goto noident; 89558951Seric } 89658951Seric p += 6; 89758951Seric while (isascii(*p) && isspace(*p)) 89858951Seric p++; 89958951Seric if (*p++ != ':') 90058951Seric { 90158951Seric /* either useridxx or malformed response */ 90258951Seric goto noident; 90358951Seric } 90458951Seric 90558951Seric /* p now points to the OSTYPE field */ 90658951Seric p = strchr(p, ':'); 90758951Seric if (p == NULL) 90858951Seric { 90958951Seric /* malformed response */ 91058951Seric goto noident; 91158951Seric } 91258951Seric 91358957Seric /* 1413 says don't do this -- but it's broken otherwise */ 91458957Seric while (isascii(*++p) && isspace(*p)) 91558957Seric continue; 91658957Seric 91758951Seric /* p now points to the authenticated name */ 91858951Seric (void) sprintf(hbuf, "%s@%s", p, RealHostName); 91958957Seric goto finish; 92058957Seric 92158957Seric #endif /* IDENTPROTO */ 92258957Seric 92358957Seric noident: 92458957Seric (void) strcpy(hbuf, RealHostName); 92558957Seric 92658957Seric finish: 92758951Seric if (RealHostName[0] != '[') 92858951Seric { 92958951Seric p = &hbuf[strlen(hbuf)]; 93058951Seric (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); 93158951Seric } 93258957Seric if (tTd(9, 1)) 93358951Seric printf("getauthinfo: %s\n", hbuf); 93458308Seric return hbuf; 93558308Seric } 93658308Seric /* 93753751Seric ** MAPHOSTNAME -- turn a hostname into canonical form 93853751Seric ** 93953751Seric ** Parameters: 94056823Seric ** map -- a pointer to this map (unused). 94153751Seric ** hbuf -- a buffer containing a hostname. 94253751Seric ** hbsize -- the size of hbuf. 94355019Seric ** avp -- unused -- for compatibility with other mapping 94455019Seric ** functions. 94559084Seric ** statp -- an exit status (out parameter) -- set to 94659084Seric ** EX_TEMPFAIL if the name server is unavailable. 94753751Seric ** 94853751Seric ** Returns: 94953751Seric ** The mapping, if found. 95053751Seric ** NULL if no mapping found. 95153751Seric ** 95253751Seric ** Side Effects: 95353751Seric ** Looks up the host specified in hbuf. If it is not 95453751Seric ** the canonical name for that host, return the canonical 95553751Seric ** name. 95653751Seric */ 95751315Seric 95853751Seric char * 95959084Seric maphostname(map, hbuf, hbsize, avp, statp) 96056823Seric MAP *map; 96116911Seric char *hbuf; 96216911Seric int hbsize; 96353751Seric char **avp; 96459084Seric int *statp; 96516911Seric { 96616911Seric register struct hostent *hp; 96733932Sbostic u_long in_addr; 96856823Seric char *cp; 96958110Seric int i; 97059671Seric register STAB *s; 97159671Seric extern struct hostent *gethostbyaddr(); 97259671Seric extern int h_errno; 97316911Seric 97456836Seric /* allow room for null */ 97556823Seric hbsize--; 97653751Seric 97725574Smiriam /* 97859671Seric ** See if we have already looked up this name. If so, just 97959671Seric ** return it. 98059671Seric */ 98153751Seric 98259671Seric s = stab(hbuf, ST_NAMECANON, ST_ENTER); 98359671Seric if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 98459671Seric { 98559671Seric errno = s->s_namecanon.nc_errno; 98659671Seric h_errno = s->s_namecanon.nc_herrno; 98759671Seric *statp = s->s_namecanon.nc_stat; 98859671Seric return s->s_namecanon.nc_cname; 98959671Seric } 99059671Seric 99159671Seric /* 99259671Seric ** If first character is a bracket, then it is an address 99359671Seric ** lookup. Address is copied into a temporary buffer to 99459671Seric ** strip the brackets and to preserve hbuf if address is 99559671Seric ** unknown. 99659671Seric */ 99759671Seric 99851315Seric if (*hbuf != '[') 99953751Seric { 100055019Seric extern bool getcanonname(); 100155019Seric 100258798Seric if (tTd(9, 1)) 100358798Seric printf("maphostname(%s, %d) => ", hbuf, hbsize); 100459671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 100558674Seric if (getcanonname(hbuf, hbsize)) 100658796Seric { 100758796Seric if (tTd(9, 1)) 100858796Seric printf("%s\n", hbuf); 100959671Seric s->s_namecanon.nc_cname = newstr(hbuf); 101053751Seric return hbuf; 101158796Seric } 101253751Seric else 101358796Seric { 101459084Seric register struct hostent *hp; 101559084Seric 101658796Seric if (tTd(9, 1)) 101759084Seric printf("FAIL (%d)\n", h_errno); 101859671Seric s->s_namecanon.nc_errno = errno; 101959671Seric s->s_namecanon.nc_herrno = h_errno; 102059084Seric switch (h_errno) 102159084Seric { 102259084Seric case TRY_AGAIN: 102359596Seric if (UseNameServer) 1024*59734Seric { 1025*59734Seric char *msg = "Recipient domain nameserver timed out"; 1026*59734Seric 1027*59734Seric message(msg); 1028*59734Seric if (CurEnv->e_message == NULL) 1029*59734Seric CurEnv->e_message = msg; 1030*59734Seric } 103159084Seric *statp = EX_TEMPFAIL; 103259084Seric break; 103359084Seric 103459084Seric case HOST_NOT_FOUND: 103559084Seric *statp = EX_NOHOST; 103659084Seric break; 103759084Seric 103859084Seric case NO_RECOVERY: 103959084Seric *statp = EX_SOFTWARE; 104059084Seric break; 104159084Seric 104259084Seric default: 104359084Seric *statp = EX_UNAVAILABLE; 104459084Seric break; 104559084Seric } 104659671Seric s->s_namecanon.nc_stat = *statp; 104759084Seric if (*statp != EX_TEMPFAIL || UseNameServer) 104859084Seric return NULL; 104959084Seric 105059084Seric /* 105159084Seric ** Try to look it up in /etc/hosts 105259084Seric */ 105359084Seric 105459084Seric hp = gethostbyname(hbuf); 105559084Seric if (hp == NULL) 105659084Seric { 105759084Seric /* no dice there either */ 105859671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 105959084Seric return NULL; 106059084Seric } 106159084Seric 106259671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 106359671Seric s->s_namecanon.nc_cname = newstr(hp->h_name); 106459084Seric return hp->h_name; 106558796Seric } 106653751Seric } 106756823Seric if ((cp = strchr(hbuf, ']')) == NULL) 106853751Seric return (NULL); 106940994Sbostic *cp = '\0'; 107056823Seric in_addr = inet_addr(&hbuf[1]); 107158110Seric 107258110Seric /* check to see if this is one of our addresses */ 107358110Seric for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 107458110Seric { 107558110Seric if (MyIpAddrs[i].s_addr == in_addr) 107658110Seric { 107758110Seric strncpy(hbuf, MyHostName, hbsize); 107858110Seric hbuf[hbsize] = '\0'; 107958110Seric return hbuf; 108058110Seric } 108158110Seric } 108258110Seric 108358110Seric /* nope -- ask the name server */ 108433932Sbostic hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 108559671Seric s->s_namecanon.nc_errno = errno; 108659671Seric s->s_namecanon.nc_herrno = h_errno; 108759671Seric s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 108833932Sbostic if (hp == NULL) 108959671Seric { 109059671Seric s->s_namecanon.nc_stat = *statp = EX_NOHOST; 109153751Seric return (NULL); 109259671Seric } 109353751Seric 109458110Seric /* found a match -- copy out */ 109559671Seric s->s_namecanon.nc_cname = newstr(hp->h_name); 109656823Seric if (strlen(hp->h_name) > hbsize) 109756823Seric hp->h_name[hbsize] = '\0'; 109853751Seric (void) strcpy(hbuf, hp->h_name); 109959671Seric s->s_namecanon.nc_stat = *statp = EX_OK; 110053751Seric return hbuf; 110133932Sbostic } 110258755Seric /* 110358755Seric ** ANYNET_NTOA -- convert a network address to printable form. 110458755Seric ** 110558755Seric ** Parameters: 110658755Seric ** sap -- a pointer to a sockaddr structure. 110758755Seric ** 110858755Seric ** Returns: 110958755Seric ** A printable version of that sockaddr. 111058755Seric */ 111116911Seric 111258755Seric char * 111358755Seric anynet_ntoa(sap) 111458755Seric register SOCKADDR *sap; 111558755Seric { 111658755Seric register char *bp; 111758755Seric register char *ap; 111858755Seric int l; 111958755Seric static char buf[80]; 112058755Seric 112158798Seric /* check for null/zero family */ 112258798Seric if (sap == NULL) 112358798Seric return "NULLADDR"; 112458798Seric if (sap->sa.sa_family == 0) 112558798Seric return "0"; 112658798Seric 112758778Seric #ifdef NETINET 112858778Seric if (sap->sa.sa_family == AF_INET) 112958755Seric { 113058755Seric extern char *inet_ntoa(); 113158755Seric 113258755Seric return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 113358755Seric } 113458778Seric #endif 113558755Seric 113658755Seric /* unknown family -- just dump bytes */ 113758778Seric (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 113858755Seric bp = &buf[strlen(buf)]; 113958778Seric ap = sap->sa.sa_data; 114058778Seric for (l = sizeof sap->sa.sa_data; --l >= 0; ) 114158755Seric { 114258755Seric (void) sprintf(bp, "%02x:", *ap++ & 0377); 114358755Seric bp += 3; 114458755Seric } 114558755Seric *--bp = '\0'; 114658755Seric return buf; 114758755Seric } 114858951Seric /* 114958951Seric ** HOSTNAMEBYANYADDR -- return name of host based on address 115058951Seric ** 115158951Seric ** Parameters: 115258951Seric ** sap -- SOCKADDR pointer 115358951Seric ** 115458951Seric ** Returns: 115558951Seric ** text representation of host name. 115658951Seric ** 115758951Seric ** Side Effects: 115858951Seric ** none. 115958951Seric */ 116058755Seric 116158951Seric char * 116258951Seric hostnamebyanyaddr(sap) 116358951Seric register SOCKADDR *sap; 116458951Seric { 116558951Seric register struct hostent *hp; 116658951Seric 116759042Seric #ifdef NAMED_BIND 116859042Seric int saveretry; 116959042Seric 117059042Seric /* shorten name server timeout to avoid higher level timeouts */ 117159042Seric saveretry = _res.retry; 117259042Seric _res.retry = 3; 117359042Seric #endif /* NAMED_BIND */ 117459042Seric 117558951Seric switch (sap->sa.sa_family) 117658951Seric { 117758951Seric #ifdef NETINET 117858951Seric case AF_INET: 117958951Seric hp = gethostbyaddr((char *) &sap->sin.sin_addr, 118058951Seric sizeof sap->sin.sin_addr, 118158951Seric AF_INET); 118258951Seric break; 118358951Seric #endif 118458951Seric 118558951Seric #ifdef NETISO 118658951Seric case AF_ISO: 118758951Seric hp = gethostbyaddr((char *) &sap->siso.siso_addr, 118858951Seric sizeof sap->siso.siso_addr, 118958951Seric AF_ISO); 119058951Seric break; 119158951Seric #endif 119258951Seric 119358951Seric default: 119458951Seric hp = gethostbyaddr(sap->sa.sa_data, 119558951Seric sizeof sap->sa.sa_data, 119658951Seric sap->sa.sa_family); 119758951Seric break; 119858951Seric } 119958951Seric 120059042Seric #ifdef NAMED_BIND 120159042Seric _res.retry = saveretry; 120259042Seric #endif /* NAMED_BIND */ 120359042Seric 120458951Seric if (hp != NULL) 120558951Seric return hp->h_name; 120658951Seric else 120758951Seric { 120858951Seric /* produce a dotted quad */ 120958951Seric static char buf[512]; 121058951Seric 121158951Seric (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); 121258951Seric return buf; 121358951Seric } 121458951Seric } 121558951Seric 121656795Seric # else /* DAEMON */ 121716911Seric /* code for systems without sophisticated networking */ 121810758Seric 121910758Seric /* 122010758Seric ** MYHOSTNAME -- stub version for case of no daemon code. 122111297Seric ** 122211297Seric ** Can't convert to upper case here because might be a UUCP name. 122312313Seric ** 122412313Seric ** Mark, you can change this to be anything you want...... 122510758Seric */ 122610758Seric 122710758Seric char ** 122812313Seric myhostname(hostbuf, size) 122910758Seric char hostbuf[]; 123012313Seric int size; 123110758Seric { 123210758Seric register FILE *f; 123310758Seric 123410758Seric hostbuf[0] = '\0'; 123510758Seric f = fopen("/usr/include/whoami", "r"); 123610758Seric if (f != NULL) 123710758Seric { 123812313Seric (void) fgets(hostbuf, size, f); 123910758Seric fixcrlf(hostbuf, TRUE); 124010758Seric (void) fclose(f); 124110758Seric } 124210758Seric return (NULL); 124310758Seric } 124416911Seric /* 124558951Seric ** GETAUTHINFO -- get the real host name asociated with a file descriptor 124658308Seric ** 124758308Seric ** Parameters: 124858308Seric ** fd -- the descriptor 124958308Seric ** 125058308Seric ** Returns: 125158308Seric ** The host name associated with this descriptor, if it can 125258308Seric ** be determined. 125358308Seric ** NULL otherwise. 125458308Seric ** 125558308Seric ** Side Effects: 125658308Seric ** none 125758308Seric */ 125858308Seric 125958308Seric char * 126058951Seric getauthinfo(fd) 126158308Seric int fd; 126258308Seric { 126358308Seric return NULL; 126458308Seric } 126558308Seric /* 126616911Seric ** MAPHOSTNAME -- turn a hostname into canonical form 126716911Seric ** 126816911Seric ** Parameters: 126956823Seric ** map -- a pointer to the database map. 127016911Seric ** hbuf -- a buffer containing a hostname. 127159084Seric ** hbsize -- size of hbuf. 127253751Seric ** avp -- a pointer to a (cf file defined) argument vector. 127359084Seric ** statp -- an exit status (out parameter). 127416911Seric ** 127516911Seric ** Returns: 127653751Seric ** mapped host name 127751315Seric ** FALSE otherwise. 127816911Seric ** 127916911Seric ** Side Effects: 128016911Seric ** Looks up the host specified in hbuf. If it is not 128116911Seric ** the canonical name for that host, replace it with 128216911Seric ** the canonical name. If the name is unknown, or it 128316911Seric ** is already the canonical name, leave it unchanged. 128416911Seric */ 128510758Seric 128616911Seric /*ARGSUSED*/ 128753751Seric char * 128859084Seric maphostname(map, hbuf, hbsize, avp, statp) 128956823Seric MAP *map; 129016911Seric char *hbuf; 129116911Seric int hbsize; 129253751Seric char **avp; 129359084Seric char *statp; 129416911Seric { 129559084Seric register struct hostent *hp; 129659084Seric 129759084Seric hp = gethostbyname(hbuf); 129859084Seric if (hp != NULL) 129959084Seric return hp->h_name; 130059084Seric *statp = EX_NOHOST; 130153751Seric return NULL; 130216911Seric } 130316911Seric 130456795Seric #endif /* DAEMON */ 1305