/* mailif.c by Michael Thorpe 2014-09-29 */ /* * THIS_IS_A_SANE_SYSTEM should be 1 for Linux and 0 * for OpenBSD. * * For other systems, test whether poll() on a closed fd says that fd is * ready to read; if if does, it's stupid like OpenBSD and * THIS_IS_A_SANE_SYSTEM needs to be 0. If it says the fd isn't ready to * read then THIS_IS_A_SANE_SYSTEM should be 1. * * If you're not sure, set it to 0. */ #define THIS_IS_A_SANE_SYSTEM 0 #if THIS_IS_A_SANE_SYSTEM #include #include int main(int argc,char **argv) { struct pollfd u; u.fd=0; u.events=POLLIN|POLLERR|POLLHUP|POLLNVAL; u.revents=0; poll(&u,1,-1); if(!(u.revents&POLLIN)) return(0); execvp("mail",argv); execvp("sendmail",argv); execv("/usr/sbin/sendmail",argv); execv("/usr/lib/sendmail",argv); return(-1); } #else #include #include #include #include #include #include static pid_t child=0; static FILE *out; static void stop_child() { pid_t p; int status; p=waitpid(child,&status,0); if(-1==p) { perror("waitpid"); exit(-1); } if(p != child) { fprintf(stderr,"Got exit value for non-child %d?!?\n",p); exit(-1); } if(WIFEXITED(status)) exit(WEXITSTATUS(status)); fputs("Child died\n",stderr); exit(-1); } static void start_child(char **argv) { int fds[2]; if(pipe(fds)) { perror("pipe"); exit(-1); } child=fork(); if(-1==child) { perror("fork"); exit(-1); } if(child) { close(fds[0]); out=fdopen(fds[1],"wb"); if(!out) { perror("fdopen"); exit(-1); } } else { close(fds[1]); if(fds[0]) { if(dup2(fds[0],0)) { perror("dup2"); exit(-1); } close(fds[0]); } execvp("mail",argv); execvp("sendmail",argv); execv("/usr/sbin/sendmail",argv); execv("/usr/lib/sendmail",argv); exit(-1); } } int main(int argc,char **argv) { int c; while(EOF != (c=fgetc(stdin))) { if(!child) start_child(argv); fputc(c,out); } if(child) { fclose(out); stop_child(); } return(0); } #endif