Commit 6366c5c6 6366c5c6ed8ae63ed3578610729de531d33a03fa by Sam Roberts

Initial commit of the port of CMU's sieve engine. It builds, and some

actions work, but has seen very little use.
1 parent fcc8b0cb
gram-sieve.tab.c
Makefile
Makefile.in
addr.c
addr.h
sieve-gram.c
sieve-gram.h
addr-lex.c
sieve-lex.c
.deps
.libs
sieve
test
_*
Larry Greenfield <leg+sieve@andrew.cmu.edu> wrote the first pass.
Alexy Melnikov <mel@taxxi.com> submitted some bug fixes and improvements.
Ken Murchison <ken@oceana.com> took the ball, added more extensions
than existed in the known world, and overall improved the code mightily.
/* cmu-sieve
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1998 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
CFLAGS = -Wall -pedantic -g -DTESTING
INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/lib
MOSTLYCLEANFILES=
CLEANFILES=
DISTCLEANFILES=
MAINTAINERCLEANFILES=\
sieve-gram.c sieve-gram.h \
sieve-lex.c \
addr-lex.c \
addr.c addr.h
bin_PROGRAMS = test sieve
SRC = \
addr-lex.c \
addr.c \
comparator.c \
imparse.c \
interp.c \
md5.c \
message.c \
parseaddr.c \
script.c \
sieve-lex.c \
sieve-gram.c \
sieve_err.c \
svfield.c \
tree.c \
util.c \
xmalloc.c
test_DEPENDENCIES =
test_LDADD =
test_SOURCES = \
test.c \
${SRC}
sieve_DEPENDENCIES = ../mailbox/libmailbox.la
sieve_LDADD = ../mailbox/libmailbox.la ../lib/libmailutils.a
sieve_SOURCES = \
sieve.c \
${SRC}
YACC = bison -y
YFLAGS = -d
LEX = flex
addr-lex.c: addr-lex.l addr.h
$(LEX) -t -Paddr addr-lex.l > $@
addr.c addr.h: addr.y
$(YACC) $(YFLAGS) -p addr addr.y
mv -f y.tab.c addr.c
mv -f y.tab.h addr.h
sieve-lex.c: sieve-lex.l sieve-gram.h
$(LEX) -t sieve-lex.l > $@
sieve-gram.c sieve-gram.h: sieve-gram.y
$(YACC) $(YFLAGS) sieve-gram.y
mv -f y.tab.c sieve-gram.c
mv -f y.tab.h sieve-gram.h
comparator.o: sieve-gram.h
script.o: sieve-gram.h
tree.o: sieve-gram.h
$Id$
CMU Sieve 2.0
-------------
- Compliant with draft-showalter-sieve-11.txt and
draft-showalter-sieve-vacation-03.txt.
- Added support for the regex, imapflags, notify and subaddress extensions.
See README for references.
- Verifies email addresses in redirect and vacation actions are syntactically
correct (compliant with RFC822).
- Run-time error reporting.
- Changed callback interface to use callback contexts instead of individual
parameters. Also added an error string buffer for run-time error reporting.
- Vacation will not reply to any message containing an "auto-submitted"
header containing anything other than "no".
CMU Sieve 1.4
-------------
Now included with imapd distribution (hell, why not?).
Error returning and recovering:
added error recovering to the parser (but not much!)
added error messages to the parser
Working on error returning and error recovering.
run-time errors
detect some errors in lexer?
Working on even better parsing:
verify addresses could be addresses
verify mailboxes could be mailboxes
verify outgoing headers can be headers
CMU Sieve 1.3
-------------
Changed for integration with cyrus deliver.
CMU Sieve 1.2
-------------
Added additional callbacks (ok, so I want to make my integration with deliver
easier) and envelope and vacation support.
Made it compile without libcyrus.
It should compile without libcyrus, but then it does not implement the
"address" test. That's just too much work to do when I have a neato
library to do it for me.
Todo:
- regex matching
CMU Sieve 1.1
-------------
- Updated to draft-showalter-sieve-07bis.txt
- Simple API (see sieve_interface.h; currently mostly undocumented)
- Implements all of the optional features except "envelope"
- Maintains "if it parses, it probably runs" behavior. (Goal: minimize
run-time errors.)
CMU Sieve 1.0
-------------
- prototype implementation
$Id$
CMU Sieve 2.0
-------------
This code is typically distributed as part of Cyrus imapd 1.6 and higher.
This code will be configured and compiled from the cyrus-imapd directory.
Notes on implementation
-----------------------
This is an implementation of a simple Sieve API. This API is
well-suited for incorporating in other programs, but is not
extensible. (If there is interest, we may implement an extensible API
in the future.)
If you wish to compile Sieve without compiling all of imapd, you'll
have to create a Makefile for it. I recommend you use Makefile.in as
a guide.
It should compile without libcyrus, but then it does not implement the
"address" test. That's just too much work to do when I have a neato
library to do it for me.
There's a simple "test" application included, which is not built by
default (type "make test" to build it). It expects:
test <message> <script>
And prints out the actions taken or errors encountered. (This
implementation will attempt all the actions or no actions.)
Questions and comments to:
Larry Greenfield (leg+sieve@andrew.cmu.edu)
References:
[SIEVE] Showalter, T., "Sieve: A Mail Filtering Language",
draft-showalter-sieve-11.txt, May, 2000.
[VACATION] Showalter, T., "Sieve: Vacation Extension",
draft-showalter-sieve-vacation-03.txt, May, 2000.
[IMAPFLAGS] Melnikov, A., "Sieve -- IMAP flag extension",
draft-melnikov-sieve-imapflags-02.txt, June, 1999.
[NOTIFY] Martin, T., "Sieve -- An extension for providing instant
notifications", draft-ietf-sieve-notify-00.txt, February, 2000.
[REGEX] Murchison, K., "Sieve: Regular Expression Extension",
draft-murchison-sieve-regex-01.txt, March, 2000.
[SUBADDR] Murchison, K., "Sieve: Subaddress Extension",
draft-murchison-sieve-subaddress-00.txt, March, 2000.
%{
/*
* addr-lex.l -- RFC 822 address lexer
*/
#include "addr.h"
#include <string.h>
#undef YY_INPUT
#define YY_INPUT(b, r, ms) (r = addrinput(b, ms))
int addrinput(char *buf, int max_size);
void addrerror(const char *);
static int ncom; /* number of open comments */
%}
%option noyywrap
%x QSTRING DOMAINLIT COMMENT
%%
\" { BEGIN QSTRING; return yytext[0]; }
\[ { BEGIN DOMAINLIT; return yytext[0]; }
\( { ncom = 1; BEGIN COMMENT; }
\) { addrerror("address parse error, "
"unexpected `')'' "
"(unbalanced comment)");
yyterminate(); }
[^\(\)<>@,;:\\".\[\] \n\r]+ return ATOM;
[\t \n\r]+ /* ignore whitespace */
. return yytext[0];
<QSTRING>([^\n\r"\\]|\\.)* return QTEXT;
<QSTRING>\" { BEGIN INITIAL; return yytext[0]; }
<DOMAINLIT>([^\[\]\n\r\\]|\\.)* return DTEXT;
<DOMAINLIT>\] { BEGIN INITIAL; return yytext[0]; }
<COMMENT>([^\(\)\n\0\\]|\\.)* /* ignore comments */
<COMMENT>\( ncom++;
<COMMENT>\) { ncom--; if (ncom == 0) BEGIN INITIAL; }
<COMMENT><<EOF>> { addrerror("address parse error, "
"expecting `')'' "
"(unterminated comment)");
yyterminate(); }
%%
/* take input from address string provided by sieve parser */
int addrinput(char *buf, int max_size)
{
extern char *addrptr; /* current position in address string */
int n; /* number of characters to read from string */
n = strlen(addrptr) < max_size ? strlen(addrptr) : max_size;
if (n > 0) {
memcpy(buf, addrptr, n);
addrptr += n;
}
return n;
}
%{
/*
* addr.y -- RFC 822 address parser
*/
#include <stdlib.h>
#include <string.h>
#include "addr.h"
int yyerror(char *msg);
extern int yylex(void);
#define yyparse addrparse
#define yyerror addrerror
#define YYERROR_VERBOSE /* i want better error messages! */
%}
%token ATOM QTEXT DTEXT
%start sieve_address
%%
address: mailbox /* one addressee */
| group /* named list */
;
group: phrase ':' ';'
| phrase ':' mailboxes ';'
;
mailboxes: mailbox
| mailbox ',' mailboxes
;
mailbox: addrspec /* simple address */
| phrase routeaddr /* name & addr-spec */
;
routeaddr: '<' addrspec '>'
| '<' route ':' addrspec '>'
;
route: '@' domain /* path-relative */
| '@' domain ',' route
;
sieve_address: addrspec /* simple address */
| phrase '<' addrspec '>' /* name & addr-spec */
;
addrspec: localpart '@' domain /* global-address */
;
localpart: word /* uninterpreted, case-preserved */
| word '.' localpart
;
domain: subdomain
| subdomain '.' domain
;
subdomain: domainref
| domainlit
;
domainref: ATOM /* symbolic reference */
;
domainlit: '[' DTEXT ']'
;
phrase: word
| word phrase
;
word: ATOM
| qstring
;
qstring: '"' QTEXT '"'
;
%%
/* copy address error message into buffer provided by sieve parser */
int yyerror(char *s)
{
extern char addrerr[];
strcpy(addrerr, s);
return 0;
}
/* comparator.c -- comparator functions
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <fnmatch.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "comparator.h"
#include "tree.h"
#include "sieve-gram.h"
/* --- i;octet comparators --- */
/* just compare the two; these should be NULL terminated */
static int octet_is(const char *pat, const char *text)
{
int sl;
sl = strlen(pat);
return (sl == strlen(text)) && !memcmp(pat, text, sl);
}
/* we implement boyer-moore for hell of it, since this is probably
not very useful for sieve */
#if 0
int boyer_moore(char *pat, char *text)
{
int i, j; /* indexes */
int M = strlen(pat); /* length of pattern */
int N = strlen(text); /* length of text */
int skip[256]; /* table of how much to skip, based on each character */
/* initialize skip table */
for (i = 0; i < 256; i++)
skip[i] = M;
for (i = 0; i < M; i++)
skip[(int) pat[i]] = M-i-1;
/* look for pat in text */
i = j = M-1;
do {
if (pat[j] == text[i]) {
i--;
j--;
} else {
if (M-j > skip[(int) text[i]]) {
i = i + M - j;
} else {
i = i + skip[(int) text[i]];
}
j = M-1;
}
} while (!((j < 0) || (i >= N)));
/* i+1 is the position of the match if i < N */
return (i < N) ? 1 : 0;
}
#endif
/* we do a brute force attack */
static int octet_contains(const char *pat, const char *text)
{
return (strstr(text, pat) != NULL);
}
static int octet_matches(const char *pat, const char *text)
{
return !fnmatch(pat, text, 0);
}
#ifdef ENABLE_REGEX
static int octet_regex(const char *pat, const char *text)
{
return (!regexec((regex_t *) pat, text, 0, NULL, 0));
}
#endif
/* --- i;ascii-casemap comparators --- */
static int ascii_casemap_is(const char *pat, const char *text)
{
int sl;
sl = strlen(pat);
return (sl == strlen(text)) && !strncasecmp(pat, text, sl);
}
/* sheer brute force */
static int ascii_casemap_contains(const char *pat, const char *text)
{
int N = strlen(text);
int M = strlen(pat);
int i, j;
i = 0, j = 0;
while ((j < M) && (i < N)) {
if (toupper(text[i]) == toupper(pat[j])) {
i++; j++;
} else {
i = i - j + 1;
j = 0;
}
}
return (j == M); /* we found a match! */
}
static int ascii_casemap_matches(const char *pat, const char *text)
{
int ret;
char *p, *t;
int i;
/* sigh, i'll just make local copies of these guys */
p = strdup(pat); t = strdup(text);
for (i = 0; p[i] != '\0'; i++)
p[i] = toupper(p[i]);
for (i = 0; t[i] != '\0'; i++)
t[i] = toupper(t[i]);
ret = !fnmatch(p, t, 0);
free(p); free(t);
return ret;
}
/* i;ascii-numeric; only supports "is"
equality: numerically equal, or both not numbers */
static int ascii_numeric_is(const char *pat, const char *text)
{
if (isdigit((int) *pat)) {
if (isdigit((int) *text)) {
return (atoi(pat) == atoi(text));
} else {
return 0;
}
} else if (isdigit((int) *text)) return 0;
else return 1; /* both not digits */
}
comparator_t *lookup_comp(const char *comp, int mode)
{
comparator_t *ret;
ret = NULL;
if (!strcmp(comp, "i;octet")) {
switch (mode) {
case IS:
ret = &octet_is;
break;
case CONTAINS:
ret = &octet_contains;
break;
case MATCHES:
ret = &octet_matches;
break;
#ifdef ENABLE_REGEX
case REGEX:
ret = &octet_regex;
break;
#endif
}
} else if (!strcmp(comp, "i;ascii-casemap")) {
switch (mode) {
case IS:
ret = &ascii_casemap_is;
break;
case CONTAINS:
ret = &ascii_casemap_contains;
break;
case MATCHES:
ret = &ascii_casemap_matches;
break;
#ifdef ENABLE_REGEX
case REGEX:
/* the ascii-casemap destinction is made during
the compilation of the regex in verify_regex() */
ret = &octet_regex;
break;
#endif
}
} else if (!strcmp(comp, "i;ascii-numeric")) {
switch (mode) {
case IS:
ret = &ascii_numeric_is;
break;
}
}
return ret;
}
/* comparator.h
* Larry Greenfield
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifndef COMPARATOR_H
#define COMPARATOR_H
#ifdef ENABLE_REGEX
#ifdef HAVE_RX
#include <rxposix.h>
#else
#include <sys/types.h>
#include <regex.h>
#endif
#endif
/* compares pat to text; returns 1 if it's true, 0 otherwise
first arg is pat, second arg is text */
typedef int comparator_t(const char *, const char *);
/* returns a pointer to a comparator function given it's name */
comparator_t *lookup_comp(const char *comp, int mode);
#endif
/* exitcodes.h -- wrapper around sysextis.h
* $Id$
*
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/* Sendmail has some weird ideas on what constitutes permenant failure. On
more than one occasion, we have gotten burned by this moving users around
through various inadvisable means, screwing up the mailboxes file,
whatever.
We don't want to fail out permenantly on things like EX_USAGE, EX_SOFTWARE,
etc., because that generally means someone was just screwing with the mail
store and we don't want to lose mail.
Instead, we map these EC_* codes to EX_* codes, thereby lying to Sendmail,
since we don't derive any benefit from Sendmail knowing what the error was.
We just want it to retry all the time anyway. This way, should sendmail's
behavior be different and we start deriving benefit from Sendmail knowing
stuff, we can easily change it back.
So other code uses the EC_* error, then we maybe change it to TEMPFAIL if
we don't agree on whether the error should be permenant or not.
Comments below stolen from sysexits.h. */
#ifndef INCLUDED_EXITCODES_H
#define INCLUDED_EXITCODES_H
#include <sysexits.h>
#define EC_OK 0 /* successful termination */
#define EC_USAGE EX_TEMPFAIL /* command line usage error */
#define EC_DATAERR EX_DATAERR /* data format error */
#define EC_NOINPUT EX_TEMPFAIL /* cannot open input */
#define EC_NOUSER EX_NOUSER /* addressee unknown */
#define EC_NOHOST EX_TEMPFAIL /* host name unknown */
#define EC_UNAVAILABLE EX_TEMPFAIL /* service unavailable */
#define EC_SOFTWARE EX_TEMPFAIL /* internal software error */
#define EC_OSERR EX_TEMPFAIL /* system error (e.g., can't fork) */
#define EC_OSFILE EX_TEMPFAIL /* critical OS file missing */
#define EC_CANTCREAT EX_TEMPFAIL /* can't create (user) output file */
#define EC_IOERR EX_TEMPFAIL /* input/output error */
#define EC_TEMPFAIL EX_TEMPFAIL /* user is invited to retry */
#define EC_PROTOCOL EX_TEMPFAIL /* remote error in protocol */
#define EC_NOPERM EX_TEMPFAIL /* permission denied */
#define EC_CONFIG EX_TEMPFAIL /* configuration error */
#endif /* INCLUDED_EXITCODES_H */
/* hmac-md5.h -- HMAC_MD5 functions
*/
#ifndef HMAC_MD5_H
#define HMAC_MD5_H 1
#define HMAC_MD5_SIZE 16
/* intermediate MD5 context */
typedef struct HMAC_MD5_CTX_s {
MD5_CTX ictx, octx;
} HMAC_MD5_CTX;
/* intermediate HMAC state
* values stored in network byte order (Big Endian)
*/
typedef struct HMAC_MD5_STATE_s {
UINT4 istate[4];
UINT4 ostate[4];
} HMAC_MD5_STATE;
/* One step hmac computation
*
* digest may be same as text or key
*/
void hmac_md5(const unsigned char *text, int text_len,
const unsigned char *key, int key_len,
unsigned char digest[HMAC_MD5_SIZE]);
/* create context from key
*/
void hmac_md5_init(HMAC_MD5_CTX *hmac,
const unsigned char *key, int key_len);
/* precalculate intermediate state from key
*/
void hmac_md5_precalc(HMAC_MD5_STATE *hmac,
const unsigned char *key, int key_len);
/* initialize context from intermediate state
*/
void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state);
#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len))
/* finish hmac from intermediate result. Intermediate result is zeroed.
*/
void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
HMAC_MD5_CTX *hmac);
#endif /* HMAC_MD5_H */
/* imparse.c -- IMxP client-side parsing routines
$Id$
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
*/
#include <config.h>
#include <stdio.h>
#include <ctype.h>
#include "imparse.h"
/*
* Parse a word from the string starting at the pointer pointed to by 's'.
* Places a pointer to the parsed word in the pointer at 'retval',
* returns the character following the word, and modifies the pointer at
* 's' to point after the returned character. Modifies the input buffer.
*/
int imparse_word(s, retval)
char **s;
char **retval;
{
int c;
*retval = *s;
for (;;) {
c = *(*s)++;
if (!c || isspace(c) || c == '(' || c == ')' || c == '\"') {
(*s)[-1] = '\0';
return c;
}
}
}
/*
* Parse an astring from the string starting at the pointer pointed to
* by 's'. On success, places a pointer to the parsed word in the
* pointer at 'retval', returns the character following the word, and
* modifies the pointer at 's' to point after the returned character.
* On failure, returns EOF, modifies the pointer at 'retval' to point
* at the empty string, and modifies 's' to point around the syntax error.
* Modifies the input buffer.
*/
int imparse_astring(s, retval)
char **s;
char **retval;
{
int c;
char *d;
int len = 0;
int sawdigit = 0;
switch (**s) {
case '\0':
case ' ':
case '(':
case ')':
case '\r':
case '\n':
/* Invalid starting character */
*retval = "";
return EOF;
default:
/*
* Atom -- parser is liberal in accepting specials other
* than whitespace, parens, or double quotes
*/
return imparse_word(s, retval);
case '\"':
/*
* Quoted-string. Parser is liberal in accepting qspecials
* other than double-quote, CR, and LF.
*/
*retval = d = ++(*s);
for (;;) {
c = *(*s)++;
if (c == '\\') {
c = *(*s)++;
}
else if (c == '\"') {
*d = '\0';
return *(*s)++;
}
else if (c == '\0' || c == '\r' || c == '\n') {
*retval = "";
return EOF;
}
*d++ = c;
}
case '{':
/* Literal */
(*s)++;
while (isdigit(c = *(*s)++)) {
sawdigit = 1;
len = len*10 + c - '0';
}
if (!sawdigit || c != '}' || *(*s)++ != '\r' || *(*s)++ != '\n') {
*retval = "";
return EOF;
}
*retval = *s;
*s += len;
c = **s;
*(*s)++ = '\0'; /* Note that 0 and '\0' mean the same thing */
return c;
}
}
/*
* Return nonzero if 's' matches the grammar for an atom
*/
int imparse_isatom(s)
const char *s;
{
int len = 0;
if (!*s) return 0;
for (; *s; s++) {
len++;
if (*s & 0x80 || *s < 0x1f || *s == 0x7f ||
*s == ' ' || *s == '{' || *s == '(' || *s == ')' ||
*s == '\"' || *s == '%' || *s == '*' || *s == '\\') return 0;
}
if (len >= 1024) return 0;
return 1;
}
/*
* Return nonzero if 's' matches the grammar for a sequence
*/
int imparse_issequence(const char* s)
{
int c;
int len = 0;
int sawcolon = 0;
while ((c = *s)) {
if (c == ',') {
if (!len) return 0;
if (!isdigit((int) s[-1]) && s[-1] != '*') return 0;
sawcolon = 0;
}
else if (c == ':') {
if (sawcolon || !len) return 0;
if (!isdigit((int) s[-1]) && s[-1] != '*') return 0;
sawcolon = 1;
}
else if (c == '*') {
if (len && s[-1] != ',' && s[-1] != ':') return 0;
if (isdigit((int) s[1])) return 0;
}
else if (!isdigit(c)) {
return 0;
}
s++;
len++;
}
if (len == 0) return 0;
if (!isdigit((int) s[-1]) && s[-1] != '*') return 0;
return 1;
}
/*
* Return nonzero if 's' matches the grammar for a number
*/
int imparse_isnumber(const char *s)
{
if (!*s) return 0;
for (; *s; s++) {
if (!isdigit((int) *s)) return 0;
}
return 1;
}
/* imparse.h -- IMxP client-side parsing routines
* $Id$
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef INCLUDED_IMPARSE_H
#define INCLUDED_IMPARSE_H
extern int imparse_word (char **s, char **retval);
extern int imparse_astring (char **s, char **retval);
extern int imparse_isatom (const char *s);
extern int imparse_issequence (const char *s);
extern int imparse_isnumber (const char *s);
#endif /* INCLUDED_IMPARSE_H */
/* interp.c -- sieve script interpretor builder
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include "xmalloc.h"
#include "sieve_interface.h"
#include "interp.h"
const char *sieve_version = "cmu-sieve 2.0";
/* build a sieve interpretor */
int sieve_interp_alloc(sieve_interp_t **interp, void *interp_context)
{
sieve_interp_t *i;
static int initonce;
if (!initonce) {
initialize_siev_error_table();
initonce = 1;
}
*interp = NULL;
i = (sieve_interp_t *) xmalloc(sizeof(sieve_interp_t));
if (i == NULL) {
return SIEVE_NOMEM;
}
i->redirect = i->discard = i->reject = i->fileinto = i->keep = NULL;
i->getsize = NULL;
i->getheader = NULL;
i->getenvelope = NULL;
i->vacation = NULL;
i->notify = NULL;
i->curflags.flag = NULL; i->curflags.nflags = 0;
i->markflags = NULL;
i->interp_context = interp_context;
i->err = NULL;
*interp = i;
return SIEVE_OK;
}
static const char *sieve_extensions = "fileinto reject envelope vacation"
" imapflags notify subaddress"
#ifdef ENABLE_REGEX
" regex";
#else
"";
#endif /* ENABLE_REGEX */
const char *sieve_listextensions(void)
{
return sieve_extensions;
}
void free_imapflags(sieve_imapflags_t *imapflags)
{
while (imapflags->nflags)
free(imapflags->flag[--imapflags->nflags]);
free(imapflags->flag);
imapflags->flag = NULL;
}
int sieve_interp_free(sieve_interp_t **interp)
{
free_imapflags(&(*interp)->curflags);
free(*interp);
return SIEVE_OK;
}
/* add the callbacks */
int sieve_register_redirect(sieve_interp_t *interp, sieve_callback *f)
{
interp->redirect = f;
return SIEVE_OK;
}
int sieve_register_discard(sieve_interp_t *interp, sieve_callback *f)
{
interp->discard = f;
return SIEVE_OK;
}
int sieve_register_reject(sieve_interp_t *interp, sieve_callback *f)
{
interp->reject = f;
return SIEVE_OK;
}
int sieve_register_fileinto(sieve_interp_t *interp, sieve_callback *f)
{
interp->fileinto = f;
return SIEVE_OK;
}
int sieve_register_keep(sieve_interp_t *interp, sieve_callback *f)
{
interp->keep = f;
return SIEVE_OK;
}
static char *default_markflags[] = { "\\flagged" };
static sieve_imapflags_t default_mark = { default_markflags, 1 };
int sieve_register_imapflags(sieve_interp_t *interp, sieve_imapflags_t *mark)
{
interp->markflags =
(mark && mark->flag && mark->nflags) ? mark : &default_mark;
return SIEVE_OK;
}
int sieve_register_notify(sieve_interp_t *interp, sieve_callback *f)
{
interp->notify = f;
return SIEVE_OK;
}
/* add the callbacks for messages. again, undefined if used after
sieve_script_parse */
int sieve_register_size(sieve_interp_t *interp, sieve_get_size *f)
{
interp->getsize = f;
return SIEVE_OK;
}
int sieve_register_header(sieve_interp_t *interp, sieve_get_header *f)
{
interp->getheader = f;
return SIEVE_OK;
}
int sieve_register_envelope(sieve_interp_t *interp, sieve_get_envelope *f)
{
interp->getenvelope = f;
return SIEVE_OK;
}
int sieve_register_vacation(sieve_interp_t *interp, sieve_vacation_t *v)
{
if (!interp->getenvelope) {
return SIEVE_NOT_FINALIZED; /* we need envelope for vacation! */
}
if (v->min_response == 0) v->min_response = 3;
if (v->max_response == 0) v->max_response = 90;
if (v->min_response < 0 || v->max_response < 7 || !v->autorespond
|| !v->send_response) {
return SIEVE_FAIL;
}
interp->vacation = v;
return SIEVE_OK;
}
int sieve_register_parse_error(sieve_interp_t *interp, sieve_parse_error *f)
{
interp->err = f;
return SIEVE_OK;
}
int sieve_register_execute_error(sieve_interp_t *interp, sieve_execute_error *f)
{
interp->execute_err = f;
return SIEVE_OK;
}
int sieve_register_summary(sieve_interp_t *interp, sieve_execute_error *f)
{
interp->summary = f;
return SIEVE_OK;
}
int interp_verify(sieve_interp_t *i)
{
if (i->redirect && i->keep && i->getsize && i->getheader) {
return SIEVE_OK;
} else {
return SIEVE_NOT_FINALIZED;
}
}
/* interp.h -- interpretor definition
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*****************************************************************/
#ifndef SIEVE_INTERP_H
#define SIEVE_INTERP_H
#include "sieve_interface.h"
struct sieve_interp {
/* standard callbacks for actions */
sieve_callback *redirect, *discard, *reject, *fileinto, *keep;
sieve_callback *notify;
sieve_vacation_t *vacation;
sieve_get_size *getsize;
sieve_get_header *getheader;
sieve_get_envelope *getenvelope;
sieve_parse_error *err;
/* current imapflags state */
sieve_imapflags_t curflags;
/* site-specific imapflags for mark/unmark */
sieve_imapflags_t *markflags;
sieve_execute_error *execute_err;
sieve_execute_error *summary;
/* context to pass along */
void *interp_context;
};
int interp_verify(sieve_interp_t *interp);
void free_imapflags(sieve_imapflags_t *imapflags);
#endif
This diff is collapsed. Click to expand it.
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST
((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
void hmac_md5 PROTO_LIST ((unsigned char *, int, unsigned char *, int, unsigned char*));
/* GLOBAL.H - RSAREF types and constants
*/
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 0 if it has not already
been defined with C compiler flags.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif
/* message.h
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifndef MESSAGE_H
#define MESSAGE_H
#include "sieve_interface.h" /* for action contexts */
#include "tree.h" /* for stringlist_t */
typedef struct Action action_list_t;
typedef enum {
ACTION_NONE,
ACTION_REJECT,
ACTION_FILEINTO,
ACTION_KEEP,
ACTION_REDIRECT,
ACTION_DISCARD,
ACTION_VACATION,
ACTION_SETFLAG,
ACTION_ADDFLAG,
ACTION_REMOVEFLAG,
ACTION_MARK,
ACTION_UNMARK,
ACTION_NOTIFY,
ACTION_DENOTIFY
} action_t;
/* information */
action_list_t *new_action_list(void);
void free_action_list(action_list_t *actions);
/* invariant: always have a dummy element when free_action_list, param
and vac_subj are freed. none of the others are automatically freed.
the do_action() functions should copy param */
struct Action {
action_t a;
union {
sieve_reject_context_t rej;
sieve_fileinto_context_t fil;
sieve_keep_context_t keep;
sieve_redirect_context_t red;
struct {
/* addr, fromaddr, subj - freed! */
sieve_send_response_context_t send;
sieve_autorespond_context_t autoresp;
} vac;
struct {
char *flag;
} fla;
} u;
char *param; /* freed! */
struct Action *next;
char *vac_subj; /* freed! */
char *vac_msg;
int vac_days;
};
typedef struct notify_action_s {
int exists; /* 0 = no +/-1 = yes (-1 flags default action) */
const char *priority;
char *message;
stringlist_t *headers;
} notify_action_t;
/* header parsing */
typedef enum {
ADDRESS_ALL,
ADDRESS_LOCALPART,
ADDRESS_DOMAIN,
ADDRESS_USER,
ADDRESS_DETAIL
} address_part_t;
int parse_address(const char *header, void **data, void **marker);
char *get_address(address_part_t addrpart, void **data, void **marker,
int canon_domain);
int free_address(void **data, void **marker);
notify_action_t *default_notify_action(void);
/* actions; return negative on failure.
* these don't actually perform the actions, they just add it to the
* action list */
int do_reject(action_list_t *m, char *msg);
int do_fileinto(action_list_t *m, char *mbox, sieve_imapflags_t *imapflags);
int do_forward(action_list_t *m, char *addr);
int do_keep(action_list_t *m, sieve_imapflags_t *imapflags);
int do_discard(action_list_t *m);
int do_vacation(action_list_t *m, char *addr, char *fromaddr,
char *subj, char *msg,
int days, int mime);
int do_setflag(action_list_t *m, char *flag);
int do_addflag(action_list_t *m, char *flag);
int do_removeflag(action_list_t *m, char *flag);
int do_mark(action_list_t *m);
int do_unmark(action_list_t *m);
int do_notify(sieve_interp_t *i,void *m, notify_action_t *notify,
const char *priority, char *message, stringlist_t *sl);
int do_denotify(notify_action_t *notify);
#endif
/* parseaddr.c -- RFC 822 address parser
* $Id$
*
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "parseaddr.h"
#include "xmalloc.h"
static char parseaddr_unspecified_domain[] = "unspecified-domain";
static void parseaddr_append (struct address ***addrpp, char *name,
char *route, char *mailbox, char *domain,
char **freemep);
static int parseaddr_phrase (char **inp, char **phrasep, char *specials);
static int parseaddr_domain (char **inp, char **domainp, char **commmentp);
static int parseaddr_route (char **inp, char **routep);
/*
* Parse an address list in 's', appending address structures to
* the list pointed to by 'addrp'.
*/
void
parseaddr_list(str, addrp)
const char *str;
struct address **addrp;
{
char *s;
int ingroup = 0;
char *freeme;
int tok = ' ';
char *phrase, *route, *mailbox, *domain, *comment;
/* Skip down to the tail */
while (*addrp) {
addrp = &(*addrp)->next;
}
s = freeme = xstrdup(str);
while (tok) {
tok = parseaddr_phrase(&s, &phrase, ingroup ? ",@<;" : ",@<:");
switch (tok) {
case ',':
case '\0':
case ';':
if (*phrase) {
parseaddr_append(&addrp, 0, 0, phrase, "", &freeme);
}
if (tok == ';') {
parseaddr_append(&addrp, 0, 0, 0, 0, &freeme);
ingroup = 0;
}
continue;
case ':':
parseaddr_append(&addrp, 0, 0, phrase, 0, &freeme);
ingroup++;
continue;
case '@':
tok = parseaddr_domain(&s, &domain, &comment);
parseaddr_append(&addrp, comment, 0, phrase, domain, &freeme);
continue;
case '<':
tok = parseaddr_phrase(&s, &mailbox, "@>");
if (tok == '@') {
route = 0;
if (!*mailbox) {
*--s = '@';
tok = parseaddr_route(&s, &route);
if (tok != ':') {
parseaddr_append(&addrp, phrase, route, "", "", &freeme);
while (tok && tok != '>') tok = *s++;
continue;
}
tok = parseaddr_phrase(&s, &mailbox, "@>");
if (tok != '@') {
parseaddr_append(&addrp, phrase, route, mailbox, "",
&freeme);
continue;
}
}
tok = parseaddr_domain(&s, &domain, 0);
parseaddr_append(&addrp, phrase, route, mailbox, domain,
&freeme);
while (tok && tok != '>') tok = *s++;
continue; /* effectively auto-inserts a comma */
}
else {
parseaddr_append(&addrp, phrase, 0, mailbox, "", &freeme);
}
}
}
if (ingroup) parseaddr_append(&addrp, 0, 0, 0, 0, &freeme);
if (freeme) free(freeme);
}
/*
* Free the address list 'addr'
*/
void
parseaddr_free(addr)
struct address *addr;
{
struct address *next;
while (addr) {
if (addr->freeme) free(addr->freeme);
next = addr->next;
free((char *)addr);
addr = next;
}
}
/*
* Helper function to append a new address structure to and address list.
*/
static void
parseaddr_append(addrpp, name, route, mailbox, domain, freemep)
struct address ***addrpp;
char *name;
char *route;
char *mailbox;
char *domain;
char **freemep;
{
struct address *newaddr;
newaddr = (struct address *)xmalloc(sizeof(struct address));
if (name && *name) {
newaddr->name = name;
}
else {
newaddr->name = 0;
}
if (route && *route) {
newaddr->route = route;
}
else {
newaddr->route = 0;
}
newaddr->mailbox = mailbox;
if (domain && !*domain) {
domain = parseaddr_unspecified_domain;
}
newaddr->domain = domain;
newaddr->next = 0;
newaddr->freeme = *freemep;
*freemep = 0;
**addrpp = newaddr;
*addrpp = &newaddr->next;
}
/* Macro to skip white space and rfc822 comments */
#define SKIPWHITESPACE(s) \
{ \
int _c, _comment = 0; \
\
while ((_c = *(s))) { \
if (_c == '(') { \
_comment = 1; \
(s)++; \
while ((_comment && (_c = *(s)))) { \
(s)++; \
if (_c == '\\' && *(s)) (s)++; \
else if (_c == '(') _comment++; \
else if (_c == ')') _comment--; \
} \
(s)--; \
} \
else if (!isspace(_c)) break; \
(s)++; \
} \
}
/*
* Parse an RFC 822 "phrase", stopping at 'specials'
*/
static int parseaddr_phrase(inp, phrasep, specials)
char **inp;
char **phrasep;
char *specials;
{
int c;
char *src = *inp;
char *dst;
SKIPWHITESPACE(src);
*phrasep = dst = src;
for (;;) {
c = *src++;
if (c == '\"') {
while ((c = *src)) {
src++;
if (c == '\"') break;
if (c == '\\') {
if (!(c = *src)) break;
src++;
}
*dst++ = c;
}
}
else if (isspace(c) || c == '(') {
src--;
SKIPWHITESPACE(src);
*dst++ = ' ';
}
else if (!c || strchr(specials, c)) {
if (dst > *phrasep && dst[-1] == ' ') dst--;
*dst = '\0';
*inp = src;
return c;
}
else {
*dst++ = c;
}
}
}
/*
* Parse a domain. If 'commentp' is non-nil, parses any trailing comment
*/
static int parseaddr_domain(inp, domainp, commentp)
char **inp;
char **domainp;
char **commentp;
{
int c;
char *src = *inp;
char *dst;
char *cdst;
int comment;
if (commentp) *commentp = 0;
SKIPWHITESPACE(src);
*domainp = dst = src;
for (;;) {
c = *src++;
if (isalnum(c) || c == '-' || c == '[' || c == ']') {
*dst++ = c;
if (commentp) *commentp = 0;
}
else if (c == '.') {
if (dst > *domainp && dst[-1] != '.') *dst++ = c;
if (commentp) *commentp = 0;
}
else if (c == '(') {
if (commentp) {
*commentp = cdst = src;
comment = 1;
while (comment && (c = *src)) {
src++;
if (c == '(') comment++;
else if (c == ')') comment--;
else if (c == '\\' && (c = *src)) src++;
if (comment) *cdst++ = c;
}
*cdst = '\0';
}
else {
src--;
SKIPWHITESPACE(src);
}
}
else if (!isspace(c)) {
if (dst > *domainp && dst[-1] == '.') dst--;
*dst = '\0';
*inp = src;
return c;
}
}
}
/*
* Parse a source route (at-domain-list)
*/
static int parseaddr_route(inp, routep)
char **inp;
char **routep;
{
int c;
char *src = *inp;
char *dst;
SKIPWHITESPACE(src);
*routep = dst = src;
for (;;) {
c = *src++;
if (isalnum(c) || c == '-' || c == '[' || c == ']' ||
c == ',' || c == '@') {
*dst++ = c;
}
else if (c == '.') {
if (dst > *routep && dst[-1] != '.') *dst++ = c;
}
else if (isspace(c) || c == '(') {
src--;
SKIPWHITESPACE(src);
}
else {
while (dst > *routep &&
(dst[-1] == '.' || dst[-1] == ',' || dst[-1] == '@')) dst--;
*dst = '\0';
*inp = src;
return c;
}
}
}
/* parseaddr.h -- RFC 822 address parser
$Id$
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
*/
#ifndef INCLUDED_PARSEADDR_H
#define INCLUDED_PARSEADDR_H
#ifndef P
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#endif
struct address {
char *name;
char *route;
char *mailbox;
char *domain;
struct address *next;
char *freeme; /* If non-nil, free */
};
extern void parseaddr_list P((const char *s, struct address **addrp));
extern void parseaddr_free P((struct address *addr));
#endif /* INCLUDED_PARSEADDR_H */
/* script.h -- script definition
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifndef SIEVE_SCRIPT_H
#define SIEVE_SCRIPT_H
#include "sieve_interface.h"
#include "interp.h"
#include "tree.h"
struct sieve_script {
sieve_interp_t interp;
/* was a "require" done for these? */
struct sieve_support {
int fileinto : 1;
int reject : 1;
int envelope : 1;
int vacation : 1;
int imapflags : 1;
int notify : 1;
int regex : 1;
int subaddress: 1;
} support;
void *script_context;
commandlist_t *cmds;
int err;
};
/* generated by the yacc script */
commandlist_t *sieve_parse(sieve_script_t *interp, FILE *f);
int script_require(sieve_script_t *s, char *req);
#endif
%{
/* sieve.l -- sieve lexer
* Larry Greenfield
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h> /* for strdup */
#include "xmalloc.h"
#include "tree.h"
#include "sieve-gram.h"
static int tonum(char *c);
static char *fixstr(char *);
static char *mlbuf;
static int mlbufsz, mlcur;
extern int yyerror(char *);
%}
%option yylineno
%option noyywrap
ws [ \t]+
ident [a-zA-Z_][a-zA-Z_0-9]*
CRLF (\r\n|\r|\n)
%state MULTILINE
%%
<MULTILINE>^\.{CRLF} { BEGIN INITIAL;
mlbuf[mlcur] = '\0';
yylval.sval = mlbuf; return STRING; }
<MULTILINE>^\.\. { /* dot stuffing! we want one . */ yyless(1); }
<MULTILINE>(.|\n) { if (mlcur == mlbufsz)
mlbuf = xrealloc(mlbuf, 1 + (mlbufsz+=1024));
mlbuf[mlcur++] = yytext[0]; }
<MULTILINE><<EOF>> { yyerror("unexpected end of file in string");
yyterminate(); }
<INITIAL>text:{ws}?(#.*)?{CRLF} { BEGIN MULTILINE;
mlcur = 0; mlbufsz = 0; mlbuf = NULL; }
<INITIAL>[0-9]+[KMG]? { yylval.nval = tonum(yytext); return NUMBER; }
<INITIAL>if return IF;
<INITIAL>elsif return ELSIF;
<INITIAL>else return ELSE;
<INITIAL>anyof return ANYOF;
<INITIAL>allof return ALLOF;
<INITIAL>exists return EXISTS;
<INITIAL>false return SFALSE;
<INITIAL>true return STRUE;
<INITIAL>address return ADDRESS;
<INITIAL>envelope return ENVELOPE;
<INITIAL>header return HEADER;
<INITIAL>not return NOT;
<INITIAL>size return SIZE;
<INITIAL>reject return REJCT;
<INITIAL>fileinto return FILEINTO;
<INITIAL>redirect return FORWARD;
<INITIAL>keep return KEEP;
<INITIAL>require return REQUIRE;
<INITIAL>stop return STOP;
<INITIAL>discard return DISCARD;
<INITIAL>setflag return SETFLAG;
<INITIAL>addflag return ADDFLAG;
<INITIAL>removeflag return REMOVEFLAG;
<INITIAL>mark return MARK;
<INITIAL>unmark return UNMARK;
<INITIAL>notify return NOTIFY;
<INITIAL>denotify return DENOTIFY;
<INITIAL>:low return LOW;
<INITIAL>:medium return MEDIUM;
<INITIAL>:high return HIGH;
<INITIAL>vacation return VACATION;
<INITIAL>:days return DAYS;
<INITIAL>:addresses return ADDRESSES;
<INITIAL>:subject return SUBJECT;
<INITIAL>:mime return MIME;
<INITIAL>:comparator return COMPARATOR;
<INITIAL>:is return IS;
<INITIAL>:contains return CONTAINS;
<INITIAL>:matches return MATCHES;
<INITIAL>:regex return REGEX;
<INITIAL>:over return OVER;
<INITIAL>:under return UNDER;
<INITIAL>:all return ALL;
<INITIAL>:localpart return LOCALPART;
<INITIAL>:domain return DOMAIN;
<INITIAL>:user return USER;
<INITIAL>:detail return DETAIL;
<INITIAL>\"([^"]|\\.)*\" { yylval.sval = fixstr(yytext); return STRING; }
<INITIAL>[ \t\n\r] ; /* ignore whitespace */
<INITIAL>#.* ; /* ignore comments */
. return yytext[0];
%%
static int tonum(char *c)
{
int val = atoi(c);
switch (c[strlen(c)-1]) {
case 'K': val *= (1 << 10); break;
case 'M': val *= (1 << 20); break;
case 'G': val *= (1 << 30); break;
default: break;
}
return val;
}
static char *fixstr(char *str)
{
char *r, *s = (char *) xmalloc(sizeof(char) * strlen(str));
r = s;
str++; /* skip open " */
while (*str != '"') {
if (*str == '\\')
str++;
*s++ = *str++;
}
*s = '\0';
return r;
}
/*
* sieve_err.c:
* This file is automatically generated; please do not edit it.
*/
#if 0
#ifdef __STDC__
#define NOARGS void
#else
#define NOARGS
#define const
#endif
static const char * const text[] = {
"Generic Sieve error",
"Sieve interpretor not finalized",
"Parse error in Sieve script",
"Run-time error during Sieve execution",
"Internal error in Sieve subsystem",
"Memory exhausted in Sieve subsystem",
"Sieve action already taken",
0
};
struct error_table {
char const * const * msgs;
long base;
int n_msgs;
};
struct et_list {
struct et_list *next;
const struct error_table * table;
};
extern struct et_list *_et_list;
static const struct error_table et = { text, -1237848064L, 7 };
static struct et_list link = { 0, 0 };
#endif
void initialize_siev_error_table (NOARGS) {
#if 0
if (!link.table) {
link.next = _et_list;
link.table = &et;
_et_list = &link;
}
#endif
}
/*
* sieve_err.h:
* This file is automatically generated; please do not edit it.
*/
#define SIEVE_FAIL (-1237848064L)
#define SIEVE_NOT_FINALIZED (-1237848063L)
#define SIEVE_PARSE_ERROR (-1237848062L)
#define SIEVE_RUN_ERROR (-1237848061L)
#define SIEVE_INTERNAL_ERROR (-1237848060L)
#define SIEVE_NOMEM (-1237848059L)
#define SIEVE_DONE (-1237848058L)
extern void initialize_siev_error_table ();
#define ERROR_TABLE_BASE_siev (-1237848064L)
/* for compatibility with older versions... */
#define init_siev_err_tbl initialize_siev_error_table
#define siev_err_base ERROR_TABLE_BASE_siev
/* sieve_interface.h -- interface for deliver
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifndef SIEVE_H
#define SIEVE_H
#include <stdio.h>
extern const char *sieve_version;
/* error codes */
#define SIEVE_OK (0)
#include <sieve_err.h>
/* external sieve types */
typedef struct sieve_interp sieve_interp_t;
typedef struct sieve_script sieve_script_t;
typedef int sieve_callback(void *action_context, void *interp_context,
void *script_context,
void *message_context, const char **errmsg);
typedef int sieve_get_size(void *message_context, int *size);
typedef int sieve_get_header(void *message_context,
const char *header,
const char ***contents);
typedef int sieve_get_envelope(void *message_context,
const char *field,
const char ***contents);
typedef struct sieve_vacation {
int min_response; /* 0 -> defaults to 3 */
int max_response; /* 0 -> defaults to 90 */
/* given a hash, say whether we've already responded to it in the last
days days. return SIEVE_OK if we SHOULD autorespond (have not already)
or SIEVE_DONE if we SHOULD NOT. */
sieve_callback *autorespond;
/* mail the response */
sieve_callback *send_response;
} sieve_vacation_t;
typedef struct sieve_imapflags {
char **flag; /* NULL -> defaults to \flagged */
int nflags;
} sieve_imapflags_t;
typedef struct sieve_redirect_context {
char *addr;
} sieve_redirect_context_t;
typedef struct sieve_reject_context {
char *msg;
} sieve_reject_context_t;
typedef struct sieve_fileinto_context {
char *mailbox;
sieve_imapflags_t *imapflags;
} sieve_fileinto_context_t;
typedef struct sieve_keep_context {
sieve_imapflags_t *imapflags;
} sieve_keep_context_t;
typedef struct sieve_notify_context {
const char *priority;
char *message;
} sieve_notify_context_t;
typedef struct sieve_autorespond_context {
unsigned char *hash;
int len;
int days;
} sieve_autorespond_context_t;
typedef struct sieve_send_response_context {
char *addr;
char *fromaddr;
char *subj;
char *msg;
int mime;
} sieve_send_response_context_t;
/* build a sieve interpretor */
int sieve_interp_alloc(sieve_interp_t **interp, void *interp_context);
int sieve_interp_free(sieve_interp_t **interp);
/* add the callbacks for actions. undefined behavior results if these
are called after sieve_script_parse is called! */
int sieve_register_redirect(sieve_interp_t *interp, sieve_callback *f);
int sieve_register_discard(sieve_interp_t *interp, sieve_callback *f);
int sieve_register_reject(sieve_interp_t *interp, sieve_callback *f);
int sieve_register_fileinto(sieve_interp_t *interp, sieve_callback *f);
int sieve_register_keep(sieve_interp_t *interp, sieve_callback *f);
int sieve_register_vacation(sieve_interp_t *interp, sieve_vacation_t *v);
int sieve_register_imapflags(sieve_interp_t *interp, sieve_imapflags_t *mark);
int sieve_register_notify(sieve_interp_t *interp, sieve_callback *f);
/* add the callbacks for messages. again, undefined if used after
sieve_script_parse */
int sieve_register_size(sieve_interp_t *interp, sieve_get_size *f);
int sieve_register_header(sieve_interp_t *interp, sieve_get_header *f);
int sieve_register_envelope(sieve_interp_t *interp, sieve_get_envelope *f);
typedef int sieve_parse_error(int lineno, const char *msg,
void *interp_context,
void *script_context);
int sieve_register_parse_error(sieve_interp_t *interp, sieve_parse_error *f);
typedef int sieve_execute_error(const char *msg, void *interp_context,
void *script_context, void *message_context);
int sieve_register_execute_error(sieve_interp_t *interp,
sieve_execute_error *f);
int sieve_register_summary(sieve_interp_t *interp,
sieve_execute_error *f);
/* given an interpretor and a script, produce an executable script */
int sieve_script_parse(sieve_interp_t *interp, FILE *script,
void *script_context, sieve_script_t **ret);
int sieve_script_free(sieve_script_t **s);
/* execute a script on a message, producing side effects via callbacks */
int sieve_execute_script(sieve_script_t *script,
void *message_context);
/* Get space separated list of extensions supported by the implementation */
const char *sieve_listextensions(void);
#endif
/*
* sieve header field cache.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "svfield.h"
static int
sv_hash_field_name (const char *name)
{
int x = 0;
/* all CHAR up to the first that is ' ', :, or a ctrl char */
for (; !iscntrl (*name) && (*name != ' ') && (*name != ':'); name++)
{
x *= 256;
x += tolower (*name);
x %= SV_FIELD_CACHE_SIZE;
}
return x;
}
/*
The body is kept, the name is still the caller's.
*/
int
sv_field_cache_add (sv_field_cache_t * m, const char *name, char *body)
{
int cl, clinit;
/* put it in the hash table */
clinit = cl = sv_hash_field_name (name);
while (m->cache[cl] != NULL && strcasecmp (name, m->cache[cl]->name))
{
cl++; /* resolve collisions linearly */
cl %= SV_FIELD_CACHE_SIZE;
if (cl == clinit)
break; /* gone all the way around, so bail */
}
/* found where to put it, so insert it into a list */
if (m->cache[cl])
{
/* add this body on */
m->cache[cl]->contents[m->cache[cl]->ncontents++] = body;
/* whoops, won't have room for the null at the end! */
if (!(m->cache[cl]->ncontents % 8))
{
/* increase the size */
sv_field_t* field = (sv_field_t *) realloc (
m->cache[cl],
sizeof(sv_field_t) +
((8 + m->cache[cl]->ncontents) * sizeof(char *))
);
if (field == NULL)
{
return ENOMEM;
}
m->cache[cl] = field;
}
}
else
{
/* create a new entry in the hash table */
sv_field_t* field = (sv_field_t *) malloc (sizeof (sv_field_t) +
8 * sizeof (char *));
if (field)
{
return ENOMEM;
}
m->cache[cl] = field;
m->cache[cl]->name = strdup (name);
m->cache[cl]->contents[0] = body;
m->cache[cl]->ncontents = 1;
}
/* we always want a NULL at the end */
m->cache[cl]->contents[m->cache[cl]->ncontents] = NULL;
return 0;
}
int
sv_field_cache_get (sv_field_cache_t * m,
const char *name, const char ***body)
{
int rc = ENOENT;
int clinit, cl;
clinit = cl = sv_hash_field_name (name);
while (m->cache[cl] != NULL)
{
if (strcasecmp (name, m->cache[cl]->name) == 0)
{
*body = (const char **) m->cache[cl]->contents;
rc = 0;
break;
}
cl++; /* try next hash bin */
cl %= SV_FIELD_CACHE_SIZE;
if (cl == clinit)
break; /* gone all the way around */
}
return rc;
}
void
sv_field_cache_release (sv_field_cache_t * m)
{
int i;
for (i = 0; i < SV_FIELD_CACHE_SIZE; i++)
{
if (m->cache[i])
{
int j;
for (j = 0; m->cache[i]->contents[j]; j++)
{
free (m->cache[i]->contents[j]);
}
free (m->cache[i]);
}
}
}
/*
* sieve field cache.
*/
#ifndef SVFIELD_H
#define SVFIELD_H
#define SV_FIELD_CACHE_SIZE 1019
typedef struct sv_field_t
{
char *name;
int ncontents;
char *contents[1];
}
sv_field_t;
typedef struct sv_field_cache_t
{
sv_field_t *cache[SV_FIELD_CACHE_SIZE];
}
sv_field_cache_t;
extern int sv_field_cache_add (sv_field_cache_t* m, const char *name, char *body);
extern int sv_field_cache_get (sv_field_cache_t* m, const char *name, const char ***body);
extern void sv_field_cache_release (sv_field_cache_t* m);
#endif
/*
* Copyright (c) 2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)sysexits.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _SYSEXITS_H_
#define _SYSEXITS_H_
/*
* SYSEXITS.H -- Exit status codes for system programs.
*
* This include file attempts to categorize possible error
* exit statuses for system programs, notably delivermail
* and the Berkeley network.
*
* Error numbers begin at EX__BASE to reduce the possibility of
* clashing with other exit statuses that random programs may
* already return. The meaning of the codes is approximately
* as follows:
*
* EX_USAGE -- The command was used incorrectly, e.g., with
* the wrong number of arguments, a bad flag, a bad
* syntax in a parameter, or whatever.
* EX_DATAERR -- The input data was incorrect in some way.
* This should only be used for user's data & not
* system files.
* EX_NOINPUT -- An input file (not a system file) did not
* exist or was not readable. This could also include
* errors like "No message" to a mailer (if it cared
* to catch it).
* EX_NOUSER -- The user specified did not exist. This might
* be used for mail addresses or remote logins.
* EX_NOHOST -- The host specified did not exist. This is used
* in mail addresses or network requests.
* EX_UNAVAILABLE -- A service is unavailable. This can occur
* if a support program or file does not exist. This
* can also be used as a catchall message when something
* you wanted to do doesn't work, but you don't know
* why.
* EX_SOFTWARE -- An internal software error has been detected.
* This should be limited to non-operating system related
* errors as possible.
* EX_OSERR -- An operating system error has been detected.
* This is intended to be used for such things as "cannot
* fork", "cannot create pipe", or the like. It includes
* things like getuid returning a user that does not
* exist in the passwd file.
* EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
* etc.) does not exist, cannot be opened, or has some
* sort of error (e.g., syntax error).
* EX_CANTCREAT -- A (user specified) output file cannot be
* created.
* EX_IOERR -- An error occurred while doing I/O on some file.
* EX_TEMPFAIL -- temporary failure, indicating something that
* is not really an error. In sendmail, this means
* that a mailer (e.g.) could not create a connection,
* and the request should be reattempted later.
* EX_PROTOCOL -- the remote system returned something that
* was "not possible" during a protocol exchange.
* EX_NOPERM -- You did not have sufficient permission to
* perform the operation. This is not intended for
* file system problems, which should use NOINPUT or
* CANTCREAT, but rather for higher level permissions.
*/
#define EX_OK 0 /* successful termination */
#define EX__BASE 64 /* base value for error messages */
#define EX_USAGE 64 /* command line usage error */
#define EX_DATAERR 65 /* data format error */
#define EX_NOINPUT 66 /* cannot open input */
#define EX_NOUSER 67 /* addressee unknown */
#define EX_NOHOST 68 /* host name unknown */
#define EX_UNAVAILABLE 69 /* service unavailable */
#define EX_SOFTWARE 70 /* internal software error */
#define EX_OSERR 71 /* system error (e.g., can't fork) */
#define EX_OSFILE 72 /* critical OS file missing */
#define EX_CANTCREAT 73 /* can't create (user) output file */
#define EX_IOERR 74 /* input/output error */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_PROTOCOL 76 /* remote error in protocol */
#define EX_NOPERM 77 /* permission denied */
#define EX_CONFIG 78 /* configuration error */
#define EX__MAX 78 /* maximum listed value */
#endif /* !_SYSEXITS_H_ */
This diff is collapsed. Click to expand it.
/* tree.c -- abstract syntax tree handling
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include "xmalloc.h"
#include "tree.h"
#include "sieve-gram.h"
stringlist_t *new_sl(char *s, stringlist_t *n)
{
stringlist_t *p = (stringlist_t *) xmalloc(sizeof(stringlist_t));
p->s = s;
p->next = n;
return p;
}
patternlist_t *new_pl(void *pat, patternlist_t *n)
{
patternlist_t *p = (patternlist_t *) xmalloc(sizeof(patternlist_t));
p->p = pat;
p->next = n;
return p;
}
tag_t *new_tag(int type, char *s)
{
tag_t *p = (tag_t *) xmalloc(sizeof(tag_t));
p->type = type;
p->arg = s;
return p;
}
taglist_t *new_taglist(tag_t *t, taglist_t *n)
{
taglist_t *p = (taglist_t *) xmalloc(sizeof(taglist_t));
p->t = t;
p->next = n;
return p;
}
test_t *new_test(int type)
{
test_t *p = (test_t *) xmalloc(sizeof(test_t));
p->type = type;
return p;
}
testlist_t *new_testlist(test_t *t, testlist_t *n)
{
testlist_t *p = (testlist_t *) xmalloc(sizeof(testlist_t));
p->t = t;
p->next = n;
return p;
}
commandlist_t *new_command(int type)
{
commandlist_t *p = (commandlist_t *) xmalloc(sizeof(commandlist_t));
p->type = type;
p->next = NULL;
return p;
}
commandlist_t *new_if(test_t *t, commandlist_t *y, commandlist_t *n)
{
commandlist_t *p = (commandlist_t *) xmalloc(sizeof(commandlist_t));
p->type = IF;
p->u.i.t = t;
p->u.i.do_then = y;
p->u.i.do_else = n;
p->next = NULL;
return p;
}
void free_sl(stringlist_t *sl)
{
stringlist_t *sl2;
while (sl != NULL) {
sl2 = sl->next;
if (sl->s) free(sl->s);
free(sl);
sl = sl2;
}
}
void free_pl(patternlist_t *pl, int comptag)
{
patternlist_t *pl2;
while (pl != NULL) {
pl2 = pl->next;
if (pl->p) {
#ifdef ENABLE_REGEX
if (comptag == REGEX) {
regfree((regex_t *) pl->p);
}
#endif
free(pl->p);
}
free(pl);
pl = pl2;
}
}
void free_test(test_t *t);
void free_tl(testlist_t *tl)
{
testlist_t *tl2;
while (tl) {
tl2 = tl->next;
if (tl->t) free_test(tl->t);
free(tl);
tl = tl2;
}
}
void free_test(test_t *t)
{
if (t == NULL) return;
switch (t->type) {
case ANYOF:
case ALLOF:
free_tl(t->u.tl);
break;
case EXISTS:
free_sl(t->u.sl);
break;
case SIZE:
case SFALSE:
case STRUE:
break;
case HEADER:
free_sl(t->u.h.sl);
free_pl(t->u.h.pl, t->u.h.comptag);
break;
case ADDRESS:
free_sl(t->u.ae.sl);
free_pl(t->u.ae.pl, t->u.ae.comptag);
break;
case NOT:
free_test(t->u.t);
break;
}
free(t);
}
void free_tree(commandlist_t *cl)
{
commandlist_t *cl2;
while (cl != NULL) {
cl2 = cl->next;
switch (cl->type) {
case IF:
free_test(cl->u.i.t);
free_tree(cl->u.i.do_then);
free_tree(cl->u.i.do_else);
break;
case REJCT:
if (cl->u.str) free(cl->u.str);
break;
case VACATION:
if (cl->u.v.subject) free(cl->u.v.subject);
if (cl->u.v.addresses) free_sl(cl->u.v.addresses);
if (cl->u.v.message) free(cl->u.v.message);
break;
case FILEINTO:
case FORWARD:
case SETFLAG:
case ADDFLAG:
case REMOVEFLAG:
free_sl(cl->u.sl);
break;
case KEEP:
case STOP:
case DISCARD:
break;
}
free(cl);
cl = cl2;
}
}
/* tree.h -- abstract syntax tree
* Larry Greenfield
* $Id$
*/
/***********************************************************
Copyright 1999 by Carnegie Mellon University
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Carnegie Mellon
University not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifndef TREE_H
#define TREE_H
#include "comparator.h"
/* abstract syntax tree for sieve */
typedef struct Stringlist stringlist_t;
typedef struct Patternlist patternlist_t;
typedef struct Commandlist commandlist_t;
typedef struct Test test_t;
typedef struct Testlist testlist_t;
typedef struct Tag tag_t;
typedef struct Taglist taglist_t;
struct Stringlist {
char *s;
stringlist_t *next;
};
struct Patternlist {
void *p;
patternlist_t *next;
};
struct Tag {
int type;
char *arg;
};
struct Taglist {
tag_t *t;
taglist_t *next;
};
struct Test {
int type;
union {
testlist_t *tl; /* anyof, allof */
stringlist_t *sl; /* exists */
struct { /* it's a header test */
int comptag;
comparator_t *comp;
stringlist_t *sl;
patternlist_t *pl;
} h;
struct { /* it's an address or envelope test */
int comptag;
comparator_t *comp;
stringlist_t *sl;
patternlist_t *pl;
int addrpart;
} ae;
test_t *t; /* not */
struct { /* size */
int t; /* tag */
int n; /* param */
} sz;
} u;
};
struct Testlist {
test_t *t;
testlist_t *next;
};
struct Commandlist {
int type;
union {
char *str;
stringlist_t *sl; /* the parameters */
struct { /* it's an if statement */
test_t *t;
commandlist_t *do_then;
commandlist_t *do_else;
} i;
struct { /* it's a vacation action */
char *subject;
int days;
stringlist_t *addresses;
char *message;
int mime;
} v;
struct { /* it's a notify action */
char *priority;
char *message;
stringlist_t *headers_list;
} n;
} u;
struct Commandlist *next;
};
stringlist_t *new_sl(char *s, stringlist_t *n);
tag_t *new_tag(int type, char *s);
taglist_t *new_taglist(tag_t *t, taglist_t *n);
test_t *new_test(int type);
testlist_t *new_testlist(test_t *t, testlist_t *n);
commandlist_t *new_command(int type);
commandlist_t *new_if(test_t *t, commandlist_t *y, commandlist_t *n);
void free_sl(stringlist_t *sl);
void free_test(test_t *t);
void free_tree(commandlist_t *cl);
#endif
/* util.c -- general utility functions
*
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Chris Newman
* Start Date: 4/6/93
*/
/* $Id$
*/
#include <config.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "util.h"
/* from OS: */
extern char *malloc(), *realloc();
#define BEAUTYBUFSIZE 4096
const unsigned char convert_to_lowercase[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
const unsigned char convert_to_uppercase[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
/* convert string to all lower case
*/
char *lcase(char* str)
{
char *scan = str;
while (*scan) {
*scan = TOLOWER(*scan);
scan++;
}
return (str);
}
/* convert string to all upper case
*/
char *ucase(char* str)
{
char *scan = str;
while (*scan) {
*scan = convert_to_uppercase[(unsigned char)(*scan)];
scan++;
}
return (str);
}
/* clean up control characters in a string while copying it
* returns pointer to end of dst string.
* dst must have twice the length of source
*/
char *beautify_copy(char* dst, const char* src)
{
unsigned char c;
while (*src) {
c = *src++ & 0x7F;
if (!isprint(c)) {
*dst++ = '^';
if (c > ' ') {
c = '?';
} else {
c += '@';
}
}
*dst++ = c;
}
*dst = '\0';
return (dst);
}
/* clean up control characters in a string while copying it
* returns pointer to a static buffer containing the cleaned-up version
* returns NULL on malloc() error
*/
char *beautify_string(const char* src)
{
static char *beautybuf = NULL;
static int beautysize = 0;
int len;
len = strlen(src) * 2 + 1;
if (beautysize < len) {
if (!beautysize) {
beautysize = len > BEAUTYBUFSIZE ? len : BEAUTYBUFSIZE;
beautybuf = malloc(beautysize);
} else {
beautysize *= 2;
if (len > beautysize) beautysize = len;
beautybuf = realloc(beautybuf, beautysize);
}
if (!beautybuf) {
beautysize = 0;
return "";
}
}
(void) beautify_copy(beautybuf, src);
return (beautybuf);
}
/* do a binary search in a keyvalue array
* nelem is the number of keyvalue elements in the kv array
* cmpf is the comparison function (strcmp, strcasecmp, etc).
* returns NULL if not found, or key/value pair if found.
*/
keyvalue *kv_bsearch(const char* key, keyvalue* kv, int nelem,
int (*cmpf) (const char *s1, const char *s2))
{
int top, mid = 0, bot, cmp = 0;
cmp = 1;
bot = 0;
top = nelem - 1;
while (top >= bot && (cmp = (*cmpf)(key, kv[mid = (bot + top) >> 1].key)))
if (cmp < 0) {
top = mid - 1;
} else {
bot = mid + 1;
}
return (cmp ? NULL : kv + mid);
}
/* util.h -- general utility functions
* $Id$
*
* Copyright (c) 1999-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Chris Newman
* Start Date: 4/6/93
*/
#ifndef INCLUDED_UTIL_H
#define INCLUDED_UTIL_H
extern const unsigned char convert_to_lowercase[256];
extern const unsigned char convert_to_uppercase[256];
#define TOUPPER(c) (convert_to_uppercase[(unsigned char)(c)])
#define TOLOWER(c) (convert_to_lowercase[(unsigned char)(c)])
typedef struct keyvalue {
char *key, *value;
} keyvalue;
/* convert string to all lower case
*/
extern char *lcase (char *str);
/* convert string to all upper case
*/
extern char *ucase (char *str);
/* clean up control characters in a string while copying it
* returns pointer to end of dst string.
* dst must have twice the length of source
*/
extern char *beautify_copy (char *dst, const char *src);
/* clean up control characters in a string while copying it
* returns pointer to a static buffer containing the cleaned-up version
* returns NULL on malloc() error
*/
extern char *beautify_string (const char *src);
/* do a binary search in a keyvalue array
* nelem is the number of keyvalue elements in the kv array
* cmpf is the comparison function (strcmp, stricmp, etc).
* returns NULL if not found, or key/value pair if found.
*/
extern keyvalue *kv_bsearch (const char *key, keyvalue *kv, int nelem,
int (*cmpf)(const char *s1, const char *s2));
#endif /* INCLUDED_UTIL_H */
/* xmalloc.c -- Allocation package that calls fatal() when out of memory
*
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* $Id$
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xmalloc.h"
#include "exitcodes.h"
void* xmalloc(unsigned size)
{
void *ret;
ret = malloc(size);
if (ret != NULL) return ret;
fatal("Virtual memory exhausted", EC_TEMPFAIL);
return 0; /*NOTREACHED*/
}
void* xzmalloc(unsigned size)
{
void *ret;
ret = malloc(size);
if (ret != NULL) {
memset(ret, 0, size);
return ret;
}
fatal("Virtual memory exhausted", EC_TEMPFAIL);
return 0; /*NOTREACHED*/
}
void *xrealloc (void* ptr, unsigned size)
{
void *ret;
/* xrealloc (NULL, size) behaves like xmalloc (size), as in ANSI C */
ret = (!ptr ? malloc (size) : realloc (ptr, size));
if (ret != NULL) return ret;
fatal("Virtual memory exhausted", EC_TEMPFAIL);
return 0; /*NOTREACHED*/
}
char *xstrdup(const char* str)
{
char *p = xmalloc(strlen(str)+1);
strcpy(p, str);
return p;
}
char *xstrndup(const char* str, unsigned len)
{
char *p = xmalloc(len+1);
strncpy(p, str, len);
p[len] = '\0';
return p;
}
/* Same as xmalloc() */
void *fs_get(unsigned size)
{
void *ret;
if ((ret = malloc(size)) != NULL)
return (void *)ret;
fatal("Virtual memory exhausted", EC_TEMPFAIL);
}
void fs_give(void** ptr)
{
free((void *)*ptr);
*ptr = 0;
}
#ifndef HAVE_STRLCPY
/* strlcpy -- copy string smartly.
*
* i believe/hope this is compatible with the BSD strlcpy().
*/
size_t strlcpy(char *dst, const char *src, size_t len)
{
size_t n;
if (len <= 0) return strlen(src);
for (n = 0; n < len; n++) {
if ((dst[n] = src[n]) == '\0') break;
}
if (src[n] == '\0') {
/* copied entire string */
return n;
} else {
dst[n] = '\0';
/* ran out of space */
return n + strlen(src + n);
}
}
#endif
#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t len)
{
size_t i, j, o;
o = strlen(dst);
if (len < o + 1)
return o + strlen(src);
len -= o + 1;
for (i = 0, j = o; i < len; i++, j++) {
if ((dst[j] = src[i]) == '\0') break;
}
dst[j] = '\0';
if (src[i] == '\0') {
return j;
} else {
return j + strlen(src + i);
}
}
#endif
/* xmalloc.h -- Allocation package that calls fatal() when out of memory
* $Id$
*
* Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef INCLUDED_XMALLOC_H
#define INCLUDED_XMALLOC_H
/* for size_t */
#include <stdio.h>
extern void *xmalloc (unsigned size);
extern void *xzmalloc (unsigned size);
extern void *xrealloc (void *ptr, unsigned size);
extern char *xstrdup (const char *str);
extern char *xstrndup (const char *str, unsigned len);
extern void *fs_get (unsigned size);
extern void fs_give (void **ptr);
/* handy string manipulation functions */
#ifndef HAVE_STRLCPY
extern size_t strlcpy(char *dst, const char *src, size_t len);
#endif
#ifndef HAVE_STRLCAT
extern size_t strlcat(char *dst, const char *src, size_t len);
#endif
/* Functions using xmalloc.h must provide a function called fatal() conforming
to the following: */
extern void fatal(const char *fatal_message, int fatal_code)
__attribute__ ((noreturn));
#endif /* INCLUDED_XMALLOC_H */