Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
John McEleney
/
mailutils
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit
e2e5a903
...
e2e5a90391f4c96f17e4fd436b047356b081f02b
authored
2002-11-19 13:58:05 +0000
by
Sergey Poznyakoff
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Support for user-defined sieve filters. Improved debugging.
1 parent
3474b31f
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
247 additions
and
32 deletions
mail.local/main.c
mail.local/main.c
View file @
e2e5a90
...
...
@@ -17,7 +17,6 @@
#include <mail.local.h>
int
debug_level
;
int
multiple_delivery
;
int
ex_quota_tempfail
;
int
exit_code
=
EX_OK
;
...
...
@@ -25,6 +24,13 @@ uid_t uid;
char
*
quotadbname
=
NULL
;
int
lock_timeout
=
300
;
/* Debuggig options */
int
debug_level
;
int
debug_flags
;
int
sieve_debug_flags
;
int
sieve_enable_log
;
mu_debug_t
mudebug
;
#define MAXFD 64
#define EX_QUOTA() (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE)
...
...
@@ -36,7 +42,17 @@ void mailer_err (char *fmt, ...);
void
notify_biff
(
mailbox_t
mbox
,
char
*
name
,
size_t
size
);
const
char
*
argp_program_version
=
"mail.local ("
PACKAGE_STRING
")"
;
static
char
doc
[]
=
"GNU mail.local -- the local MDA"
;
static
char
doc
[]
=
"GNU mail.local -- the local MDA"
"
\v
"
"Debug flags are:
\n
"
" g - guimb stack traces
\n
"
" T - mailutil traces (MU_DEBUG_TRACE)
\n
"
" P - network protocols (MU_DEBUG_PROT)
\n
"
" t - sieve trace (MU_SIEVE_DEBUG_TRACE)
\n
"
" l - sieve action logs
\n
"
" 0-9 - Set mail.local debugging level
\n
"
;
static
char
args_doc
[]
=
"recipient [recipient ...]"
;
#define ARG_MULTIPLE_DELIVERY 1
...
...
@@ -55,17 +71,13 @@ static struct argp_option options[] =
{
"quota-db"
,
'q'
,
"FILE"
,
0
,
"Specify path to quota database"
,
0
},
#endif
{
"sieve"
,
'S'
,
"PATTERN"
,
0
,
"Set name pattern for user-defined sieve mail filters"
,
0
},
#ifdef WITH_GUILE
{
"source"
,
's'
,
"PATTERN"
,
0
,
"Set name pattern for user-defined mail filters"
,
0
},
#endif
{
"debug"
,
'x'
,
#ifdef WITH_GUILE
"{NUMBER|guile}"
,
#else
"NUMBER"
,
#endif
0
,
{
"debug"
,
'x'
,
"FLAGS"
,
0
,
"Enable debugging"
,
0
},
{
"timeout"
,
't'
,
"NUMBER"
,
0
,
"Set timeout for acquiring the lockfile"
},
...
...
@@ -94,6 +106,10 @@ static const char *argp_capa[] = {
char
*
from
=
NULL
;
char
*
progfile_pattern
=
NULL
;
char
*
sieve_pattern
=
NULL
;
message_t
sieve_msg
=
NULL
;
#define D_DEFAULT "9s"
static
error_t
parse_opt
(
int
key
,
char
*
arg
,
struct
argp_state
*
state
)
...
...
@@ -117,7 +133,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
}
from
=
arg
;
break
;
#ifdef USE_DBM
case
'q'
:
quotadbname
=
arg
;
...
...
@@ -125,34 +141,59 @@ parse_opt (int key, char *arg, struct argp_state *state)
#endif
#ifdef WITH_GUILE
case
's'
:
progfile_pattern
=
optarg
;
break
;
case
's'
:
progfile_pattern
=
optarg
;
break
;
#endif
case
'S'
:
sieve_pattern
=
optarg
;
break
;
case
't'
:
lock_timeout
=
strtoul
(
optarg
,
NULL
,
0
);
break
;
case
't'
:
lock_timeout
=
strtoul
(
optarg
,
NULL
,
0
);
break
;
case
'x'
:
if
(
optarg
)
{
case
'x'
:
do
{
if
(
!
optarg
)
optarg
=
D_DEFAULT
;
switch
(
*
optarg
)
{
case
'g'
:
#ifdef WITH_GUILE
if
(
strcmp
(
optarg
,
"guile"
)
==
0
)
debug_guile
=
1
;
else
#endif
debug_level
=
strtoul
(
optarg
,
NULL
,
0
);
}
else
{
debug_level
=
9
;
#ifdef WITH_GUILE
debug_guile
=
1
;
#endif
}
break
;
break
;
case
't'
:
sieve_debug_flags
|=
MU_SIEVE_DEBUG_TRACE
;
break
;
case
'l'
:
sieve_enable_log
=
1
;
break
;
case
'T'
:
debug_flags
|=
MU_DEBUG_TRACE
;
break
;
case
'P'
:
debug_flags
|=
MU_DEBUG_PROT
;
break
;
default:
if
(
isdigit
(
*
optarg
))
debug_level
=
*
optarg
-
'0'
;
else
argp_error
(
state
,
"%c is not a valid debug flag"
,
*
arg
);
break
;
}
}
while
(
*++
optarg
);
break
;
default:
return
ARGP_ERR_UNKNOWN
;
...
...
@@ -162,6 +203,64 @@ parse_opt (int key, char *arg, struct argp_state *state)
return
0
;
}
static
int
_mu_debug_printer
(
mu_debug_t
unused
,
size_t
level
,
const
char
*
fmt
,
va_list
ap
)
{
vsyslog
((
level
==
MU_DEBUG_ERROR
)
?
LOG_ERR
:
LOG_DEBUG
,
fmt
,
ap
);
return
0
;
}
static
int
_sieve_debug_printer
(
void
*
unused
,
const
char
*
fmt
,
va_list
ap
)
{
vsyslog
(
LOG_DEBUG
,
fmt
,
ap
);
return
0
;
}
static
void
_sieve_action_log
(
void
*
user_name
,
const
char
*
script
,
size_t
msgno
,
message_t
msg
,
const
char
*
action
,
const
char
*
fmt
,
va_list
ap
)
{
size_t
uid
=
0
;
char
*
text
=
NULL
;
message_get_uid
(
msg
,
&
uid
);
asprintf
(
&
text
,
"%s on msg uid %d"
,
action
,
uid
);
if
(
fmt
&&
strlen
(
fmt
))
{
char
*
diag
=
NULL
;
asprintf
(
&
diag
,
fmt
,
ap
);
syslog
(
LOG_NOTICE
,
"(user %s) %s: %s"
,
(
char
*
)
user_name
,
text
,
diag
);
free
(
diag
);
}
else
syslog
(
LOG_NOTICE
,
"(user %s) %s"
,
(
char
*
)
user_name
,
text
);
free
(
text
);
}
static
int
_sieve_parse_error
(
void
*
user_name
,
const
char
*
filename
,
int
lineno
,
const
char
*
fmt
,
va_list
ap
)
{
char
*
text
;
vasprintf
(
&
text
,
fmt
,
ap
);
if
(
filename
)
{
char
*
loc
;
asprintf
(
&
loc
,
"%s:%d: "
,
filename
,
lineno
);
syslog
(
LOG_ERR
,
"%s: %s"
,
loc
,
text
);
free
(
loc
);
}
else
syslog
(
LOG_ERR
,
"(user %s) %s"
,
user_name
,
text
);
free
(
text
);
return
0
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
...
...
@@ -180,6 +279,28 @@ main (int argc, char *argv[])
openlog
(
"mail.local"
,
LOG_PID
,
log_facility
);
mu_error_set_print
(
mu_syslog_error_printer
);
if
(
debug_flags
)
{
int
rc
;
if
((
rc
=
mu_debug_create
(
&
mudebug
,
NULL
)))
{
mu_error
(
"mu_debug_create failed: %s
\n
"
,
mu_errstring
(
rc
));
exit
(
EX_TEMPFAIL
);
}
if
((
rc
=
mu_debug_set_level
(
mudebug
,
debug_flags
)))
{
mu_error
(
"mu_debug_set_level failed: %s
\n
"
,
mu_errstring
(
rc
));
exit
(
EX_TEMPFAIL
);
}
if
((
rc
=
mu_debug_set_print
(
mudebug
,
_mu_debug_printer
,
NULL
)))
{
mu_error
(
"mu_debug_set_print failed: %s
\n
"
,
mu_errstring
(
rc
));
exit
(
EX_TEMPFAIL
);
}
}
uid
=
getuid
();
...
...
@@ -204,6 +325,34 @@ main (int argc, char *argv[])
}
fp
=
make_tmp
(
from
,
&
tempfile
);
if
(
sieve_pattern
)
{
stream_t
stream
;
int
status
;
fflush
(
fp
);
file_stream_create
(
&
stream
,
tempfile
,
MU_STREAM_RDWR
);
if
((
status
=
stream_open
(
stream
)))
{
mu_error
(
"Opening temporary file failed: %s
\n
"
,
mu_errstring
(
status
));
return
EX_TEMPFAIL
;
}
if
((
status
=
message_create
(
&
sieve_msg
,
NULL
)))
{
mu_error
(
"Can't create temporary message: %s
\n
"
,
mu_errstring
(
status
));
return
EX_TEMPFAIL
;
}
if
((
status
=
message_set_stream
(
sieve_msg
,
stream
,
NULL
)))
{
mu_error
(
"Can't assign stream to temporary message: %s
\n
"
,
mu_errstring
(
status
));
return
EX_TEMPFAIL
;
}
}
if
(
multiple_delivery
)
multiple_delivery
=
argc
>
1
;
...
...
@@ -229,6 +378,64 @@ main (int argc, char *argv[])
}
int
sieve_test
(
struct
mu_auth_data
*
auth
)
{
int
rc
=
1
;
char
*
progfile
;
if
(
!
sieve_pattern
)
return
1
;
progfile
=
mu_expand_path_pattern
(
sieve_pattern
,
auth
->
name
);
if
(
access
(
progfile
,
R_OK
))
{
if
(
debug_level
>
2
)
syslog
(
LOG_DEBUG
,
"access to %s failed: %m"
,
progfile
);
}
else
{
sieve_machine_t
mach
;
rc
=
sieve_machine_init
(
&
mach
,
auth
->
name
);
if
(
rc
)
{
mu_error
(
"can't initialize sieve machine: %s"
,
mu_errstring
(
rc
));
}
else
{
sieve_set_debug
(
mach
,
_sieve_debug_printer
);
sieve_set_debug_level
(
mach
,
mudebug
,
sieve_debug_flags
);
sieve_set_parse_error
(
mach
,
_sieve_parse_error
);
if
(
sieve_enable_log
)
sieve_set_logger
(
mach
,
_sieve_action_log
);
rc
=
sieve_compile
(
mach
,
progfile
);
if
(
rc
==
0
)
{
attribute_t
attr
;
message_get_attribute
(
sieve_msg
,
&
attr
);
attribute_unset_deleted
(
attr
);
if
(
switch_user_id
(
auth
,
1
)
==
0
)
{
chdir
(
auth
->
dir
);
rc
=
sieve_message
(
mach
,
sieve_msg
);
if
(
rc
==
0
)
rc
=
attribute_is_deleted
(
attr
)
==
0
;
switch_user_id
(
auth
,
0
);
chdir
(
"/"
);
}
}
sieve_machine_destroy
(
&
mach
);
}
}
free
(
progfile
);
return
rc
;
}
int
mda
(
FILE
*
fp
,
char
*
username
)
{
deliver
(
fp
,
username
);
...
...
@@ -374,11 +581,19 @@ deliver (FILE *fp, char *name)
exit_code
=
EX_UNAVAILABLE
;
return
;
}
if
(
!
sieve_test
(
auth
))
{
exit_code
=
EX_OK
;
mu_auth_data_free
(
auth
);
return
;
}
if
((
status
=
mailbox_create
(
&
mbox
,
auth
->
mailbox
))
!=
0
)
{
mailer_err
(
"can't open mailbox %s: %s"
,
auth
->
mailbox
,
mu_errstring
(
status
));
mu_auth_data_free
(
auth
);
return
;
}
...
...
Please
register
or
sign in
to post a comment