1 # include <errno.h> 2 # include "sendmail.h" 3 4 #ifndef DAEMON 5 SCCSID(@(#)daemon.c 3.10 03/22/82 (w/o daemon mode)); 6 #else 7 8 # include <sys/socket.h> 9 # include <net/in.h> 10 11 SCCSID(@(#)daemon.c 3.10 03/22/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 128 /* 129 ** Try to actually open the connection. 130 */ 131 132 # ifdef DEBUG 133 if (Debug) 134 printf("getconnection\n"); 135 # endif DEBUG 136 137 s = socket(SOCK_STREAM, 0, &SendmailAddress, SO_ACCEPTCONN); 138 139 # ifdef DEBUG 140 if (Debug) 141 printf("getconnection: %d\n", s); 142 # endif DEBUG 143 accept(s, &otherend); 144 145 return (s); 146 } 147 /* 148 ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 149 ** 150 ** Parameters: 151 ** host -- the name of the host. 152 ** outfile -- a pointer to a place to put the outfile 153 ** descriptor. 154 ** infile -- ditto for infile. 155 ** 156 ** Returns: 157 ** An exit code telling whether the connection could be 158 ** made and if not why not. 159 ** 160 ** Side Effects: 161 ** none. 162 */ 163 164 makeconnection(host, outfile, infile) 165 char *host; 166 FILE **outfile; 167 FILE **infile; 168 { 169 register int s; 170 171 /* 172 ** Set up the address for the mailer. 173 */ 174 175 if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1) 176 return (EX_NOHOST); 177 178 /* 179 ** Try to actually open the connection. 180 */ 181 182 # ifdef DEBUG 183 if (Debug) 184 printf("makeconnection (%s)\n", host); 185 # endif DEBUG 186 187 s = socket(SOCK_STREAM, 0, 0, 0); 188 if (s < 0) 189 { 190 syserr("makeconnection: no socket"); 191 goto failure; 192 } 193 194 # ifdef DEBUG 195 if (Debug) 196 printf("makeconnection: %d\n", s); 197 # endif DEBUG 198 if (connect(s, &SendmailAddress) < 0) 199 { 200 /* failure, decide if temporary or not */ 201 failure: 202 switch (errno) 203 { 204 case EISCONN: 205 case ETIMEDOUT: 206 /* there are others, I'm sure..... */ 207 return (EX_TEMPFAIL); 208 209 default: 210 return (EX_UNAVAILABLE); 211 } 212 } 213 214 /* connection ok, put it into canonical form */ 215 *outfile = fdopen(s, "w"); 216 *infile = fdopen(s, "r"); 217 218 return (0); 219 } 220 221 #endif DAEMON 222