1939f5b94Sdist /* 20942ea6aSbostic * Copyright (c) 1983 Eric P. Allman 3da1c6175Sbostic * Copyright (c) 1988 Regents of the University of California. 4da1c6175Sbostic * All rights reserved. 5da1c6175Sbostic * 63bc94712Sbostic * %sccs.include.redist.c% 7939f5b94Sdist */ 8939f5b94Sdist 97aa493c5Seric #include <errno.h> 106c05f684Sbostic #include "sendmail.h" 117fa39d90Seric 12af5e902cSeric #ifndef lint 13da1c6175Sbostic #ifdef DAEMON 14*05b57da8Seric static char sccsid[] = "@(#)daemon.c 5.52 (Berkeley) 11/15/92 (with daemon mode)"; 15d0a9e852Seric #else 16*05b57da8Seric static char sccsid[] = "@(#)daemon.c 5.52 (Berkeley) 11/15/92 (without daemon mode)"; 17da1c6175Sbostic #endif 18da1c6175Sbostic #endif /* not lint */ 19da1c6175Sbostic 20da1c6175Sbostic #ifdef DAEMON 21d0a9e852Seric 221c71e510Seric # include <netdb.h> 2352308a50Seric # include <sys/signal.h> 241e1663f7Swnj # include <sys/wait.h> 25af5e902cSeric # include <sys/time.h> 26af5e902cSeric # include <sys/resource.h> 27d0a9e852Seric 287fa39d90Seric /* 297fa39d90Seric ** DAEMON.C -- routines to use when running as a daemon. 3047b12ae1Seric ** 3147b12ae1Seric ** This entire file is highly dependent on the 4.2 BSD 3247b12ae1Seric ** interprocess communication primitives. No attempt has 3347b12ae1Seric ** been made to make this file portable to Version 7, 3447b12ae1Seric ** Version 6, MPX files, etc. If you should try such a 3547b12ae1Seric ** thing yourself, I recommend chucking the entire file 3647b12ae1Seric ** and starting from scratch. Basic semantics are: 3747b12ae1Seric ** 3847b12ae1Seric ** getrequests() 3947b12ae1Seric ** Opens a port and initiates a connection. 4047b12ae1Seric ** Returns in a child. Must set InChannel and 4147b12ae1Seric ** OutChannel appropriately. 42b7d7afcbSeric ** clrdaemon() 43b7d7afcbSeric ** Close any open files associated with getting 44b7d7afcbSeric ** the connection; this is used when running the queue, 45b7d7afcbSeric ** etc., to avoid having extra file descriptors during 46b7d7afcbSeric ** the queue run and to avoid confusing the network 47b7d7afcbSeric ** code (if it cares). 48914346b1Seric ** makeconnection(host, port, outfile, infile, usesecureport) 4947b12ae1Seric ** Make a connection to the named host on the given 5047b12ae1Seric ** port. Set *outfile and *infile to the files 5147b12ae1Seric ** appropriate for communication. Returns zero on 5247b12ae1Seric ** success, else an exit status describing the 5347b12ae1Seric ** error. 54*05b57da8Seric ** maphostname(map, hbuf, hbufsiz, avp) 55*05b57da8Seric ** Convert the entry in hbuf into a canonical form. 567fa39d90Seric */ 577fa39d90Seric /* 587fa39d90Seric ** GETREQUESTS -- open mail IPC port and get requests. 597fa39d90Seric ** 607fa39d90Seric ** Parameters: 617fa39d90Seric ** none. 627fa39d90Seric ** 637fa39d90Seric ** Returns: 647fa39d90Seric ** none. 657fa39d90Seric ** 667fa39d90Seric ** Side Effects: 677fa39d90Seric ** Waits until some interesting activity occurs. When 687fa39d90Seric ** it does, a child is created to process it, and the 697fa39d90Seric ** parent waits for completion. Return from this 70147303b1Seric ** routine is always in the child. The file pointers 71147303b1Seric ** "InChannel" and "OutChannel" should be set to point 72147303b1Seric ** to the communication channel. 737fa39d90Seric */ 747fa39d90Seric 75b7d7afcbSeric int DaemonSocket = -1; /* fd describing socket */ 761c71e510Seric 777fa39d90Seric getrequests() 787fa39d90Seric { 791c71e510Seric int t; 801c71e510Seric register struct servent *sp; 817868dfc2Seric int on = 1; 8215d084d5Seric bool refusingconnections = TRUE; 83914346b1Seric struct sockaddr_in srvraddr; 849b100374Sbostic extern void reapchild(); 85eb889047Seric 86a8268164Seric /* 871c71e510Seric ** Set up the address for the mailer. 88eb889047Seric */ 89eb889047Seric 901c71e510Seric sp = getservbyname("smtp", "tcp"); 911c71e510Seric if (sp == NULL) 92d0a9e852Seric { 931c71e510Seric syserr("server \"smtp\" unknown"); 94a1961f2aSeric goto severe; 951c71e510Seric } 96914346b1Seric srvraddr.sin_family = AF_INET; 97914346b1Seric srvraddr.sin_addr.s_addr = INADDR_ANY; 98914346b1Seric srvraddr.sin_port = sp->s_port; 991c71e510Seric 1001c71e510Seric /* 1011c71e510Seric ** Try to actually open the connection. 1021c71e510Seric */ 1031c71e510Seric 1041c71e510Seric if (tTd(15, 1)) 105914346b1Seric printf("getrequests: port 0x%x\n", srvraddr.sin_port); 1061c71e510Seric 1071c71e510Seric /* get a socket for the SMTP connection */ 108af5e902cSeric DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 109b7d7afcbSeric if (DaemonSocket < 0) 1101c71e510Seric { 1111c71e510Seric /* probably another daemon already */ 1121c71e510Seric syserr("getrequests: can't create socket"); 1131c71e510Seric severe: 114b0ba8827Seric # ifdef LOG 115b0ba8827Seric if (LogLevel > 0) 116d2aa4720Seric syslog(LOG_ALERT, "cannot get connection"); 1176c2c3107Seric # endif /* LOG */ 11847b12ae1Seric finis(); 119d0a9e852Seric } 1201b6e4a15Seric 1211b6e4a15Seric /* turn on network debugging? */ 122a2ef5fa4Seric if (tTd(15, 101)) 12352308a50Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 1241b6e4a15Seric 1257868dfc2Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 1267868dfc2Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 1277868dfc2Seric 128914346b1Seric if (bind(DaemonSocket, (struct sockaddr *)&srvraddr, sizeof srvraddr) < 0) 1291c71e510Seric { 1301c71e510Seric syserr("getrequests: cannot bind"); 131b7d7afcbSeric (void) close(DaemonSocket); 1321c71e510Seric goto severe; 1331c71e510Seric } 1341c71e510Seric 1351cd247eeSeric (void) signal(SIGCHLD, reapchild); 13652308a50Seric 1371c71e510Seric if (tTd(15, 1)) 138b7d7afcbSeric printf("getrequests: %d\n", DaemonSocket); 1391c71e510Seric 1401c71e510Seric for (;;) 1411c71e510Seric { 1423a099713Seric register int pid; 143a44d5a5eSeric auto int lotherend; 14415d084d5Seric extern bool refuseconnections(); 1453a099713Seric 1463a099713Seric /* see if we are rejecting connections */ 14715d084d5Seric CurrentLA = getla(); 14815d084d5Seric if (refuseconnections()) 1496775ec03Sbostic { 15015d084d5Seric if (!refusingconnections) 15115d084d5Seric { 15215d084d5Seric /* don't queue so peer will fail quickly */ 15315d084d5Seric (void) listen(DaemonSocket, 0); 15415d084d5Seric refusingconnections = TRUE; 15515d084d5Seric } 15615d084d5Seric setproctitle("rejecting connections: load average: %.2f", 15715d084d5Seric (double)CurrentLA); 1583a099713Seric sleep(5); 15915d084d5Seric continue; 16015d084d5Seric } 16115d084d5Seric 16215d084d5Seric if (refusingconnections) 16315d084d5Seric { 16415d084d5Seric /* start listening again */ 16515d084d5Seric if (listen(DaemonSocket, 10) < 0) 16615d084d5Seric { 16715d084d5Seric syserr("getrequests: cannot listen"); 16815d084d5Seric (void) close(DaemonSocket); 16915d084d5Seric goto severe; 17015d084d5Seric } 17115d084d5Seric setproctitle("accepting connections"); 17215d084d5Seric refusingconnections = FALSE; 1736775ec03Sbostic } 174a44d5a5eSeric 1751c71e510Seric /* wait for a connection */ 1761c71e510Seric do 1771c71e510Seric { 1781c71e510Seric errno = 0; 1799f9a15b6Skarels lotherend = sizeof RealHostAddr; 1809b100374Sbostic t = accept(DaemonSocket, 1819b100374Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 1821c71e510Seric } while (t < 0 && errno == EINTR); 1831c71e510Seric if (t < 0) 1841c71e510Seric { 1851c71e510Seric syserr("getrequests: accept"); 1861c71e510Seric sleep(5); 1871c71e510Seric continue; 1881c71e510Seric } 189d0a9e852Seric 190d0a9e852Seric /* 191d0a9e852Seric ** Create a subprocess to process the mail. 192d0a9e852Seric */ 193d0a9e852Seric 19461e4310fSeric if (tTd(15, 2)) 1951c71e510Seric printf("getrequests: forking (fd = %d)\n", t); 196eb889047Seric 197a8268164Seric pid = fork(); 198a8268164Seric if (pid < 0) 199a8268164Seric { 200a8268164Seric syserr("daemon: cannot fork"); 201a8268164Seric sleep(10); 2021c71e510Seric (void) close(t); 203a8268164Seric continue; 204a8268164Seric } 205a8268164Seric 206a8268164Seric if (pid == 0) 207a8268164Seric { 208a44d5a5eSeric extern struct hostent *gethostbyaddr(); 209a44d5a5eSeric register struct hostent *hp; 210a44d5a5eSeric char buf[MAXNAME]; 211a44d5a5eSeric 212a8268164Seric /* 213a8268164Seric ** CHILD -- return to caller. 214a44d5a5eSeric ** Collect verified idea of sending host. 215a8268164Seric ** Verify calling user id if possible here. 216a8268164Seric */ 217a8268164Seric 2181cd247eeSeric (void) signal(SIGCHLD, SIG_DFL); 219779ac194Seric 220a44d5a5eSeric /* determine host name */ 2219f9a15b6Skarels hp = gethostbyaddr((char *) &RealHostAddr.sin_addr, sizeof RealHostAddr.sin_addr, AF_INET); 222a44d5a5eSeric if (hp != NULL) 223fefbbe29Seric (void) strcpy(buf, hp->h_name); 224a44d5a5eSeric else 22529dcf4baSeric { 22629dcf4baSeric extern char *inet_ntoa(); 22729dcf4baSeric 22829dcf4baSeric /* produce a dotted quad */ 22929dcf4baSeric (void) sprintf(buf, "[%s]", 2309f9a15b6Skarels inet_ntoa(RealHostAddr.sin_addr)); 23129dcf4baSeric } 23229dcf4baSeric 2332a6bc25bSeric #ifdef LOG 2342a6bc25bSeric if (LogLevel > 9) 2352a6bc25bSeric { 2362a6bc25bSeric /* log connection information */ 2372a6bc25bSeric syslog(LOG_INFO, "connect from %s (%s)", 2382a6bc25bSeric buf, inet_ntoa(RealHostAddr.sin_addr)); 2392a6bc25bSeric } 2402a6bc25bSeric #endif 2412a6bc25bSeric 24229dcf4baSeric /* should we check for illegal connection here? XXX */ 24329dcf4baSeric 244a44d5a5eSeric RealHostName = newstr(buf); 245a44d5a5eSeric 246b7d7afcbSeric (void) close(DaemonSocket); 2471c71e510Seric InChannel = fdopen(t, "r"); 2481d5bd586Seric OutChannel = fdopen(dup(t), "w"); 24961e4310fSeric if (tTd(15, 2)) 250d0a9e852Seric printf("getreq: returning\n"); 251252c8a22Seric # ifdef LOG 252252c8a22Seric if (LogLevel > 11) 253252c8a22Seric syslog(LOG_DEBUG, "connected, pid=%d", getpid()); 2546c2c3107Seric # endif /* LOG */ 255a8268164Seric return; 256a8268164Seric } 257a8268164Seric 2583c154354Seric /* close the port so that others will hang (for a while) */ 2593c154354Seric (void) close(t); 2608e3e4b17Seric } 2613c154354Seric /*NOTREACHED*/ 2623c154354Seric } 2638e3e4b17Seric /* 264b7d7afcbSeric ** CLRDAEMON -- reset the daemon connection 265b7d7afcbSeric ** 266b7d7afcbSeric ** Parameters: 267b7d7afcbSeric ** none. 268b7d7afcbSeric ** 269b7d7afcbSeric ** Returns: 270b7d7afcbSeric ** none. 271b7d7afcbSeric ** 272b7d7afcbSeric ** Side Effects: 273b7d7afcbSeric ** releases any resources used by the passive daemon. 274b7d7afcbSeric */ 275b7d7afcbSeric 276b7d7afcbSeric clrdaemon() 277b7d7afcbSeric { 278b7d7afcbSeric if (DaemonSocket >= 0) 279b7d7afcbSeric (void) close(DaemonSocket); 280b7d7afcbSeric DaemonSocket = -1; 281b7d7afcbSeric } 282b7d7afcbSeric /* 2837aa493c5Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 2847aa493c5Seric ** 2857aa493c5Seric ** Parameters: 2867aa493c5Seric ** host -- the name of the host. 28748ff0a9dSeric ** port -- the port number to connect to. 288655feedbSeric ** mci -- a pointer to the mail connection information 289655feedbSeric ** structure to be filled in. 290914346b1Seric ** usesecureport -- if set, use a low numbered (reserved) 291914346b1Seric ** port to provide some rudimentary authentication. 2927aa493c5Seric ** 2937aa493c5Seric ** Returns: 2947aa493c5Seric ** An exit code telling whether the connection could be 2957aa493c5Seric ** made and if not why not. 2967aa493c5Seric ** 2977aa493c5Seric ** Side Effects: 2987aa493c5Seric ** none. 2997aa493c5Seric */ 3007aa493c5Seric 301b31e7f2bSeric int 302655feedbSeric makeconnection(host, port, mci, usesecureport) 3037aa493c5Seric char *host; 304210215eaSeric u_short port; 305b31e7f2bSeric register MCI *mci; 306914346b1Seric bool usesecureport; 3077aa493c5Seric { 30804344589Sbloom register int i, s; 30904344589Sbloom register struct hostent *hp = (struct hostent *)NULL; 310914346b1Seric struct sockaddr_in addr; 3116286bb75Sbloom int sav_errno; 312914346b1Seric extern char *inet_ntoa(); 313134746fbSeric #ifdef NAMED_BIND 314134746fbSeric extern int h_errno; 315134746fbSeric #endif 3167aa493c5Seric 3177aa493c5Seric /* 3187aa493c5Seric ** Set up the address for the mailer. 31971096d12Seric ** Accept "[a.b.c.d]" syntax for host name. 3207aa493c5Seric */ 3217aa493c5Seric 322134746fbSeric #ifdef NAMED_BIND 323794bdbb9Smiriam h_errno = 0; 324134746fbSeric #endif 325794bdbb9Smiriam errno = 0; 326794bdbb9Smiriam 32771096d12Seric if (host[0] == '[') 32871096d12Seric { 329a44d5a5eSeric long hid; 3306c2c3107Seric register char *p = strchr(host, ']'); 33171096d12Seric 332a44d5a5eSeric if (p != NULL) 33371096d12Seric { 334a44d5a5eSeric *p = '\0'; 335a44d5a5eSeric hid = inet_addr(&host[1]); 336a44d5a5eSeric *p = ']'; 33771096d12Seric } 338a44d5a5eSeric if (p == NULL || hid == -1) 33971096d12Seric { 34071096d12Seric usrerr("Invalid numeric domain spec \"%s\"", host); 34171096d12Seric return (EX_NOHOST); 34271096d12Seric } 343914346b1Seric addr.sin_addr.s_addr = hid; 34471096d12Seric } 3451c71e510Seric else 3461c71e510Seric { 34704344589Sbloom hp = gethostbyname(host); 348794bdbb9Smiriam if (hp == NULL) 349794bdbb9Smiriam { 350134746fbSeric #ifdef NAMED_BIND 351794bdbb9Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 35252308a50Seric return (EX_TEMPFAIL); 35382e5d8ddSeric 354134746fbSeric /* if name server is specified, assume temp fail */ 355134746fbSeric if (errno == ECONNREFUSED && UseNameServer) 356134746fbSeric return (EX_TEMPFAIL); 357134746fbSeric #endif 358134746fbSeric 35982e5d8ddSeric /* 36082e5d8ddSeric ** XXX Should look for mail forwarder record here 36182e5d8ddSeric ** XXX if (h_errno == NO_ADDRESS). 36282e5d8ddSeric */ 36382e5d8ddSeric 3647aa493c5Seric return (EX_NOHOST); 365794bdbb9Smiriam } 366914346b1Seric bcopy(hp->h_addr, (char *) &addr.sin_addr, hp->h_length); 36704344589Sbloom i = 1; 3681c71e510Seric } 3691c71e510Seric 3701c71e510Seric /* 3711c71e510Seric ** Determine the port number. 3721c71e510Seric */ 3731c71e510Seric 374fd7c0790Seric if (port != 0) 375914346b1Seric addr.sin_port = htons(port); 376fd7c0790Seric else 3771c71e510Seric { 3781c71e510Seric register struct servent *sp = getservbyname("smtp", "tcp"); 3791c71e510Seric 3801c71e510Seric if (sp == NULL) 3811c71e510Seric { 3821c71e510Seric syserr("makeconnection: server \"smtp\" unknown"); 3831c71e510Seric return (EX_OSFILE); 3841c71e510Seric } 385914346b1Seric addr.sin_port = sp->s_port; 3861c71e510Seric } 3877aa493c5Seric 3887aa493c5Seric /* 3897aa493c5Seric ** Try to actually open the connection. 3907aa493c5Seric */ 3917aa493c5Seric 39204344589Sbloom again: 39361e4310fSeric if (tTd(16, 1)) 39404344589Sbloom printf("makeconnection (%s [%s])\n", host, 395914346b1Seric inet_ntoa(addr.sin_addr)); 3967aa493c5Seric 397914346b1Seric if (usesecureport) 398914346b1Seric { 399914346b1Seric int rport = IPPORT_RESERVED - 1; 400914346b1Seric 401914346b1Seric s = rresvport(&rport); 402914346b1Seric } 403914346b1Seric else 404914346b1Seric { 405af5e902cSeric s = socket(AF_INET, SOCK_STREAM, 0); 406914346b1Seric } 4077aa493c5Seric if (s < 0) 4087aa493c5Seric { 4096286bb75Sbloom sav_errno = errno; 410914346b1Seric syserr("makeconnection: no socket"); 4117aa493c5Seric goto failure; 4127aa493c5Seric } 4137aa493c5Seric 41461e4310fSeric if (tTd(16, 1)) 415b31e7f2bSeric printf("makeconnection: fd=%d\n", s); 4161b6e4a15Seric 4171b6e4a15Seric /* turn on network debugging? */ 418a2ef5fa4Seric if (tTd(16, 101)) 41952308a50Seric { 42052308a50Seric int on = 1; 42152308a50Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 42252308a50Seric } 42387d6e633Srick if (CurEnv->e_xfp != NULL) 424877a6142Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 4254bd6a662Seric errno = 0; /* for debugging */ 426914346b1Seric addr.sin_family = AF_INET; 427914346b1Seric if (connect(s, (struct sockaddr *) &addr, sizeof addr) < 0) 4287aa493c5Seric { 4296286bb75Sbloom sav_errno = errno; 4306286bb75Sbloom (void) close(s); 43104344589Sbloom if (hp && hp->h_addr_list[i]) 43204344589Sbloom { 433914346b1Seric bcopy(hp->h_addr_list[i++], (char *) &addr.sin_addr, 434914346b1Seric hp->h_length); 43504344589Sbloom goto again; 43604344589Sbloom } 43704344589Sbloom 4387aa493c5Seric /* failure, decide if temporary or not */ 4397aa493c5Seric failure: 4406286bb75Sbloom switch (sav_errno) 4417aa493c5Seric { 4427aa493c5Seric case EISCONN: 4437aa493c5Seric case ETIMEDOUT: 444292668b9Seric case EINPROGRESS: 445292668b9Seric case EALREADY: 446292668b9Seric case EADDRINUSE: 44736bd23a8Seric case EHOSTDOWN: 448292668b9Seric case ENETDOWN: 449292668b9Seric case ENETRESET: 450292668b9Seric case ENOBUFS: 451a1645df8Seric case ECONNREFUSED: 452efe49624Seric case ECONNRESET: 453cae8261aSeric case EHOSTUNREACH: 454dca8e1f7Seric case ENETUNREACH: 4559b2e2555Seric #ifdef ENOSR 4569b2e2555Seric case ENOSR: 4579b2e2555Seric #endif 4587aa493c5Seric /* there are others, I'm sure..... */ 4597aa493c5Seric return (EX_TEMPFAIL); 4607aa493c5Seric 461a44d5a5eSeric case EPERM: 462a44d5a5eSeric /* why is this happening? */ 463a44d5a5eSeric syserr("makeconnection: funny failure, addr=%lx, port=%x", 464914346b1Seric addr.sin_addr.s_addr, addr.sin_port); 4654bd6a662Seric return (EX_TEMPFAIL); 466a44d5a5eSeric 4677aa493c5Seric default: 46887d6e633Srick { 46987d6e633Srick extern char *errstring(); 47087d6e633Srick 471e8212f61Sbostic message(Arpa_Info, "%s", errstring(sav_errno)); 4727aa493c5Seric return (EX_UNAVAILABLE); 4737aa493c5Seric } 4747aa493c5Seric } 47587d6e633Srick } 4767aa493c5Seric 4777aa493c5Seric /* connection ok, put it into canonical form */ 478655feedbSeric mci->mci_out = fdopen(s, "w"); 479655feedbSeric mci->mci_in = fdopen(dup(s), "r"); 4807aa493c5Seric 481dca8e1f7Seric return (EX_OK); 4827aa493c5Seric } 483444eaf03Seric /* 484444eaf03Seric ** MYHOSTNAME -- return the name of this host. 485444eaf03Seric ** 486444eaf03Seric ** Parameters: 487444eaf03Seric ** hostbuf -- a place to return the name of this host. 488897f1869Seric ** size -- the size of hostbuf. 489444eaf03Seric ** 490444eaf03Seric ** Returns: 491444eaf03Seric ** A list of aliases for this host. 492444eaf03Seric ** 493444eaf03Seric ** Side Effects: 494444eaf03Seric ** none. 495444eaf03Seric */ 496444eaf03Seric 497444eaf03Seric char ** 498897f1869Seric myhostname(hostbuf, size) 499444eaf03Seric char hostbuf[]; 500897f1869Seric int size; 501444eaf03Seric { 502444eaf03Seric extern struct hostent *gethostbyname(); 503a44d5a5eSeric struct hostent *hp; 504444eaf03Seric 505af5e902cSeric if (gethostname(hostbuf, size) < 0) 506af5e902cSeric { 507af5e902cSeric (void) strcpy(hostbuf, "localhost"); 508af5e902cSeric } 509a44d5a5eSeric hp = gethostbyname(hostbuf); 510a44d5a5eSeric if (hp != NULL) 5117364df9fSeric { 512fefbbe29Seric (void) strcpy(hostbuf, hp->h_name); 513a44d5a5eSeric return (hp->h_aliases); 5147364df9fSeric } 515444eaf03Seric else 516444eaf03Seric return (NULL); 517444eaf03Seric } 518cb452edcSeric /* 51915d084d5Seric ** MAPHOSTNAME -- turn a hostname into canonical form 52015d084d5Seric ** 52115d084d5Seric ** Parameters: 522*05b57da8Seric ** map -- a pointer to this map (unused). 52315d084d5Seric ** hbuf -- a buffer containing a hostname. 52415d084d5Seric ** hbsize -- the size of hbuf. 525d798a1deSeric ** avp -- unused -- for compatibility with other mapping 526d798a1deSeric ** functions. 52715d084d5Seric ** 52815d084d5Seric ** Returns: 52915d084d5Seric ** The mapping, if found. 53015d084d5Seric ** NULL if no mapping found. 53115d084d5Seric ** 53215d084d5Seric ** Side Effects: 53315d084d5Seric ** Looks up the host specified in hbuf. If it is not 53415d084d5Seric ** the canonical name for that host, return the canonical 53515d084d5Seric ** name. 536f36ede03Sbostic */ 537cb452edcSeric 53815d084d5Seric char * 539*05b57da8Seric maphostname(map, hbuf, hbsize, avp) 540*05b57da8Seric MAP *map; 54199f7cf32Seric char *hbuf; 54299f7cf32Seric int hbsize; 54315d084d5Seric char **avp; 54499f7cf32Seric { 54599f7cf32Seric register struct hostent *hp; 5465f78836eSmiriam u_long in_addr; 547*05b57da8Seric char *cp; 548f36ede03Sbostic struct hostent *gethostbyaddr(); 5495f78836eSmiriam 550*05b57da8Seric /* allow room for null & trailing dot on correct match */ 551*05b57da8Seric hbsize--; 55215d084d5Seric if (ConfigLevel >= 2) 55315d084d5Seric hbsize--; 55415d084d5Seric 555f36ede03Sbostic /* 556f36ede03Sbostic * If first character is a bracket, then it is an address 557f36ede03Sbostic * lookup. Address is copied into a temporary buffer to 558f36ede03Sbostic * strip the brackets and to preserve hbuf if address is 559f36ede03Sbostic * unknown. 560f36ede03Sbostic */ 56115d084d5Seric 562cb452edcSeric if (*hbuf != '[') 56315d084d5Seric { 564d798a1deSeric extern bool getcanonname(); 565d798a1deSeric 56615d084d5Seric if (getcanonname(hbuf, hbsize)) 56715d084d5Seric { 56815d084d5Seric /* found a match -- add the trailing dot */ 56915d084d5Seric if (ConfigLevel >= 2) 570dafbc479Seric { 571dafbc479Seric int i = strlen(hbuf) - 1; 572dafbc479Seric 573dafbc479Seric if (hbuf[i] != '.') 574dafbc479Seric (void) strcpy(&hbuf[++i], "."); 575dafbc479Seric } 57615d084d5Seric return hbuf; 57715d084d5Seric } 57815d084d5Seric else 57915d084d5Seric return NULL; 58015d084d5Seric } 581*05b57da8Seric if ((cp = strchr(hbuf, ']')) == NULL) 58215d084d5Seric return (NULL); 58334e39927Sbostic *cp = '\0'; 584*05b57da8Seric in_addr = inet_addr(&hbuf[1]); 58531601fa7Seric hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 5865f78836eSmiriam if (hp == NULL) 58715d084d5Seric return (NULL); 58815d084d5Seric 58915d084d5Seric /* found a match -- copy and dot terminate */ 590*05b57da8Seric if (strlen(hp->h_name) > hbsize) 591*05b57da8Seric hp->h_name[hbsize] = '\0'; 592fefbbe29Seric (void) strcpy(hbuf, hp->h_name); 59315d084d5Seric if (ConfigLevel >= 2) 59415d084d5Seric (void) strcat(hbuf, "."); 59515d084d5Seric return hbuf; 59699f7cf32Seric } 597f36ede03Sbostic 5986c2c3107Seric # else /* DAEMON */ 59999f7cf32Seric /* code for systems without sophisticated networking */ 600444eaf03Seric 601444eaf03Seric /* 602444eaf03Seric ** MYHOSTNAME -- stub version for case of no daemon code. 60321e9914dSeric ** 60421e9914dSeric ** Can't convert to upper case here because might be a UUCP name. 605897f1869Seric ** 606897f1869Seric ** Mark, you can change this to be anything you want...... 607444eaf03Seric */ 608444eaf03Seric 609444eaf03Seric char ** 610897f1869Seric myhostname(hostbuf, size) 611444eaf03Seric char hostbuf[]; 612897f1869Seric int size; 613444eaf03Seric { 614444eaf03Seric register FILE *f; 615444eaf03Seric 616444eaf03Seric hostbuf[0] = '\0'; 617444eaf03Seric f = fopen("/usr/include/whoami", "r"); 618444eaf03Seric if (f != NULL) 619444eaf03Seric { 620897f1869Seric (void) fgets(hostbuf, size, f); 621444eaf03Seric fixcrlf(hostbuf, TRUE); 622444eaf03Seric (void) fclose(f); 623444eaf03Seric } 624444eaf03Seric return (NULL); 625444eaf03Seric } 62699f7cf32Seric /* 62799f7cf32Seric ** MAPHOSTNAME -- turn a hostname into canonical form 62899f7cf32Seric ** 62999f7cf32Seric ** Parameters: 630*05b57da8Seric ** map -- a pointer to the database map. 63199f7cf32Seric ** hbuf -- a buffer containing a hostname. 63215d084d5Seric ** avp -- a pointer to a (cf file defined) argument vector. 63399f7cf32Seric ** 63499f7cf32Seric ** Returns: 63515d084d5Seric ** mapped host name 636cb452edcSeric ** FALSE otherwise. 63799f7cf32Seric ** 63899f7cf32Seric ** Side Effects: 63999f7cf32Seric ** Looks up the host specified in hbuf. If it is not 64099f7cf32Seric ** the canonical name for that host, replace it with 64199f7cf32Seric ** the canonical name. If the name is unknown, or it 64299f7cf32Seric ** is already the canonical name, leave it unchanged. 64399f7cf32Seric */ 64499f7cf32Seric 64599f7cf32Seric /*ARGSUSED*/ 64615d084d5Seric char * 647*05b57da8Seric maphostname(map, hbuf, hbsize, avp) 648*05b57da8Seric MAP *map; 64999f7cf32Seric char *hbuf; 65099f7cf32Seric int hbsize; 65115d084d5Seric char **avp; 65299f7cf32Seric { 65315d084d5Seric return NULL; 65499f7cf32Seric } 65599f7cf32Seric 6566c2c3107Seric #endif /* DAEMON */ 657