Download | Plain Text | Line Numbers
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
// gcc -std=c99
static char *sendmail = "/var/qmail/bin/sendmail";
int fd_copy(int to, int from)
{
if (to == from)
return 0;
if (fcntl(from, F_GETFL, 0) == -1)
return -1;
close(to);
if (fcntl(from, F_DUPFD, to) == -1)
return -1;
return 0;
}
void sig_catch(int sig, void (*f)())
{
#ifdef HASSIGACTION
struct sigaction sa;
sa.sa_handler = f;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(sig, &sa, (struct sigaction *)0);
#else
signal(sig, f);
#endif
}
int wait_pid(int *wstat, int pid)
{
int r;
do
r = waitpid(pid, wstat, 0);
while (r == -1 && errno == EINTR);
return r;
}
int main(int argc, char *argv[])
{
for(int i = 0; i < argc; i++)
{
if (!strcmp(argv[i], "<>"))
argv[i][0] = '\0';
}
argv[0] = sendmail;
int pi[2], pid;
if (pipe(pi) == -1)
{
fprintf(stderr, "sendmail: unable to open pipe\n");
exit(100);
}
switch(pid = fork())
{
case -1:
fprintf(stderr, "sendmail: unable to fork\n");
exit(100);
case 0:
close(pi[1]);
if (fd_copy(0, pi[0]) == -1)
{
fprintf(stderr, "sendmail: unable to copy pipe to stdin\n");
exit(100);
}
sig_catch(SIGPIPE, SIG_DFL);
execv(argv[0], argv);
fprintf(stderr, "sendmail: unable to run sendmail\n");
exit(111);
}
close(pi[0]);
char *r, buf[255];
while(r = fgets(buf, sizeof(buf), stdin))
{
if (ferror(stdin))
{
fprintf(stderr, "sendmail: error while readin stdin: %s\n",
strerror(fileno(stdin)));
exit(111);
}
int len = strlen(buf);
if (len >= 2 && buf[len - 2] == '\r' && buf[len - 1] == '\n')
{
buf[len - 2] = buf[len - 1];
buf[len - 1] = '\0';
len--;
}
write(pi[1], buf, len);
if (feof(stdin))
break;
}
close(pi[1]);
int wstat;
if (wait_pid(&wstat, pid) == -1)
exit(111);
exit(wstat >> 8);
}