/***************************************************************************
*
* Copyright 2008 by Sean Conner.
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Comments, questions and criticisms can be sent to: sean@conman.org
*
*************************************************************************/
/****************************************************************
*
* Wrapper program for sendmail for PHP under Apache (may work
* on other webservers, but untested).
*
* To compile:
*
* You'll need to install my cgilib, available at
* http://www.conman.org/software/cgilib/cgilib.tar.gz
*
* Then:
*
* gcc -Wall -ansi -pedantic -o wrapper wrapper.c -lcgi5
*
* Copy the wrapper program somewhere where Apache can execute it,
* then modify /etc/php.ini:
*
* ; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
* ; sendmail_path = /usr/sbin/sendmail -t -i
* sendmail_path = /path/to/wrapper -t -i
*
* Restart Apache, and Bob's your uncle.
*
* The wrapper logs information to syslog using the LOG_LOCAL4 facility,
* so you may want to check /etc/syslog.conf to make sure you're
* logging local4.info (at least) somewhere.
*
******************************************************************/
/********************************************************************
*
* This program was brought to you by a grant from Pick Internet [1], and
* by a grant from HarmonyLogic [2]. Also, by the number 10.
*
* [1] http://www.pickint.net/
* [2] http://www.harmonylogic.com/
*
********************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*******************************************************/
int main(int argc,char *argv[],char *envp[])
{
List headers;
Stream tmp;
char *hostname;
char *workdir;
char *to;
char *cc;
char *bcc;
int rc;
pid_t child;
char tmpfile[BUFSIZ];
int fhin;
MemInit();
DdtInit();
StreamInit();
openlog("smw",0,LOG_LOCAL4);
/*---------------------------------------------------------
; copy STDIN to a file. This copy is used twice, once
; to read the headers, then again when we fork() to
; sendmail.
;--------------------------------------------------------*/
sprintf(tmpfile,"/tmp/wrapper.%lu",(unsigned long)getpid());
tmp = FileStreamWrite(tmpfile,FILE_CREATE | FILE_TRUNCATE);
StreamCopy(tmp,StdinStream);
StreamFree(tmp);
/*----------------------------------------------------
; read in the headers from the email we're sending
;----------------------------------------------------*/
tmp = FileStreamRead(tmpfile);
ListInit(&headers);
RFC822HeadersRead(tmp,&headers);
StreamFree(tmp);
hostname = spc_getenv("HOSTNAME");
workdir = spc_getenv("PWD");
to = PairListGetValue(&headers,"TO");
cc = PairListGetValue(&headers,"CC");
bcc = PairListGetValue(&headers,"BCC");
syslog(
LOG_INFO,
"H: %s W: %s To: %s Cc: %s Bcc: %s",
hostname,
workdir,
to,
cc,
bcc
);
/*--------------------------------------------------
; we open the file for read mode---this file then
; becomes STDIN for sendmail when we fork()/exec() it
;----------------------------------------------------*/
fhin = open(tmpfile,O_RDONLY);
if (fhin == -1)
{
syslog(LOG_CRIT,"open(%s,READ) = %s",tmpfile,strerror(errno));
exit(EXIT_FAILURE);
}
child = fork();
if (child == (pid_t)-1)
{
syslog(LOG_CRIT,"fork() = %s",strerror(errno));
exit(EXIT_FAILURE);
}
if (child == 0) /* child process */
{
char **newargv;
int i;
/*--------------------------------------------------
; while argv[] is writable on Linux, it may not be
; on other systems, so just in case, we copy the
; array, so we can swap out the name of the program
; in argv[0]
;-------------------------------------------------*/
newargv = MemAlloc(sizeof(char *) * (argc + 1));
newargv[0] = "sendmail";
for (i = 1 ; i < argc ; i++)
newargv[i] = argv[i];
newargv[i] = NULL;
/*-----------------------------------------------
; set STDIN to our file, then fork() away
;-----------------------------------------------*/
dup2(fhin,STDIN_FILENO);
rc = execve("/usr/sbin/sendmail",newargv,envp);
syslog(LOG_CRIT,"execve() = %s",strerror(errno));
exit(EXIT_FAILURE);
}
else /* parent process */
{
pid_t cstat;
int status;
cstat = waitpid(child,&status,0);
if (WIFEXITED(status))
rc = WEXITSTATUS(status);
else
rc = EXIT_FAILURE;
unlink(tmpfile); /* make sure we clean up after ourselves */
exit(rc);
}
}