1 # include <errno.h> 2 # include "sendmail.h" 3 4 #ifndef DAEMON 5 SCCSID(@(#)daemon.c 3.11 05/06/82 (w/o daemon mode)); 6 #else 7 8 # include <sys/socket.h> 9 # include <net/in.h> 10 11 SCCSID(@(#)daemon.c 3.11 05/06/82 (with daemon mode)); 12 13 /* 14 ** DAEMON.C -- routines to use when running as a daemon. 15 */ 16 /* 17 ** GETREQUESTS -- open mail IPC port and get requests. 18 ** 19 ** Parameters: 20 ** none. 21 ** 22 ** Returns: 23 ** none. 24 ** 25 ** Side Effects: 26 ** Waits until some interesting activity occurs. When 27 ** it does, a child is created to process it, and the 28 ** parent waits for completion. Return from this 29 ** routine is always in the child. 30 */ 31 32 getrequests() 33 { 34 for (;;) 35 { 36 register int pid; 37 auto int st; 38 register int port; 39 40 /* 41 ** Wait for a connection. 42 */ 43 44 while ((port = getconnection()) < 0) 45 { 46 syserr("getrequests: getconnection failed"); 47 sleep(30); 48 } 49 50 /* 51 ** Create a subprocess to process the mail. 52 */ 53 54 # ifdef DEBUG 55 if (Debug > 1) 56 printf("getrequests: forking (port = %d)\n", port); 57 # endif DEBUG 58 59 pid = fork(); 60 if (pid < 0) 61 { 62 syserr("daemon: cannot fork"); 63 sleep(10); 64 close(port); 65 continue; 66 } 67 68 if (pid == 0) 69 { 70 /* 71 ** CHILD -- return to caller. 72 ** Verify calling user id if possible here. 73 */ 74 75 InChannel = fdopen(port, "r"); 76 OutChannel = fdopen(port, "w"); 77 initsys(); 78 # ifdef DEBUG 79 if (Debug > 1) 80 printf("getreq: returning\n"); 81 # endif DEBUG 82 return; 83 } 84 85 /* 86 ** PARENT -- wait for child to terminate. 87 ** Perhaps we should allow concurrent processing? 88 */ 89 90 # ifdef DEBUG 91 if (Debug > 1) 92 { 93 sleep(2); 94 printf("getreq: parent waiting\n"); 95 } 96 # endif DEBUG 97 98 (void) wait(&st); 99 close(port); 100 } 101 } 102 /* 103 ** GETCONNECTION -- make a connection with the outside world 104 ** 105 ** Parameters: 106 ** none. 107 ** 108 ** Returns: 109 ** The port for mail traffic. 110 ** 111 ** Side Effects: 112 ** Waits for a connection. 113 */ 114 115 struct sockaddr_in SendmailAddress = { AF_INET, IPPORT_SMTP }; 116 117 getconnection() 118 { 119 register int s; 120 struct sockaddr otherend; 121 122 /* 123 ** Set up the address for the mailer. 124 */ 125 126 SendmailAddress.sin_addr.s_addr = 0; 127 SendmailAddress.sin_port = IPPORT_SMTP; 128 129 /* 130 ** Try to actually open the connection. 131 */ 132 133 # ifdef DEBUG 134 if (Debug) 135 printf("getconnection\n"); 136 # endif DEBUG 137 138 s = socket(SOCK_STREAM, 0, &SendmailAddress, SO_ACCEPTCONN); 139 140 # ifdef DEBUG 141 if (Debug) 142 printf("getconnection: %d\n", s); 143 # endif DEBUG 144 accept(s, &otherend); 145 146 return (s); 147 } 148 /* 149 ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 150 ** 151 ** Parameters: 152 ** host -- the name of the host. 153 ** port -- the port number to connect to. 154 ** outfile -- a pointer to a place to put the outfile 155 ** descriptor. 156 ** infile -- ditto for infile. 157 ** 158 ** Returns: 159 ** An exit code telling whether the connection could be 160 ** made and if not why not. 161 ** 162 ** Side Effects: 163 ** none. 164 */ 165 166 makeconnection(host, port, outfile, infile) 167 char *host; 168 int port; 169 FILE **outfile; 170 FILE **infile; 171 { 172 register int s; 173 174 /* 175 ** Set up the address for the mailer. 176 */ 177 178 if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1) 179 return (EX_NOHOST); 180 if (port == 0) 181 port = IPPORT_SMTP; 182 SendmailAddress.sin_port = port; 183 184 /* 185 ** Try to actually open the connection. 186 */ 187 188 # ifdef DEBUG 189 if (Debug) 190 printf("makeconnection (%s)\n", host); 191 # endif DEBUG 192 193 s = socket(SOCK_STREAM, 0, 0, 0); 194 if (s < 0) 195 { 196 syserr("makeconnection: no socket"); 197 goto failure; 198 } 199 200 # ifdef DEBUG 201 if (Debug) 202 printf("makeconnection: %d\n", s); 203 # endif DEBUG 204 if (connect(s, &SendmailAddress) < 0) 205 { 206 /* failure, decide if temporary or not */ 207 failure: 208 switch (errno) 209 { 210 case EISCONN: 211 case ETIMEDOUT: 212 /* there are others, I'm sure..... */ 213 return (EX_TEMPFAIL); 214 215 default: 216 return (EX_UNAVAILABLE); 217 } 218 } 219 220 /* connection ok, put it into canonical form */ 221 *outfile = fdopen(s, "w"); 222 *infile = fdopen(s, "r"); 223 224 return (0); 225 } 226 227 #endif DAEMON 228