1*6039Seric # include <errno.h> 24535Seric # include "sendmail.h" 34535Seric 45978Seric #ifndef DAEMON 5*6039Seric SCCSID(@(#)daemon.c 3.8 03/05/82 (w/o daemon mode)); 65978Seric #else 74535Seric 85978Seric # include <sys/socket.h> 95978Seric # include <wellknown.h> 105978Seric # include <net/in.h> 115978Seric 12*6039Seric SCCSID(@(#)daemon.c 3.8 03/05/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 char *host = "localhost"; 1225978Seric struct sockaddr otherend; 1235978Seric 1245978Seric /* 1255978Seric ** Set up the address for the mailer. 1265978Seric */ 1275978Seric 1285978Seric SendmailAddress.sin_addr.s_addr = rhost(&host); 1295978Seric 1305978Seric /* 1315978Seric ** Try to actually open the connection. 1325978Seric */ 1335978Seric 1345978Seric # ifdef DEBUG 1355978Seric if (Debug) 1365978Seric printf("getconnection (%s)\n", host); 1375978Seric # endif DEBUG 1385978Seric 1395978Seric s = socket(SOCK_STREAM, 0, &SendmailAddress, SO_ACCEPTCONN); 1405978Seric 1415978Seric # ifdef DEBUG 1425978Seric if (Debug) 1435978Seric printf("getconnection: %d\n", s); 1445978Seric # endif DEBUG 1455978Seric accept(s, &otherend); 1465978Seric 1475978Seric return (s); 1485978Seric } 149*6039Seric /* 150*6039Seric ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 151*6039Seric ** 152*6039Seric ** Parameters: 153*6039Seric ** host -- the name of the host. 154*6039Seric ** outfile -- a pointer to a place to put the outfile 155*6039Seric ** descriptor. 156*6039Seric ** infile -- ditto for infile. 157*6039Seric ** 158*6039Seric ** Returns: 159*6039Seric ** An exit code telling whether the connection could be 160*6039Seric ** made and if not why not. 161*6039Seric ** 162*6039Seric ** Side Effects: 163*6039Seric ** none. 164*6039Seric */ 1655978Seric 166*6039Seric makeconnection(host, outfile, infile) 167*6039Seric char *host; 168*6039Seric FILE **outfile; 169*6039Seric FILE **infile; 170*6039Seric { 171*6039Seric register int s; 172*6039Seric 173*6039Seric /* 174*6039Seric ** Set up the address for the mailer. 175*6039Seric */ 176*6039Seric 177*6039Seric if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1) 178*6039Seric return (EX_NOHOST); 179*6039Seric 180*6039Seric /* 181*6039Seric ** Try to actually open the connection. 182*6039Seric */ 183*6039Seric 184*6039Seric # ifdef DEBUG 185*6039Seric if (Debug) 186*6039Seric printf("makeconnection (%s)\n", host); 187*6039Seric # endif DEBUG 188*6039Seric 189*6039Seric s = socket(SOCK_STREAM, 0, 0, 0); 190*6039Seric if (s < 0) 191*6039Seric { 192*6039Seric syserr("makeconnection: no socket"); 193*6039Seric goto failure; 194*6039Seric } 195*6039Seric 196*6039Seric # ifdef DEBUG 197*6039Seric if (Debug) 198*6039Seric printf("makeconnection: %d\n", s); 199*6039Seric # endif DEBUG 200*6039Seric if (connect(s, &SendmailAddress) < 0) 201*6039Seric { 202*6039Seric /* failure, decide if temporary or not */ 203*6039Seric failure: 204*6039Seric switch (errno) 205*6039Seric { 206*6039Seric case EISCONN: 207*6039Seric case ETIMEDOUT: 208*6039Seric /* there are others, I'm sure..... */ 209*6039Seric return (EX_TEMPFAIL); 210*6039Seric 211*6039Seric default: 212*6039Seric return (EX_UNAVAILABLE); 213*6039Seric } 214*6039Seric } 215*6039Seric 216*6039Seric /* connection ok, put it into canonical form */ 217*6039Seric *outfile = fdopen(s, "w"); 218*6039Seric *infile = fdopen(s, "r"); 219*6039Seric 220*6039Seric return (0); 221*6039Seric } 222*6039Seric 2235978Seric #endif DAEMON 224