Commit 7368302e 7368302e1b04e367b2a9601ca73a602849707430 by Sam Roberts

State now tracks whether its been opened, rather than segving.

1 parent cede6707
...@@ -59,7 +59,7 @@ struct _sendmail ...@@ -59,7 +59,7 @@ struct _sendmail
59 pid_t pid; 59 pid_t pid;
60 off_t offset; 60 off_t offset;
61 int fd; 61 int fd;
62 enum sendmail_state { SENDMAIL_NO_STATE, SENDMAIL_SEND } state; 62 enum sendmail_state { SENDMAIL_CLOSED, SENDMAIL_OPEN, SENDMAIL_SEND } state;
63 }; 63 };
64 64
65 typedef struct _sendmail * sendmail_t; 65 typedef struct _sendmail * sendmail_t;
...@@ -78,7 +78,7 @@ _mailer_sendmail_init (mailer_t mailer) ...@@ -78,7 +78,7 @@ _mailer_sendmail_init (mailer_t mailer)
78 sendmail = mailer->data = calloc (1, sizeof (*sendmail)); 78 sendmail = mailer->data = calloc (1, sizeof (*sendmail));
79 if (mailer->data == NULL) 79 if (mailer->data == NULL)
80 return ENOMEM; 80 return ENOMEM;
81 sendmail->state = SENDMAIL_NO_STATE; 81 sendmail->state = SENDMAIL_CLOSED;
82 mailer->_destroy = sendmail_destroy; 82 mailer->_destroy = sendmail_destroy;
83 mailer->_open = sendmail_open; 83 mailer->_open = sendmail_open;
84 mailer->_close = sendmail_close; 84 mailer->_close = sendmail_close;
...@@ -134,6 +134,7 @@ sendmail_open (mailer_t mailer, int flags) ...@@ -134,6 +134,7 @@ sendmail_open (mailer_t mailer, int flags)
134 return errno; 134 return errno;
135 } 135 }
136 sendmail->path = path; 136 sendmail->path = path;
137 sendmail->state = SENDMAIL_OPEN;
137 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE, "sendmail (%s)\n", sendmail->path); 138 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE, "sendmail (%s)\n", sendmail->path);
138 return 0; 139 return 0;
139 } 140 }
...@@ -141,12 +142,24 @@ sendmail_open (mailer_t mailer, int flags) ...@@ -141,12 +142,24 @@ sendmail_open (mailer_t mailer, int flags)
141 static int 142 static int
142 sendmail_close (mailer_t mailer) 143 sendmail_close (mailer_t mailer)
143 { 144 {
144 (void)mailer; 145 sendmail_t sendmail = mailer->data;
146
147 /* Sanity checks. */
148 if (sendmail == NULL)
149 return EINVAL;
150
151 if(sendmail->path)
152 free(sendmail->path);
153
154 sendmail->path = NULL;
155 sendmail->state = SENDMAIL_CLOSED;
156
145 return 0; 157 return 0;
146 } 158 }
147 159
148 static int 160 static int
149 sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t to) 161 sendmail_send_message (mailer_t mailer, message_t msg, address_t from,
162 address_t to)
150 { 163 {
151 sendmail_t sendmail = mailer->data; 164 sendmail_t sendmail = mailer->data;
152 int status = 0; 165 int status = 0;
...@@ -156,7 +169,9 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -156,7 +169,9 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
156 169
157 switch (sendmail->state) 170 switch (sendmail->state)
158 { 171 {
159 case SENDMAIL_NO_STATE: 172 case SENDMAIL_CLOSED:
173 return EINVAL;
174 case SENDMAIL_OPEN:
160 { 175 {
161 int tunnel[2]; 176 int tunnel[2];
162 int argc = 0; 177 int argc = 0;
...@@ -173,7 +188,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -173,7 +188,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
173 if (from) 188 if (from)
174 { 189 {
175 if ((status = address_aget_email (from, 1, &emailfrom)) != 0) 190 if ((status = address_aget_email (from, 1, &emailfrom)) != 0)
176 goto NO_STATE_CLEANUP; 191 goto OPEN_STATE_CLEANUP;
177 192
178 if (!emailfrom) 193 if (!emailfrom)
179 { 194 {
...@@ -181,9 +196,10 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -181,9 +196,10 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
181 status = EINVAL; 196 status = EINVAL;
182 197
183 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE, 198 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE,
184 "envelope from (%s) not fully qualifed\n", emailfrom); 199 "envelope from (%s) not fully qualifed\n",
200 emailfrom);
185 201
186 goto NO_STATE_CLEANUP; 202 goto OPEN_STATE_CLEANUP;
187 } 203 }
188 204
189 argc += 2; /* -f from */ 205 argc += 2; /* -f from */
...@@ -206,7 +222,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -206,7 +222,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
206 if ((argvec = calloc (argc, sizeof (*argvec))) == 0) 222 if ((argvec = calloc (argc, sizeof (*argvec))) == 0)
207 { 223 {
208 status = ENOMEM; 224 status = ENOMEM;
209 goto NO_STATE_CLEANUP; 225 goto OPEN_STATE_CLEANUP;
210 } 226 }
211 227
212 argc = 0; 228 argc = 0;
...@@ -214,20 +230,20 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -214,20 +230,20 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
214 if ((argvec[argc++] = strdup (sendmail->path)) == 0) 230 if ((argvec[argc++] = strdup (sendmail->path)) == 0)
215 { 231 {
216 status = ENOMEM; 232 status = ENOMEM;
217 goto NO_STATE_CLEANUP; 233 goto OPEN_STATE_CLEANUP;
218 } 234 }
219 235
220 if ((argvec[argc++] = strdup ("-oi")) == 0) 236 if ((argvec[argc++] = strdup ("-oi")) == 0)
221 { 237 {
222 status = ENOMEM; 238 status = ENOMEM;
223 goto NO_STATE_CLEANUP; 239 goto OPEN_STATE_CLEANUP;
224 } 240 }
225 if (from) 241 if (from)
226 { 242 {
227 if ((argvec[argc++] = strdup ("-f")) == 0) 243 if ((argvec[argc++] = strdup ("-f")) == 0)
228 { 244 {
229 status = ENOMEM; 245 status = ENOMEM;
230 goto NO_STATE_CLEANUP; 246 goto OPEN_STATE_CLEANUP;
231 } 247 }
232 argvec[argc++] = emailfrom; 248 argvec[argc++] = emailfrom;
233 } 249 }
...@@ -236,7 +252,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -236,7 +252,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
236 if ((argvec[argc++] = strdup ("-t")) == 0) 252 if ((argvec[argc++] = strdup ("-t")) == 0)
237 { 253 {
238 status = ENOMEM; 254 status = ENOMEM;
239 goto NO_STATE_CLEANUP; 255 goto OPEN_STATE_CLEANUP;
240 } 256 }
241 } 257 }
242 else 258 else
...@@ -250,16 +266,17 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -250,16 +266,17 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
250 { 266 {
251 char *email = 0; 267 char *email = 0;
252 if ((status = address_aget_email (to, i, &email)) != 0) 268 if ((status = address_aget_email (to, i, &email)) != 0)
253 goto NO_STATE_CLEANUP; 269 goto OPEN_STATE_CLEANUP;
254 if (!email) 270 if (!email)
255 { 271 {
256 /* the address wasn't fully qualified, choke (for now) */ 272 /* the address wasn't fully qualified, choke (for now) */
257 status = EINVAL; 273 status = EINVAL;
258 274
259 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE, 275 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE,
260 "envelope to (%s) not fully qualifed\n", email); 276 "envelope to (%s) not fully qualifed\n",
277 email);
261 278
262 goto NO_STATE_CLEANUP; 279 goto OPEN_STATE_CLEANUP;
263 } 280 }
264 argvec[argc++] = email; 281 argvec[argc++] = email;
265 } 282 }
...@@ -286,17 +303,17 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -286,17 +303,17 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
286 status = errno; 303 status = errno;
287 304
288 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE, 305 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE,
289 "vfork() failed: %s\n", strerror(status)); 306 "vfork() failed: %s\n", strerror (status));
290 } 307 }
291 } 308 }
292 else 309 else
293 { 310 {
294 status = errno; 311 status = errno;
295 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE, 312 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE,
296 "pipe() failed: %s\n", strerror(status)); 313 "pipe() failed: %s\n", strerror (status));
297 } 314 }
298 315
299 NO_STATE_CLEANUP: 316 OPEN_STATE_CLEANUP:
300 MAILER_DEBUG0 (mailer, MU_DEBUG_TRACE, "exec argv:"); 317 MAILER_DEBUG0 (mailer, MU_DEBUG_TRACE, "exec argv:");
301 for (argc = 0; argvec && argvec[argc]; argc++) 318 for (argc = 0; argvec && argvec[argc]; argc++)
302 { 319 {
...@@ -315,7 +332,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -315,7 +332,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
315 sendmail->state = SENDMAIL_SEND; 332 sendmail->state = SENDMAIL_SEND;
316 } 333 }
317 334
318 case SENDMAIL_SEND: /* Parent. */ 335 case SENDMAIL_SEND:
319 { 336 {
320 stream_t stream = NULL; 337 stream_t stream = NULL;
321 char buffer[512]; 338 char buffer[512];
...@@ -332,7 +349,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -332,7 +349,7 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
332 status = errno; 349 status = errno;
333 350
334 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE, 351 MAILER_DEBUG1 (mailer, MU_DEBUG_TRACE,
335 "write() failed: %s\n", strerror(status)); 352 "write() failed: %s\n", strerror (status));
336 353
337 break; 354 break;
338 } 355 }
...@@ -340,21 +357,24 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -340,21 +357,24 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
340 } 357 }
341 if (status == EAGAIN) 358 if (status == EAGAIN)
342 return status; 359 return status;
360
343 close (sendmail->fd); 361 close (sendmail->fd);
362
344 rc = waitpid (sendmail->pid, &status, 0); 363 rc = waitpid (sendmail->pid, &status, 0);
364
345 if (rc < 0) 365 if (rc < 0)
346 { 366 {
347 status = errno; 367 status = errno;
348 MAILER_DEBUG2 (mailer, MU_DEBUG_TRACE, 368 MAILER_DEBUG2 (mailer, MU_DEBUG_TRACE,
349 "waitpid(%d) failed: %s\n", 369 "waitpid(%d) failed: %s\n",
350 sendmail->pid, strerror(status)); 370 sendmail->pid, strerror (status));
351 } 371 }
352 else if (WIFEXITED (status)) 372 else if (WIFEXITED (status))
353 { 373 {
354 status = WEXITSTATUS (status); 374 status = WEXITSTATUS (status);
355 MAILER_DEBUG2 (mailer, MU_DEBUG_TRACE, 375 MAILER_DEBUG2 (mailer, MU_DEBUG_TRACE,
356 "%s exited with: %s\n", 376 "%s exited with: %s\n",
357 sendmail->path, strerror(status)); 377 sendmail->path, strerror (status));
358 } 378 }
359 /* Shouldn't this notification only happen on success? */ 379 /* Shouldn't this notification only happen on success? */
360 observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT); 380 observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT);
...@@ -363,6 +383,9 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t ...@@ -363,6 +383,9 @@ sendmail_send_message (mailer_t mailer, message_t msg, address_t from, address_t
363 break; 383 break;
364 } 384 }
365 385
366 sendmail->state = SENDMAIL_NO_STATE; 386 sendmail->state = SENDMAIL_OPEN;
387
367 return status; 388 return status;
368 } 389 }
390
391
......