16039Seric # include <errno.h> 24535Seric # include "sendmail.h" 34535Seric 45978Seric #ifndef DAEMON 5*6897Seric SCCSID(@(#)daemon.c 3.12 05/22/82 (w/o daemon mode)); 65978Seric #else 74535Seric 85978Seric # include <sys/socket.h> 95978Seric # include <net/in.h> 105978Seric 11*6897Seric SCCSID(@(#)daemon.c 3.12 05/22/82 (with daemon mode)); 125978Seric 134535Seric /* 144535Seric ** DAEMON.C -- routines to use when running as a daemon. 154535Seric */ 164535Seric /* 174535Seric ** GETREQUESTS -- open mail IPC port and get requests. 184535Seric ** 194535Seric ** Parameters: 204535Seric ** none. 214535Seric ** 224535Seric ** Returns: 234535Seric ** none. 244535Seric ** 254535Seric ** Side Effects: 264535Seric ** Waits until some interesting activity occurs. When 274535Seric ** it does, a child is created to process it, and the 284535Seric ** parent waits for completion. Return from this 294535Seric ** routine is always in the child. 304535Seric */ 314535Seric 324535Seric getrequests() 334535Seric { 344631Seric for (;;) 354631Seric { 364636Seric register int pid; 374636Seric auto int st; 385978Seric register int port; 394631Seric 404636Seric /* 414636Seric ** Wait for a connection. 424636Seric */ 434631Seric 445978Seric while ((port = getconnection()) < 0) 455978Seric { 465978Seric syserr("getrequests: getconnection failed"); 475978Seric sleep(30); 485978Seric } 494631Seric 505978Seric /* 515978Seric ** Create a subprocess to process the mail. 525978Seric */ 535978Seric 545978Seric # ifdef DEBUG 555978Seric if (Debug > 1) 565978Seric printf("getrequests: forking (port = %d)\n", port); 575978Seric # endif DEBUG 585978Seric 594636Seric pid = fork(); 604636Seric if (pid < 0) 614631Seric { 624636Seric syserr("daemon: cannot fork"); 634636Seric sleep(10); 645978Seric close(port); 654636Seric continue; 664631Seric } 674631Seric 684636Seric if (pid == 0) 694631Seric { 704636Seric /* 714636Seric ** CHILD -- return to caller. 724636Seric ** Verify calling user id if possible here. 734636Seric */ 744631Seric 755978Seric InChannel = fdopen(port, "r"); 765978Seric OutChannel = fdopen(port, "w"); 774636Seric initsys(); 785978Seric # ifdef DEBUG 795978Seric if (Debug > 1) 805978Seric printf("getreq: returning\n"); 815978Seric # endif DEBUG 824636Seric return; 834631Seric } 844631Seric 854636Seric /* 864636Seric ** PARENT -- wait for child to terminate. 874636Seric ** Perhaps we should allow concurrent processing? 884636Seric */ 894631Seric 905978Seric # ifdef DEBUG 915978Seric if (Debug > 1) 925978Seric { 935978Seric sleep(2); 945978Seric printf("getreq: parent waiting\n"); 955978Seric } 965978Seric # endif DEBUG 975978Seric 984836Seric (void) wait(&st); 995978Seric close(port); 1004631Seric } 1014631Seric } 1025978Seric /* 1035978Seric ** GETCONNECTION -- make a connection with the outside world 1045978Seric ** 1055978Seric ** Parameters: 1065978Seric ** none. 1075978Seric ** 1085978Seric ** Returns: 1095978Seric ** The port for mail traffic. 1105978Seric ** 1115978Seric ** Side Effects: 1125978Seric ** Waits for a connection. 1135978Seric */ 1145978Seric 1155979Seric struct sockaddr_in SendmailAddress = { AF_INET, IPPORT_SMTP }; 1165978Seric 1175978Seric getconnection() 1185978Seric { 1195978Seric register int s; 1205978Seric struct sockaddr otherend; 1215978Seric 1225978Seric /* 1235978Seric ** Set up the address for the mailer. 1245978Seric */ 1255978Seric 1266058Seric SendmailAddress.sin_addr.s_addr = 0; 1276633Seric SendmailAddress.sin_port = IPPORT_SMTP; 1285978Seric 1295978Seric /* 1305978Seric ** Try to actually open the connection. 1315978Seric */ 1325978Seric 1335978Seric # ifdef DEBUG 1345978Seric if (Debug) 1356058Seric printf("getconnection\n"); 1365978Seric # endif DEBUG 1375978Seric 1385978Seric s = socket(SOCK_STREAM, 0, &SendmailAddress, SO_ACCEPTCONN); 1395978Seric 1405978Seric # ifdef DEBUG 1415978Seric if (Debug) 1425978Seric printf("getconnection: %d\n", s); 1435978Seric # endif DEBUG 1445978Seric accept(s, &otherend); 1455978Seric 1465978Seric return (s); 1475978Seric } 1486039Seric /* 1496039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 1506039Seric ** 1516039Seric ** Parameters: 1526039Seric ** host -- the name of the host. 1536633Seric ** port -- the port number to connect to. 1546039Seric ** outfile -- a pointer to a place to put the outfile 1556039Seric ** descriptor. 1566039Seric ** infile -- ditto for infile. 1576039Seric ** 1586039Seric ** Returns: 1596039Seric ** An exit code telling whether the connection could be 1606039Seric ** made and if not why not. 1616039Seric ** 1626039Seric ** Side Effects: 1636039Seric ** none. 1646039Seric */ 1655978Seric 1666633Seric makeconnection(host, port, outfile, infile) 1676039Seric char *host; 1686633Seric int port; 1696039Seric FILE **outfile; 1706039Seric FILE **infile; 1716039Seric { 1726039Seric register int s; 1736039Seric 1746039Seric /* 1756039Seric ** Set up the address for the mailer. 1766039Seric */ 1776039Seric 1786039Seric if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1) 1796039Seric return (EX_NOHOST); 1806633Seric if (port == 0) 1816633Seric port = IPPORT_SMTP; 1826633Seric SendmailAddress.sin_port = port; 1836039Seric 1846039Seric /* 1856039Seric ** Try to actually open the connection. 1866039Seric */ 1876039Seric 1886039Seric # ifdef DEBUG 1896039Seric if (Debug) 1906039Seric printf("makeconnection (%s)\n", host); 1916039Seric # endif DEBUG 1926039Seric 1936039Seric s = socket(SOCK_STREAM, 0, 0, 0); 1946039Seric if (s < 0) 1956039Seric { 1966039Seric syserr("makeconnection: no socket"); 1976039Seric goto failure; 1986039Seric } 1996039Seric 2006039Seric # ifdef DEBUG 2016039Seric if (Debug) 2026039Seric printf("makeconnection: %d\n", s); 2036039Seric # endif DEBUG 2046039Seric if (connect(s, &SendmailAddress) < 0) 2056039Seric { 2066039Seric /* failure, decide if temporary or not */ 2076039Seric failure: 2086039Seric switch (errno) 2096039Seric { 2106039Seric case EISCONN: 2116039Seric case ETIMEDOUT: 212*6897Seric case EINPROGRESS: 213*6897Seric case EALREADY: 214*6897Seric case EADDRINUSE: 215*6897Seric case ENETDOWN: 216*6897Seric case ENETRESET: 217*6897Seric case ENOBUFS: 2186039Seric /* there are others, I'm sure..... */ 2196039Seric return (EX_TEMPFAIL); 2206039Seric 2216039Seric default: 2226039Seric return (EX_UNAVAILABLE); 2236039Seric } 2246039Seric } 2256039Seric 2266039Seric /* connection ok, put it into canonical form */ 2276039Seric *outfile = fdopen(s, "w"); 2286039Seric *infile = fdopen(s, "r"); 2296039Seric 2306039Seric return (0); 2316039Seric } 2326039Seric 2335978Seric #endif DAEMON 234