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*6c2c3107Seric static char sccsid[] = "@(#)daemon.c 5.51 (Berkeley) 11/14/92 (with daemon mode)"; 15d0a9e852Seric #else 16*6c2c3107Seric static char sccsid[] = "@(#)daemon.c 5.51 (Berkeley) 11/14/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. 54d798a1deSeric ** maphostname(hbuf, hbufsize, avp) 558e8f00b5Seric ** Convert the entry in hbuf into a canonical form. It 568e8f00b5Seric ** may not be larger than hbufsize. 577fa39d90Seric */ 587fa39d90Seric /* 597fa39d90Seric ** GETREQUESTS -- open mail IPC port and get requests. 607fa39d90Seric ** 617fa39d90Seric ** Parameters: 627fa39d90Seric ** none. 637fa39d90Seric ** 647fa39d90Seric ** Returns: 657fa39d90Seric ** none. 667fa39d90Seric ** 677fa39d90Seric ** Side Effects: 687fa39d90Seric ** Waits until some interesting activity occurs. When 697fa39d90Seric ** it does, a child is created to process it, and the 707fa39d90Seric ** parent waits for completion. Return from this 71147303b1Seric ** routine is always in the child. The file pointers 72147303b1Seric ** "InChannel" and "OutChannel" should be set to point 73147303b1Seric ** to the communication channel. 747fa39d90Seric */ 757fa39d90Seric 76b7d7afcbSeric int DaemonSocket = -1; /* fd describing socket */ 771c71e510Seric 787fa39d90Seric getrequests() 797fa39d90Seric { 801c71e510Seric int t; 811c71e510Seric register struct servent *sp; 827868dfc2Seric int on = 1; 8315d084d5Seric bool refusingconnections = TRUE; 84914346b1Seric struct sockaddr_in srvraddr; 859b100374Sbostic extern void reapchild(); 86eb889047Seric 87a8268164Seric /* 881c71e510Seric ** Set up the address for the mailer. 89eb889047Seric */ 90eb889047Seric 911c71e510Seric sp = getservbyname("smtp", "tcp"); 921c71e510Seric if (sp == NULL) 93d0a9e852Seric { 941c71e510Seric syserr("server \"smtp\" unknown"); 95a1961f2aSeric goto severe; 961c71e510Seric } 97914346b1Seric srvraddr.sin_family = AF_INET; 98914346b1Seric srvraddr.sin_addr.s_addr = INADDR_ANY; 99914346b1Seric srvraddr.sin_port = sp->s_port; 1001c71e510Seric 1011c71e510Seric /* 1021c71e510Seric ** Try to actually open the connection. 1031c71e510Seric */ 1041c71e510Seric 1051c71e510Seric if (tTd(15, 1)) 106914346b1Seric printf("getrequests: port 0x%x\n", srvraddr.sin_port); 1071c71e510Seric 1081c71e510Seric /* get a socket for the SMTP connection */ 109af5e902cSeric DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 110b7d7afcbSeric if (DaemonSocket < 0) 1111c71e510Seric { 1121c71e510Seric /* probably another daemon already */ 1131c71e510Seric syserr("getrequests: can't create socket"); 1141c71e510Seric severe: 115b0ba8827Seric # ifdef LOG 116b0ba8827Seric if (LogLevel > 0) 117d2aa4720Seric syslog(LOG_ALERT, "cannot get connection"); 118*6c2c3107Seric # endif /* LOG */ 11947b12ae1Seric finis(); 120d0a9e852Seric } 1211b6e4a15Seric 1221b6e4a15Seric /* turn on network debugging? */ 123a2ef5fa4Seric if (tTd(15, 101)) 12452308a50Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 1251b6e4a15Seric 1267868dfc2Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 1277868dfc2Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 1287868dfc2Seric 129914346b1Seric if (bind(DaemonSocket, (struct sockaddr *)&srvraddr, sizeof srvraddr) < 0) 1301c71e510Seric { 1311c71e510Seric syserr("getrequests: cannot bind"); 132b7d7afcbSeric (void) close(DaemonSocket); 1331c71e510Seric goto severe; 1341c71e510Seric } 1351c71e510Seric 1361cd247eeSeric (void) signal(SIGCHLD, reapchild); 13752308a50Seric 1381c71e510Seric if (tTd(15, 1)) 139b7d7afcbSeric printf("getrequests: %d\n", DaemonSocket); 1401c71e510Seric 1411c71e510Seric for (;;) 1421c71e510Seric { 1433a099713Seric register int pid; 144a44d5a5eSeric auto int lotherend; 14515d084d5Seric extern bool refuseconnections(); 1463a099713Seric 1473a099713Seric /* see if we are rejecting connections */ 14815d084d5Seric CurrentLA = getla(); 14915d084d5Seric if (refuseconnections()) 1506775ec03Sbostic { 15115d084d5Seric if (!refusingconnections) 15215d084d5Seric { 15315d084d5Seric /* don't queue so peer will fail quickly */ 15415d084d5Seric (void) listen(DaemonSocket, 0); 15515d084d5Seric refusingconnections = TRUE; 15615d084d5Seric } 15715d084d5Seric setproctitle("rejecting connections: load average: %.2f", 15815d084d5Seric (double)CurrentLA); 1593a099713Seric sleep(5); 16015d084d5Seric continue; 16115d084d5Seric } 16215d084d5Seric 16315d084d5Seric if (refusingconnections) 16415d084d5Seric { 16515d084d5Seric /* start listening again */ 16615d084d5Seric if (listen(DaemonSocket, 10) < 0) 16715d084d5Seric { 16815d084d5Seric syserr("getrequests: cannot listen"); 16915d084d5Seric (void) close(DaemonSocket); 17015d084d5Seric goto severe; 17115d084d5Seric } 17215d084d5Seric setproctitle("accepting connections"); 17315d084d5Seric refusingconnections = FALSE; 1746775ec03Sbostic } 175a44d5a5eSeric 1761c71e510Seric /* wait for a connection */ 1771c71e510Seric do 1781c71e510Seric { 1791c71e510Seric errno = 0; 1809f9a15b6Skarels lotherend = sizeof RealHostAddr; 1819b100374Sbostic t = accept(DaemonSocket, 1829b100374Sbostic (struct sockaddr *)&RealHostAddr, &lotherend); 1831c71e510Seric } while (t < 0 && errno == EINTR); 1841c71e510Seric if (t < 0) 1851c71e510Seric { 1861c71e510Seric syserr("getrequests: accept"); 1871c71e510Seric sleep(5); 1881c71e510Seric continue; 1891c71e510Seric } 190d0a9e852Seric 191d0a9e852Seric /* 192d0a9e852Seric ** Create a subprocess to process the mail. 193d0a9e852Seric */ 194d0a9e852Seric 19561e4310fSeric if (tTd(15, 2)) 1961c71e510Seric printf("getrequests: forking (fd = %d)\n", t); 197eb889047Seric 198a8268164Seric pid = fork(); 199a8268164Seric if (pid < 0) 200a8268164Seric { 201a8268164Seric syserr("daemon: cannot fork"); 202a8268164Seric sleep(10); 2031c71e510Seric (void) close(t); 204a8268164Seric continue; 205a8268164Seric } 206a8268164Seric 207a8268164Seric if (pid == 0) 208a8268164Seric { 209a44d5a5eSeric extern struct hostent *gethostbyaddr(); 210a44d5a5eSeric register struct hostent *hp; 211a44d5a5eSeric char buf[MAXNAME]; 212a44d5a5eSeric 213a8268164Seric /* 214a8268164Seric ** CHILD -- return to caller. 215a44d5a5eSeric ** Collect verified idea of sending host. 216a8268164Seric ** Verify calling user id if possible here. 217a8268164Seric */ 218a8268164Seric 2191cd247eeSeric (void) signal(SIGCHLD, SIG_DFL); 220779ac194Seric 221a44d5a5eSeric /* determine host name */ 2229f9a15b6Skarels hp = gethostbyaddr((char *) &RealHostAddr.sin_addr, sizeof RealHostAddr.sin_addr, AF_INET); 223a44d5a5eSeric if (hp != NULL) 224fefbbe29Seric (void) strcpy(buf, hp->h_name); 225a44d5a5eSeric else 22629dcf4baSeric { 22729dcf4baSeric extern char *inet_ntoa(); 22829dcf4baSeric 22929dcf4baSeric /* produce a dotted quad */ 23029dcf4baSeric (void) sprintf(buf, "[%s]", 2319f9a15b6Skarels inet_ntoa(RealHostAddr.sin_addr)); 23229dcf4baSeric } 23329dcf4baSeric 2342a6bc25bSeric #ifdef LOG 2352a6bc25bSeric if (LogLevel > 9) 2362a6bc25bSeric { 2372a6bc25bSeric /* log connection information */ 2382a6bc25bSeric syslog(LOG_INFO, "connect from %s (%s)", 2392a6bc25bSeric buf, inet_ntoa(RealHostAddr.sin_addr)); 2402a6bc25bSeric } 2412a6bc25bSeric #endif 2422a6bc25bSeric 24329dcf4baSeric /* should we check for illegal connection here? XXX */ 24429dcf4baSeric 245a44d5a5eSeric RealHostName = newstr(buf); 246a44d5a5eSeric 247b7d7afcbSeric (void) close(DaemonSocket); 2481c71e510Seric InChannel = fdopen(t, "r"); 2491d5bd586Seric OutChannel = fdopen(dup(t), "w"); 25061e4310fSeric if (tTd(15, 2)) 251d0a9e852Seric printf("getreq: returning\n"); 252252c8a22Seric # ifdef LOG 253252c8a22Seric if (LogLevel > 11) 254252c8a22Seric syslog(LOG_DEBUG, "connected, pid=%d", getpid()); 255*6c2c3107Seric # endif /* LOG */ 256a8268164Seric return; 257a8268164Seric } 258a8268164Seric 2593c154354Seric /* close the port so that others will hang (for a while) */ 2603c154354Seric (void) close(t); 2618e3e4b17Seric } 2623c154354Seric /*NOTREACHED*/ 2633c154354Seric } 2648e3e4b17Seric /* 265b7d7afcbSeric ** CLRDAEMON -- reset the daemon connection 266b7d7afcbSeric ** 267b7d7afcbSeric ** Parameters: 268b7d7afcbSeric ** none. 269b7d7afcbSeric ** 270b7d7afcbSeric ** Returns: 271b7d7afcbSeric ** none. 272b7d7afcbSeric ** 273b7d7afcbSeric ** Side Effects: 274b7d7afcbSeric ** releases any resources used by the passive daemon. 275b7d7afcbSeric */ 276b7d7afcbSeric 277b7d7afcbSeric clrdaemon() 278b7d7afcbSeric { 279b7d7afcbSeric if (DaemonSocket >= 0) 280b7d7afcbSeric (void) close(DaemonSocket); 281b7d7afcbSeric DaemonSocket = -1; 282b7d7afcbSeric } 283b7d7afcbSeric /* 2847aa493c5Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 2857aa493c5Seric ** 2867aa493c5Seric ** Parameters: 2877aa493c5Seric ** host -- the name of the host. 28848ff0a9dSeric ** port -- the port number to connect to. 289655feedbSeric ** mci -- a pointer to the mail connection information 290655feedbSeric ** structure to be filled in. 291914346b1Seric ** usesecureport -- if set, use a low numbered (reserved) 292914346b1Seric ** port to provide some rudimentary authentication. 2937aa493c5Seric ** 2947aa493c5Seric ** Returns: 2957aa493c5Seric ** An exit code telling whether the connection could be 2967aa493c5Seric ** made and if not why not. 2977aa493c5Seric ** 2987aa493c5Seric ** Side Effects: 2997aa493c5Seric ** none. 3007aa493c5Seric */ 3017aa493c5Seric 302b31e7f2bSeric int 303655feedbSeric makeconnection(host, port, mci, usesecureport) 3047aa493c5Seric char *host; 305210215eaSeric u_short port; 306b31e7f2bSeric register MCI *mci; 307914346b1Seric bool usesecureport; 3087aa493c5Seric { 30904344589Sbloom register int i, s; 31004344589Sbloom register struct hostent *hp = (struct hostent *)NULL; 311914346b1Seric struct sockaddr_in addr; 3126286bb75Sbloom int sav_errno; 313914346b1Seric extern char *inet_ntoa(); 314134746fbSeric #ifdef NAMED_BIND 315134746fbSeric extern int h_errno; 316134746fbSeric #endif 3177aa493c5Seric 3187aa493c5Seric /* 3197aa493c5Seric ** Set up the address for the mailer. 32071096d12Seric ** Accept "[a.b.c.d]" syntax for host name. 3217aa493c5Seric */ 3227aa493c5Seric 323134746fbSeric #ifdef NAMED_BIND 324794bdbb9Smiriam h_errno = 0; 325134746fbSeric #endif 326794bdbb9Smiriam errno = 0; 327794bdbb9Smiriam 32871096d12Seric if (host[0] == '[') 32971096d12Seric { 330a44d5a5eSeric long hid; 331*6c2c3107Seric register char *p = strchr(host, ']'); 33271096d12Seric 333a44d5a5eSeric if (p != NULL) 33471096d12Seric { 335a44d5a5eSeric *p = '\0'; 336a44d5a5eSeric hid = inet_addr(&host[1]); 337a44d5a5eSeric *p = ']'; 33871096d12Seric } 339a44d5a5eSeric if (p == NULL || hid == -1) 34071096d12Seric { 34171096d12Seric usrerr("Invalid numeric domain spec \"%s\"", host); 34271096d12Seric return (EX_NOHOST); 34371096d12Seric } 344914346b1Seric addr.sin_addr.s_addr = hid; 34571096d12Seric } 3461c71e510Seric else 3471c71e510Seric { 34804344589Sbloom hp = gethostbyname(host); 349794bdbb9Smiriam if (hp == NULL) 350794bdbb9Smiriam { 351134746fbSeric #ifdef NAMED_BIND 352794bdbb9Smiriam if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 35352308a50Seric return (EX_TEMPFAIL); 35482e5d8ddSeric 355134746fbSeric /* if name server is specified, assume temp fail */ 356134746fbSeric if (errno == ECONNREFUSED && UseNameServer) 357134746fbSeric return (EX_TEMPFAIL); 358134746fbSeric #endif 359134746fbSeric 36082e5d8ddSeric /* 36182e5d8ddSeric ** XXX Should look for mail forwarder record here 36282e5d8ddSeric ** XXX if (h_errno == NO_ADDRESS). 36382e5d8ddSeric */ 36482e5d8ddSeric 3657aa493c5Seric return (EX_NOHOST); 366794bdbb9Smiriam } 367914346b1Seric bcopy(hp->h_addr, (char *) &addr.sin_addr, hp->h_length); 36804344589Sbloom i = 1; 3691c71e510Seric } 3701c71e510Seric 3711c71e510Seric /* 3721c71e510Seric ** Determine the port number. 3731c71e510Seric */ 3741c71e510Seric 375fd7c0790Seric if (port != 0) 376914346b1Seric addr.sin_port = htons(port); 377fd7c0790Seric else 3781c71e510Seric { 3791c71e510Seric register struct servent *sp = getservbyname("smtp", "tcp"); 3801c71e510Seric 3811c71e510Seric if (sp == NULL) 3821c71e510Seric { 3831c71e510Seric syserr("makeconnection: server \"smtp\" unknown"); 3841c71e510Seric return (EX_OSFILE); 3851c71e510Seric } 386914346b1Seric addr.sin_port = sp->s_port; 3871c71e510Seric } 3887aa493c5Seric 3897aa493c5Seric /* 3907aa493c5Seric ** Try to actually open the connection. 3917aa493c5Seric */ 3927aa493c5Seric 39304344589Sbloom again: 39461e4310fSeric if (tTd(16, 1)) 39504344589Sbloom printf("makeconnection (%s [%s])\n", host, 396914346b1Seric inet_ntoa(addr.sin_addr)); 3977aa493c5Seric 398914346b1Seric if (usesecureport) 399914346b1Seric { 400914346b1Seric int rport = IPPORT_RESERVED - 1; 401914346b1Seric 402914346b1Seric s = rresvport(&rport); 403914346b1Seric } 404914346b1Seric else 405914346b1Seric { 406af5e902cSeric s = socket(AF_INET, SOCK_STREAM, 0); 407914346b1Seric } 4087aa493c5Seric if (s < 0) 4097aa493c5Seric { 4106286bb75Sbloom sav_errno = errno; 411914346b1Seric syserr("makeconnection: no socket"); 4127aa493c5Seric goto failure; 4137aa493c5Seric } 4147aa493c5Seric 41561e4310fSeric if (tTd(16, 1)) 416b31e7f2bSeric printf("makeconnection: fd=%d\n", s); 4171b6e4a15Seric 4181b6e4a15Seric /* turn on network debugging? */ 419a2ef5fa4Seric if (tTd(16, 101)) 42052308a50Seric { 42152308a50Seric int on = 1; 42252308a50Seric (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 42352308a50Seric } 42487d6e633Srick if (CurEnv->e_xfp != NULL) 425877a6142Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 4264bd6a662Seric errno = 0; /* for debugging */ 427914346b1Seric addr.sin_family = AF_INET; 428914346b1Seric if (connect(s, (struct sockaddr *) &addr, sizeof addr) < 0) 4297aa493c5Seric { 4306286bb75Sbloom sav_errno = errno; 4316286bb75Sbloom (void) close(s); 43204344589Sbloom if (hp && hp->h_addr_list[i]) 43304344589Sbloom { 434914346b1Seric bcopy(hp->h_addr_list[i++], (char *) &addr.sin_addr, 435914346b1Seric hp->h_length); 43604344589Sbloom goto again; 43704344589Sbloom } 43804344589Sbloom 4397aa493c5Seric /* failure, decide if temporary or not */ 4407aa493c5Seric failure: 4416286bb75Sbloom switch (sav_errno) 4427aa493c5Seric { 4437aa493c5Seric case EISCONN: 4447aa493c5Seric case ETIMEDOUT: 445292668b9Seric case EINPROGRESS: 446292668b9Seric case EALREADY: 447292668b9Seric case EADDRINUSE: 44836bd23a8Seric case EHOSTDOWN: 449292668b9Seric case ENETDOWN: 450292668b9Seric case ENETRESET: 451292668b9Seric case ENOBUFS: 452a1645df8Seric case ECONNREFUSED: 453efe49624Seric case ECONNRESET: 454cae8261aSeric case EHOSTUNREACH: 455dca8e1f7Seric case ENETUNREACH: 4569b2e2555Seric #ifdef ENOSR 4579b2e2555Seric case ENOSR: 4589b2e2555Seric #endif 4597aa493c5Seric /* there are others, I'm sure..... */ 4607aa493c5Seric return (EX_TEMPFAIL); 4617aa493c5Seric 462a44d5a5eSeric case EPERM: 463a44d5a5eSeric /* why is this happening? */ 464a44d5a5eSeric syserr("makeconnection: funny failure, addr=%lx, port=%x", 465914346b1Seric addr.sin_addr.s_addr, addr.sin_port); 4664bd6a662Seric return (EX_TEMPFAIL); 467a44d5a5eSeric 4687aa493c5Seric default: 46987d6e633Srick { 47087d6e633Srick extern char *errstring(); 47187d6e633Srick 472e8212f61Sbostic message(Arpa_Info, "%s", errstring(sav_errno)); 4737aa493c5Seric return (EX_UNAVAILABLE); 4747aa493c5Seric } 4757aa493c5Seric } 47687d6e633Srick } 4777aa493c5Seric 4787aa493c5Seric /* connection ok, put it into canonical form */ 479655feedbSeric mci->mci_out = fdopen(s, "w"); 480655feedbSeric mci->mci_in = fdopen(dup(s), "r"); 4817aa493c5Seric 482dca8e1f7Seric return (EX_OK); 4837aa493c5Seric } 484444eaf03Seric /* 485444eaf03Seric ** MYHOSTNAME -- return the name of this host. 486444eaf03Seric ** 487444eaf03Seric ** Parameters: 488444eaf03Seric ** hostbuf -- a place to return the name of this host. 489897f1869Seric ** size -- the size of hostbuf. 490444eaf03Seric ** 491444eaf03Seric ** Returns: 492444eaf03Seric ** A list of aliases for this host. 493444eaf03Seric ** 494444eaf03Seric ** Side Effects: 495444eaf03Seric ** none. 496444eaf03Seric */ 497444eaf03Seric 498444eaf03Seric char ** 499897f1869Seric myhostname(hostbuf, size) 500444eaf03Seric char hostbuf[]; 501897f1869Seric int size; 502444eaf03Seric { 503444eaf03Seric extern struct hostent *gethostbyname(); 504a44d5a5eSeric struct hostent *hp; 505444eaf03Seric 506af5e902cSeric if (gethostname(hostbuf, size) < 0) 507af5e902cSeric { 508af5e902cSeric (void) strcpy(hostbuf, "localhost"); 509af5e902cSeric } 510a44d5a5eSeric hp = gethostbyname(hostbuf); 511a44d5a5eSeric if (hp != NULL) 5127364df9fSeric { 513fefbbe29Seric (void) strcpy(hostbuf, hp->h_name); 514a44d5a5eSeric return (hp->h_aliases); 5157364df9fSeric } 516444eaf03Seric else 517444eaf03Seric return (NULL); 518444eaf03Seric } 519cb452edcSeric /* 52015d084d5Seric ** MAPHOSTNAME -- turn a hostname into canonical form 52115d084d5Seric ** 52215d084d5Seric ** Parameters: 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 * 53915d084d5Seric maphostname(hbuf, hbsize, avp) 54099f7cf32Seric char *hbuf; 54199f7cf32Seric int hbsize; 54215d084d5Seric char **avp; 54399f7cf32Seric { 54499f7cf32Seric register struct hostent *hp; 5455f78836eSmiriam u_long in_addr; 54634e39927Sbostic char ptr[256], *cp; 547f36ede03Sbostic struct hostent *gethostbyaddr(); 5485f78836eSmiriam 54915d084d5Seric /* allow room for trailing dot on correct match */ 55015d084d5Seric if (ConfigLevel >= 2) 55115d084d5Seric hbsize--; 55215d084d5Seric 553f36ede03Sbostic /* 554f36ede03Sbostic * If first character is a bracket, then it is an address 555f36ede03Sbostic * lookup. Address is copied into a temporary buffer to 556f36ede03Sbostic * strip the brackets and to preserve hbuf if address is 557f36ede03Sbostic * unknown. 558f36ede03Sbostic */ 55915d084d5Seric 560cb452edcSeric if (*hbuf != '[') 56115d084d5Seric { 562d798a1deSeric extern bool getcanonname(); 563d798a1deSeric 56415d084d5Seric if (getcanonname(hbuf, hbsize)) 56515d084d5Seric { 56615d084d5Seric /* found a match -- add the trailing dot */ 56715d084d5Seric if (ConfigLevel >= 2) 568dafbc479Seric { 569dafbc479Seric int i = strlen(hbuf) - 1; 570dafbc479Seric 571dafbc479Seric if (hbuf[i] != '.') 572dafbc479Seric (void) strcpy(&hbuf[++i], "."); 573dafbc479Seric } 57415d084d5Seric return hbuf; 57515d084d5Seric } 57615d084d5Seric else 57715d084d5Seric return NULL; 57815d084d5Seric } 579*6c2c3107Seric if ((cp = strchr(strcpy(ptr, hbuf), ']')) == NULL) 58015d084d5Seric return (NULL); 58134e39927Sbostic *cp = '\0'; 5825f78836eSmiriam in_addr = inet_addr(&ptr[1]); 58331601fa7Seric hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 5845f78836eSmiriam if (hp == NULL) 58515d084d5Seric return (NULL); 58615d084d5Seric 58715d084d5Seric /* found a match -- copy and dot terminate */ 588f36ede03Sbostic if (strlen(hp->h_name) >= hbsize) 589301df7d6Sbloom hp->h_name[hbsize - 1] = '\0'; 590fefbbe29Seric (void) strcpy(hbuf, hp->h_name); 59115d084d5Seric if (ConfigLevel >= 2) 59215d084d5Seric (void) strcat(hbuf, "."); 59315d084d5Seric return hbuf; 59499f7cf32Seric } 595f36ede03Sbostic 596*6c2c3107Seric # else /* DAEMON */ 59799f7cf32Seric /* code for systems without sophisticated networking */ 598444eaf03Seric 599444eaf03Seric /* 600444eaf03Seric ** MYHOSTNAME -- stub version for case of no daemon code. 60121e9914dSeric ** 60221e9914dSeric ** Can't convert to upper case here because might be a UUCP name. 603897f1869Seric ** 604897f1869Seric ** Mark, you can change this to be anything you want...... 605444eaf03Seric */ 606444eaf03Seric 607444eaf03Seric char ** 608897f1869Seric myhostname(hostbuf, size) 609444eaf03Seric char hostbuf[]; 610897f1869Seric int size; 611444eaf03Seric { 612444eaf03Seric register FILE *f; 613444eaf03Seric 614444eaf03Seric hostbuf[0] = '\0'; 615444eaf03Seric f = fopen("/usr/include/whoami", "r"); 616444eaf03Seric if (f != NULL) 617444eaf03Seric { 618897f1869Seric (void) fgets(hostbuf, size, f); 619444eaf03Seric fixcrlf(hostbuf, TRUE); 620444eaf03Seric (void) fclose(f); 621444eaf03Seric } 622444eaf03Seric return (NULL); 623444eaf03Seric } 62499f7cf32Seric /* 62599f7cf32Seric ** MAPHOSTNAME -- turn a hostname into canonical form 62699f7cf32Seric ** 62799f7cf32Seric ** Parameters: 62899f7cf32Seric ** hbuf -- a buffer containing a hostname. 62999f7cf32Seric ** hbsize -- the size of hbuf. 63015d084d5Seric ** avp -- a pointer to a (cf file defined) argument vector. 63199f7cf32Seric ** 63299f7cf32Seric ** Returns: 63315d084d5Seric ** mapped host name 634cb452edcSeric ** FALSE otherwise. 63599f7cf32Seric ** 63699f7cf32Seric ** Side Effects: 63799f7cf32Seric ** Looks up the host specified in hbuf. If it is not 63899f7cf32Seric ** the canonical name for that host, replace it with 63999f7cf32Seric ** the canonical name. If the name is unknown, or it 64099f7cf32Seric ** is already the canonical name, leave it unchanged. 64199f7cf32Seric */ 64299f7cf32Seric 64399f7cf32Seric /*ARGSUSED*/ 64415d084d5Seric char * 64515d084d5Seric maphostname(hbuf, hbsize, avp) 64699f7cf32Seric char *hbuf; 64799f7cf32Seric int hbsize; 64815d084d5Seric char **avp; 64999f7cf32Seric { 65015d084d5Seric return NULL; 65199f7cf32Seric } 65299f7cf32Seric 653*6c2c3107Seric #endif /* DAEMON */ 654