Mercurial > dovecot > original-hg > dovecot-1.2
view src/deliver/smtp-client.c @ 7086:7ed926ed7aa4 HEAD
Updated copyright notices to include year 2008.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 01 Jan 2008 22:05:21 +0200 |
parents | 65c69a53a7be |
children | db0d0d7385fd |
line wrap: on
line source
/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "deliver.h" #include "smtp-client.h" #include <unistd.h> #include <sys/wait.h> struct smtp_client { FILE *f; pid_t pid; }; static struct smtp_client *smtp_client_devnull(FILE **file_r) { struct smtp_client *client; client = i_new(struct smtp_client, 1); client->f = *file_r = fopen("/dev/null", "w"); if (client->f == NULL) i_fatal("fopen() failed: %m"); client->pid = (pid_t)-1; return client; } static void ATTR_NORETURN smtp_client_run_sendmail(const char *destination, const char *return_path, int fd) { const char *argv[7], *sendmail_path; /* deliver_set's contents may point to environment variables. deliver_env_clean() cleans them up, so they have to be copied. */ sendmail_path = t_strdup(deliver_set->sendmail_path); argv[0] = sendmail_path; argv[1] = "-i"; /* ignore dots */ argv[2] = "-f"; argv[3] = return_path != NULL && *return_path != '\0' ? return_path : "<>"; argv[4] = "--"; argv[5] = destination; argv[6] = NULL; if (dup2(fd, STDIN_FILENO) < 0) i_fatal("dup2() failed: %m"); deliver_env_clean(); (void)execv(sendmail_path, (void *)argv); i_fatal("execv(%s) failed: %m", sendmail_path); } struct smtp_client *smtp_client_open(const char *destination, const char *return_path, FILE **file_r) { struct smtp_client *client; int fd[2]; pid_t pid; if (pipe(fd) < 0) { i_error("pipe() failed: %m"); return smtp_client_devnull(file_r); } if ((pid = fork()) == (pid_t)-1) { i_error("fork() failed: %m"); (void)close(fd[0]); (void)close(fd[1]); return smtp_client_devnull(file_r); } if (pid == 0) { /* child */ (void)close(fd[1]); smtp_client_run_sendmail(destination, return_path, fd[0]); } (void)close(fd[0]); client = i_new(struct smtp_client, 1); client->f = *file_r = fdopen(fd[1], "w"); if (client->f == NULL) i_fatal("fdopen() failed: %m"); return client; } int smtp_client_close(struct smtp_client *client) { int ret = EX_TEMPFAIL, status; fclose(client->f); if (client->pid == (pid_t)-1) { /* smtp_client_open() failed already */ } else if (waitpid(client->pid, &status, 0) < 0) i_error("waitpid() failed: %m"); else if (WIFEXITED(status)) { ret = WEXITSTATUS(status); if (ret != 0) { i_error("Sendmail process terminated abnormally, " "exit status %d", ret); } } else if (WIFSIGNALED(status)) { i_error("Sendmail process terminated abnormally, " "signal %d", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { i_error("Sendmail process stopped, signal %d", WSTOPSIG(status)); } else { i_error("Sendmail process terminated abnormally, " "return status %d", status); } i_free(client); return ret; }