home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.shrubbery.net
/
2015-02-07.ftp.shrubbery.net.tar
/
ftp.shrubbery.net
/
pub
/
foad
/
foad-0.3.tar.gz
/
foad-0.3.tar
/
foad-0.3
/
foad.c
< prev
next >
Wrap
C/C++ Source or Header
|
2003-09-22
|
10KB
|
457 lines
#include "foad.h"
char version[] = "0.2";
#define FOADRC ".foadrc"
int debug = 0,
egrepbcc = 0,
egrepfrom = 0,
negate = 0,
testconf = 0;
char *foadrc,
*progname,
*c_bcc = NULL,
*c_from = NULL,
*c_cc = NULL,
*c_to = NULL;
struct s_addresses addresses,
bcc,
from,
cc,
to;
#if STDC_HEADERS
int main(int, char **);
int read_conf(char *);
void usage(void);
#endif
int
main(int argc, char **argv)
{
register int op;
char *home;
extern char *optarg;
extern int optind, opterr;
node *next;
if ((progname = strrchr(argv[0], '/')) != NULL)
progname++;
else
progname = argv[0];
while ((op = getopt(argc, argv, "bdfhntvc:")) != -1)
switch (op) {
case 'b':
++egrepbcc;
break;
case 'c': /* alt .foadrc */
foadrc = optarg;
break;
case 'd':
++debug;
break;
case 'f':
++egrepfrom;
break;
case 'n':
negate = 1;
break;
case 'v':
fprintf(stderr, "%s version %s\n", progname, version);
exit(0);
case 't':
++testconf;
break;
default:
usage();
}
if (foadrc == NULL) {
if ((home = getenv("HOME")) == NULL) {
fprintf(stderr, "%s: could not find $HOME in environment\n",
progname);
return(1 ^ negate);
}
if ((foadrc = (char *) malloc(strlen(home)+strlen(FOADRC)+2)) == NULL) {
fprintf(stderr, "%s: malloc failed: %s\n", progname,
strerror(errno));
return(1 ^ negate);
}
strcpy(foadrc, home); strcat(foadrc, "/"); strcat(foadrc, FOADRC);
}
if (debug)
fprintf(stderr, "\n%s: reading config file: %s\n", progname, foadrc);
if (read_conf(foadrc)) {
if (debug)
fprintf(stderr, "%s: config error: exit code %d\n\n",
progname, 1 ^ negate);
return(1 ^ negate);
}
if (testconf) { /* just read the .foadrc and exit */
if (debug) {
node *next = addresses.next;
fprintf(stderr, "%s: read the following regex's:\n", progname);
while (next) {
fprintf(stderr, "%s: \t%s\n", progname, next->addr);
next = next->next;
}
fprintf(stderr, "%s: exit code %d\n\n", progname, 0 ^ negate);
}
return(0 ^ negate);
}
if (read_header()) {
if (debug)
fprintf(stderr, "%s: header error: exit code %d\n\n",
progname, 1 ^ negate);
return(1 ^ negate);
}
if (debug) {
if (from.next) {
next = from.next;
fprintf(stderr, "%s: FROM: ", progname);
while (next) {
fprintf(stderr, "%s", next->addr);
next = next->next;
if (next)
fprintf(stderr, ",");
}
fprintf(stderr, "\n");
} else
fprintf(stderr, "%s: FROM: (null)\n", progname);
if (to.next) {
next = to.next;
fprintf(stderr, "%s: TO: ", progname);
while (next) {
fprintf(stderr, "%s", next->addr);
next = next->next;
if (next)
fprintf(stderr, ",");
}
fprintf(stderr, "\n");
} else
fprintf(stderr, "%s: TO: (null)\n", progname);
if (cc.next) {
next = cc.next;
fprintf(stderr, "%s: CC: ", progname);
while (next) {
fprintf(stderr, "%s", next->addr);
next = next->next;
if (next)
fprintf(stderr, ",");
}
fprintf(stderr, "\n");
} else
fprintf(stderr, "%s: CC: (null)\n", progname);
if (bcc.next) {
next = bcc.next;
fprintf(stderr, "%s: BCC: ", progname);
while (next) {
fprintf(stderr, "%s", next->addr);
next = next->next;
if (next)
fprintf(stderr, ",");
}
fprintf(stderr, "\n");
} else
fprintf(stderr, "%s: BCC: (null)\n", progname);
}
if (match()) {
if (debug)
fprintf(stderr, "%s: exit code %d\n\n", progname, 1 ^ negate);
return(1 ^ negate);
}
if (debug)
fprintf(stderr, "%s: exit code %d\n\n", progname, 0 ^ negate);
return(0 ^ negate);
}
/*
function: int read_conf(* foadrc)
description: read config file, ie: list of addresses
returns: non-zero on error
*/
int
read_conf(char *foadrc)
{
FILE *fp;
char buf[LINE_MAX];
int line = 0,
error = 0;
if ((fp = fopen(foadrc, "r")) == NULL) {
fprintf(stderr, "%s: could not open rc file %s: %s\n",
progname, foadrc, strerror(errno));
return(1);
}
do {
if (fgets(buf, LINE_MAX, fp) == NULL) {
if (feof(fp))
break;
fprintf(stderr, "%s: error reading %s line %d: %s\n", progname,
foadrc, line, strerror(errno));
error++; break;
}
line++;
if (strlen(buf) == LINE_MAX -1 && buf[LINE_MAX-1] != '\n') {
fprintf(stderr, "%s: %s: line %d exeeds max length of %d\n",
progname, foadrc, line, LINE_MAX);
error++; break;
}
if (*buf == '#')
continue;
error += dequote(buf);
if (add_addr(buf, line)) { error++; break; }
} while (1);
fclose(fp);
return(error);
}
/*
function: int add_addr(address)
description: add address to linked list
returns: non-zero on error
*/
int
add_addr(char *addr, int line)
{
node *next = addresses.next,
*new;
char errbuf[LINE_MAX] = "";
int errcode;
if (addr == NULL)
return(1);
if ((new = (node *) malloc(sizeof(node))) == NULL) {
fprintf(stderr, "%s: malloc failed: %s\n", progname, strerror(errno));
return(1);
}
bzero(new, sizeof(node));
new->line = line;
if ((new->addr = strdup(addr)) == NULL) {
fprintf(stderr, "%s: malloc failed: %s\n", progname, strerror(errno));
return(1);
}
if ((errcode = regcomp(&new->preg, new->addr,
REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
regerror(errcode, &new->preg, errbuf, LINE_MAX);
fprintf(stderr, "%s: regex compile failed for %s line %d: %s\n",
progname, foadrc, line, errbuf);
free(new->addr);
free(new);
return(1);
}
if (addresses.next == NULL)
addresses.next = new;
else
while (next) {
if (next->next == NULL) {
next->next = new; break;
}
next = next->next;
}
return(0);
}
/*
function: int dequote(string)
description: remove leading/trailing spaces from a string
returns: non-zero on error
*/
int
dequote(register char *s)
{
static regex_t *preg1, *preg2;
regmatch_t pmatch[2];
size_t nmatch = 2;
char buf[256];
int err;
if (s == NULL)
return(0);
if (!preg1) { /* remove trailing spaces */
if ((preg1 = malloc(sizeof(regex_t))) == NULL) {
fprintf(stderr, "%s: malloc failed: %s\n", progname,
strerror(errno));
return(1);
}
if ((err = regcomp(preg1, "([ \t]*)\n?$", REG_EXTENDED))) {
regerror(err, preg1, buf, 256);
fprintf(stderr, "%s: regex compile failed: %s\n", progname, buf);
return(1);
}
}
if ((err = regexec(preg1, s, nmatch, pmatch, 0))) {
if (err != REG_NOMATCH) {
regerror(err, preg1, buf, 256);
fprintf(stderr, "%s: regexec failed: %s\n", progname, buf);
}
return(1);
} else
*(s+ pmatch[1].rm_so) = '\0';
if (!preg2) { /* remove leading spaces */
if ((preg2 = malloc(sizeof(regex_t))) == NULL) {
fprintf(stderr, "%s: malloc failed: %s\n", progname,
strerror(errno));
return(1);
}
if ((err = regcomp(preg2, "^([ \t]*)", REG_EXTENDED))) {
regerror(err, preg2, buf, 256);
fprintf(stderr, "%s: regex compile failed: %s\n", progname, buf);
return(1);
}
}
if ((err = regexec(preg2, s, nmatch, pmatch, 0))) {
if (err != REG_NOMATCH) {
regerror(err, preg2, buf, 256);
fprintf(stderr, "%s: regexec failed: %s\n", progname, buf);
}
return(1);
} else
strcpy(s, s + pmatch[1].rm_eo);
return(0);
}
/*
function: int match()
description: match address against the to and cc (etc) until one matches or
we hit the end of the list.
returns: non-zero if there is a match, zero if no match
*/
int
match(void)
{
node *addr,
*h_addr;
/* if -f option and a from: header was found, match .foadrc entries */
if (egrepfrom && from.next) {
addr = addresses.next;
while (addr) {
if (debug)
fprintf(stderr, "%s: %s : ", progname, addr->addr);
if (listmatch(&addr->preg, &from)) {
if (debug)
fprintf(stderr, "%s: match from: %s\n", progname,
addr->addr);
return(1);
}
addr = addr->next;
}
}
/* match .foadrc entries against to: header, if one existed */
if (to.next) {
addr = addresses.next;
while (addr) {
if (debug)
fprintf(stderr, "%s: %s : ", progname, addr->addr);
if (listmatch(&addr->preg, &to)) {
if (debug)
fprintf(stderr, "%s: match to: %s\n", progname, addr->addr);
return(1);
}
addr = addr->next;
}
}
/* match .foadrc entries against cc: header, if one existed */
if (cc.next) {
addr = addresses.next;
while (addr) {
if (debug)
fprintf(stderr, "%s: %s : ", progname, addr->addr);
if (listmatch(&addr->preg, &cc)) {
if (debug)
fprintf(stderr, "%s: match cc: %s\n", progname, addr->addr);
return(1);
}
addr = addr->next;
}
}
/* if -b option and a bcc: header was found, match .foadrc entries */
if (egrepbcc && bcc.next) {
addr = addresses.next;
while (addr) {
if (debug)
fprintf(stderr, "%s: %s : ", progname, addr->addr);
if (listmatch(&addr->preg, &bcc)) {
if (debug)
fprintf(stderr, "%s: match bcc: %s\n", progname,
addr->addr);
return(1);
}
addr = addr->next;
}
}
if (debug)
fprintf(stderr, "%s: no match\n", progname);
return(0);
}
/*
function: int listmatch()
description: match .foadrc address against the elements of a linked list
from split mail headers (from/to/cc/bcc)
returns: non-zero if there is a match, zero if no match
*/
int
listmatch(regex_t *preg, s_addresses *list)
{
node *next = list->next;
while (next) {
/* use preg, compiled when .foadrc was read, for match */
if (!regexec(preg, next->addr, 0, NULL, 0)) {
if (debug)
fprintf(stderr, "%s\n", next->addr);
return(1);
}
next = next->next;
}
if (debug)
fprintf(stderr, "no match\n");
return(0);
}
void
usage(void)
{
fprintf(stderr, "usage: %s [-bhntv] [-c .foadrc]\n"
"\t-b egrep Bcc: and Resent-Bcc: headers\n"
"\t-c alternate .foadrc location (dflt: $HOME/%s)\n"
"\t-f egrep From: header\n"
"\t-h print this help msg\n"
"\t-n negate (complement of) exit code\n"
"\t-t read the $HOME/%s and exit non-zero on error\n"
"\t-v version info\n",
progname, FOADRC, FOADRC);
exit(1);
}