#include "common.h"
#include "send.h"
Biobuf bin;
int rmail, tflg;
char *subjectarg;
char *findbody(char*);
void
main(int argc, char *argv[])
{
message *mp;
dest *dp;
Reprog *p;
Resub match[10];
char file[MAXPATHLEN];
Biobuf *fp;
char *rcvr, *cp;
Mlock *l;
String *tmp;
int i;
int header, body;
header = body = 0;
ARGBEGIN {
case 'h':
header = 1;
break;
case 'b':
header = 1;
body = 1;
break;
} ARGEND
Binit(&bin, 0, OREAD);
if(argc < 2){
fprint(2, "usage: filter rcvr mailfile [regexp mailfile ...]\n");
exits("usage");
}
mp = m_read(&bin, 1, 0);
/* get rid of local system name */
cp = strchr(s_to_c(mp->sender), '!');
if(cp){
cp++;
mp->sender = s_copy(cp);
}
dp = d_new(s_copy(argv[0]));
strecpy(file, file+sizeof file, argv[1]);
cp = findbody(s_to_c(mp->body));
for(i = 2; i < argc; i += 2){
p = regcomp(argv[i]);
if(p == 0)
continue;
if(regexec(p, s_to_c(mp->sender), match, 10)){
regsub(argv[i+1], file, sizeof(file), match, 10);
break;
}
if(header == 0 && body == 0)
continue;
if(regexec(p, s_to_c(mp->body), match, 10)){
if(body == 0 && match[0].sp >= cp)
continue;
regsub(argv[i+1], file, sizeof(file), match, 10);
break;
}
}
/*
* always lock the normal mail file to avoid too many lock files
* lying about. This isn't right but it's what the majority prefers.
*/
l = syslock(argv[1]);
if(l == 0){
fprint(2, "can't lock mail file %s\n", argv[1]);
exit(1);
}
/*
* open the destination mail file
*/
fp = sysopen(file, "ca", MBOXMODE);
if (fp == 0){
tmp = s_append(0, file);
s_append(tmp, ".tmp");
fp = sysopen(s_to_c(tmp), "cal", MBOXMODE);
if(fp == 0){
sysunlock(l);
fprint(2, "can't open mail file %s\n", file);
exit(1);
}
syslog(0, "mail", "error: used %s", s_to_c(tmp));
s_free(tmp);
}
Bseek(fp, 0, 2);
if(m_print(mp, fp, (char *)0, 1) < 0
|| Bprint(fp, "\n") < 0
|| Bflush(fp) < 0){
sysclose(fp);
sysunlock(l);
fprint(2, "can't write mail file %s\n", file);
exit(1);
}
sysclose(fp);
sysunlock(l);
rcvr = argv[0];
if(cp = strrchr(rcvr, '!'))
rcvr = cp+1;
logdelivery(dp, rcvr, mp);
exit(0);
}
char*
findbody(char *p)
{
if(*p == '\n')
return p;
while(*p){
if(*p == '\n' && *(p+1) == '\n')
return p+1;
p++;
}
return p;
}
|