16039Seric # include <errno.h> 24535Seric # include "sendmail.h" 34535Seric 45978Seric #ifndef DAEMON 5*6058Seric SCCSID(@(#)daemon.c 3.9 03/06/82 (w/o daemon mode)); 65978Seric #else 74535Seric 85978Seric # include <sys/socket.h> 95978Seric # include <wellknown.h> 105978Seric # include <net/in.h> 115978Seric 12*6058Seric SCCSID(@(#)daemon.c 3.9 03/06/82 (with daemon mode)); 135978Seric 144535Seric /* 154535Seric ** DAEMON.C -- routines to use when running as a daemon. 164535Seric */ 174535Seric /* 184535Seric ** GETREQUESTS -- open mail IPC port and get requests. 194535Seric ** 204535Seric ** Parameters: 214535Seric ** none. 224535Seric ** 234535Seric ** Returns: 244535Seric ** none. 254535Seric ** 264535Seric ** Side Effects: 274535Seric ** Waits until some interesting activity occurs. When 284535Seric ** it does, a child is created to process it, and the 294535Seric ** parent waits for completion. Return from this 304535Seric ** routine is always in the child. 314535Seric */ 324535Seric 334535Seric getrequests() 344535Seric { 354631Seric for (;;) 364631Seric { 374636Seric register int pid; 384636Seric auto int st; 395978Seric register int port; 404631Seric 414636Seric /* 424636Seric ** Wait for a connection. 434636Seric */ 444631Seric 455978Seric while ((port = getconnection()) < 0) 465978Seric { 475978Seric syserr("getrequests: getconnection failed"); 485978Seric sleep(30); 495978Seric } 504631Seric 515978Seric /* 525978Seric ** Create a subprocess to process the mail. 535978Seric */ 545978Seric 555978Seric # ifdef DEBUG 565978Seric if (Debug > 1) 575978Seric printf("getrequests: forking (port = %d)\n", port); 585978Seric # endif DEBUG 595978Seric 604636Seric pid = fork(); 614636Seric if (pid < 0) 624631Seric { 634636Seric syserr("daemon: cannot fork"); 644636Seric sleep(10); 655978Seric close(port); 664636Seric continue; 674631Seric } 684631Seric 694636Seric if (pid == 0) 704631Seric { 714636Seric /* 724636Seric ** CHILD -- return to caller. 734636Seric ** Verify calling user id if possible here. 744636Seric */ 754631Seric 765978Seric InChannel = fdopen(port, "r"); 775978Seric OutChannel = fdopen(port, "w"); 784636Seric initsys(); 795978Seric # ifdef DEBUG 805978Seric if (Debug > 1) 815978Seric printf("getreq: returning\n"); 825978Seric # endif DEBUG 834636Seric return; 844631Seric } 854631Seric 864636Seric /* 874636Seric ** PARENT -- wait for child to terminate. 884636Seric ** Perhaps we should allow concurrent processing? 894636Seric */ 904631Seric 915978Seric # ifdef DEBUG 925978Seric if (Debug > 1) 935978Seric { 945978Seric sleep(2); 955978Seric printf("getreq: parent waiting\n"); 965978Seric } 975978Seric # endif DEBUG 985978Seric 994836Seric (void) wait(&st); 1005978Seric close(port); 1014631Seric } 1024631Seric } 1035978Seric /* 1045978Seric ** GETCONNECTION -- make a connection with the outside world 1055978Seric ** 1065978Seric ** Parameters: 1075978Seric ** none. 1085978Seric ** 1095978Seric ** Returns: 1105978Seric ** The port for mail traffic. 1115978Seric ** 1125978Seric ** Side Effects: 1135978Seric ** Waits for a connection. 1145978Seric */ 1155978Seric 1165979Seric struct sockaddr_in SendmailAddress = { AF_INET, IPPORT_SMTP }; 1175978Seric 1185978Seric getconnection() 1195978Seric { 1205978Seric register int s; 1215978Seric struct sockaddr otherend; 1225978Seric 1235978Seric /* 1245978Seric ** Set up the address for the mailer. 1255978Seric */ 1265978Seric 127*6058Seric SendmailAddress.sin_addr.s_addr = 0; 1285978Seric 1295978Seric /* 1305978Seric ** Try to actually open the connection. 1315978Seric */ 1325978Seric 1335978Seric # ifdef DEBUG 1345978Seric if (Debug) 135*6058Seric 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. 1536039Seric ** outfile -- a pointer to a place to put the outfile 1546039Seric ** descriptor. 1556039Seric ** infile -- ditto for infile. 1566039Seric ** 1576039Seric ** Returns: 1586039Seric ** An exit code telling whether the connection could be 1596039Seric ** made and if not why not. 1606039Seric ** 1616039Seric ** Side Effects: 1626039Seric ** none. 1636039Seric */ 1645978Seric 1656039Seric makeconnection(host, outfile, infile) 1666039Seric char *host; 1676039Seric FILE **outfile; 1686039Seric FILE **infile; 1696039Seric { 1706039Seric register int s; 1716039Seric 1726039Seric /* 1736039Seric ** Set up the address for the mailer. 1746039Seric */ 1756039Seric 1766039Seric if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1) 1776039Seric return (EX_NOHOST); 1786039Seric 1796039Seric /* 1806039Seric ** Try to actually open the connection. 1816039Seric */ 1826039Seric 1836039Seric # ifdef DEBUG 1846039Seric if (Debug) 1856039Seric printf("makeconnection (%s)\n", host); 1866039Seric # endif DEBUG 1876039Seric 1886039Seric s = socket(SOCK_STREAM, 0, 0, 0); 1896039Seric if (s < 0) 1906039Seric { 1916039Seric syserr("makeconnection: no socket"); 1926039Seric goto failure; 1936039Seric } 1946039Seric 1956039Seric # ifdef DEBUG 1966039Seric if (Debug) 1976039Seric printf("makeconnection: %d\n", s); 1986039Seric # endif DEBUG 1996039Seric if (connect(s, &SendmailAddress) < 0) 2006039Seric { 2016039Seric /* failure, decide if temporary or not */ 2026039Seric failure: 2036039Seric switch (errno) 2046039Seric { 2056039Seric case EISCONN: 2066039Seric case ETIMEDOUT: 2076039Seric /* there are others, I'm sure..... */ 2086039Seric return (EX_TEMPFAIL); 2096039Seric 2106039Seric default: 2116039Seric return (EX_UNAVAILABLE); 2126039Seric } 2136039Seric } 2146039Seric 2156039Seric /* connection ok, put it into canonical form */ 2166039Seric *outfile = fdopen(s, "w"); 2176039Seric *infile = fdopen(s, "r"); 2186039Seric 2196039Seric return (0); 2206039Seric } 2216039Seric 2225978Seric #endif DAEMON 223