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