#include #include #include #include #include #include #include #include #include // 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); }