Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions child-fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <math.h>

#include "fdm.h"
#include "deliver.h"
Expand Down Expand Up @@ -134,10 +135,13 @@ fetch_poll(struct account *a, struct iolist *iol, struct io *pio, int timeout)
struct io *rio;
char *cause;
double tim;
int remaining;

log_debug3(
"%s: polling: %u, timeout=%d", a->name, ARRAY_LENGTH(iol), timeout);
tim = get_time();

restart:
log_debug3("%s: polling: %u, timeout=%d, wake=%d", a->name,
ARRAY_LENGTH(iol), timeout, a->wakein);
switch (io_polln(
ARRAY_DATA(iol), ARRAY_LENGTH(iol), &rio, timeout, &cause)) {
case 0:
Expand All @@ -154,7 +158,15 @@ fetch_poll(struct account *a, struct iolist *iol, struct io *pio, int timeout)
xfree(cause);
return (-1);
}
tim = get_time() - tim;
remaining = a->wakein - ((int)floor(get_time() - tim));
if (a->wakein) {
if (remaining > 0) {
/* poll returned early, sleep. */
timeout = sleep(remaining);
goto restart;
}
a->wakein = 0;
}

return (0);
}
Expand Down Expand Up @@ -339,6 +351,7 @@ fetch_account(struct account *a, struct io *pio, int nflags, double tim)
struct iolist iol;
int aborted, complete, holding, timeout;

restart:
log_debug2("%s: fetching", a->name);

TAILQ_INIT(&fetch_matchq);
Expand All @@ -359,7 +372,7 @@ fetch_account(struct account *a, struct io *pio, int nflags, double tim)

ARRAY_INIT(&iol);

aborted = complete = holding = 0;
aborted = complete = holding = a->wakein = 0;
for (;;) {
log_debug3("%s: fetch loop start", a->name);

Expand Down Expand Up @@ -427,7 +440,12 @@ fetch_account(struct account *a, struct io *pio, int nflags, double tim)
continue;
case FETCH_BLOCK:
/* Fetch again - allow blocking. */
log_debug3("%s: fetch, block", a->name);
if (a->wakein)
log_debug(
"%s: fetch, block (wake in %u secs)",
a->name,a->wakein);
else
log_debug3("%s: fetch, block", a->name);
break;
case FETCH_MAIL:
/* Mail ready. */
Expand Down Expand Up @@ -458,7 +476,11 @@ fetch_account(struct account *a, struct io *pio, int nflags, double tim)
* non-empty, we can block unless there are mails that aren't
* blocked (these mails can continue to be processed).
*/
timeout = conf.timeout;

if (a->wakein)
timeout = a->wakein;
else
timeout = conf.timeout;
if (fetch_queued == 0 && ARRAY_LENGTH(&iol) == 1)
timeout = 0;
else if (fetch_queued != 0 && fetch_blocked != fetch_queued)
Expand Down Expand Up @@ -502,7 +524,13 @@ fetch_account(struct account *a, struct io *pio, int nflags, double tim)
log_info("%s: %u messages found", a->name, a->fetch->total(a));
else
fetch_status(a, tim);
return (aborted);

/* In daemon mode, always try to restart. */
if (conf.daemon) {
log_debug("%s: restarting", a->name);
goto restart;
} else
return (aborted);
}

/*
Expand Down
5 changes: 5 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ AC_CHECK_HEADERS(
[ \
sys/queue.h \
sys/tree.h \
math.h \
]
)
AC_CHECK_FUNCS(
Expand All @@ -63,6 +64,10 @@ AC_CHECK_FUNCS(
]
)

AC_SEARCH_LIBS(
floor,
[m])

AC_SEARCH_LIBS(
tdb_open,
[tdb],
Expand Down
9 changes: 8 additions & 1 deletion fdm.1
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
.Sh SYNOPSIS
.Nm fdm
.Bk -words
.Op Fl hklmnqv
.Op Fl dhklmnqv
.Op Fl a Ar account
.Op Fl D Ar name Ns = Ns Ar value
.Op Fl f Ar conffile
Expand Down Expand Up @@ -59,6 +59,13 @@ Default is
or
.Pa /etc/fdm.conf
if that doesn't exist.
.It Fl d
Run in daemon mode. Loop through accounts with a delay.
Implies
.Fl l .
Daemon mode is only compatible with the
.Ic fetch
command.
.It Fl h
Look at the
.Ev HOME
Expand Down
24 changes: 22 additions & 2 deletions fdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ __dead void
usage(void)
{
fprintf(stderr,
"usage: %s [-hklmnqv] [-a name] [-D name=value] [-f conffile] "
"usage: %s [-dhklmnqv] [-a name] [-D name=value] [-f conffile] "
"[-u user] [-x name] [fetch|poll|cache] [arguments]\n", __progname);
exit(1);
}
Expand Down Expand Up @@ -326,6 +326,13 @@ main(int argc, char **argv)
conf.def_user = NULL;
conf.cmd_user = NULL;
conf.max_accts = -1;
conf.keep_all = 0;
conf.daemon = 0;
conf.syslog = 0;
conf.allow_many = 0;
conf.check_only = 0;
conf.debug = 0;
conf.fetch_freq = DEFFETCHFREQ;
conf.strip_chars = xstrdup(DEFSTRIPCHARS);

conf.user_order = xmalloc(sizeof *conf.user_order);
Expand All @@ -336,7 +343,7 @@ main(int argc, char **argv)
ARRAY_INIT(&conf.excl);

ARRAY_INIT(&macros);
while ((opt = getopt(argc, argv, "a:D:f:hklmnqu:vx:")) != -1) {
while ((opt = getopt(argc, argv, "a:D:f:dhklmnqu:vx:")) != -1) {
switch (opt) {
case 'a':
ARRAY_ADD(&conf.incl, xstrdup(optarg));
Expand All @@ -348,6 +355,10 @@ main(int argc, char **argv)
if (conf.conf_file == NULL)
conf.conf_file = xstrdup(optarg);
break;
case 'd':
conf.daemon = 1;
conf.syslog = 1;
break;
case 'h':
home = getenv("HOME");
break;
Expand Down Expand Up @@ -403,6 +414,15 @@ main(int argc, char **argv)
usage();
}

/* fork off into daemon mode if requested. */
if (conf.daemon) {
if (op != FDMOP_FETCH)
fatal("Fetch command must be given for daemon mode.");

if (daemon(0,0))
fatal("Daemon mode failed.");
}

/* Set debug level and start logging to syslog if necessary. */
if (conf.syslog)
log_open_syslog(conf.debug);
Expand Down
5 changes: 5 additions & 0 deletions fdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#define CONFFILE ".fdm.conf"
#define LOCKFILE ".fdm.lock"
#define DEFLOCKTIMEOUT 10
#define DEFFETCHFREQ 60 * 5 /* 5 minutes */
#define MAXQUEUEVALUE 50
#define DEFMAILQUEUE 2
#define DEFMAILSIZE (32 * 1024 * 1024) /* 32 MB */
Expand Down Expand Up @@ -489,6 +490,8 @@ struct account {

int disabled;
int keep;
int wakein; /* secs */
int timeout;

struct fetch *fetch;
void *data;
Expand Down Expand Up @@ -613,6 +616,7 @@ struct conf {

char *conf_file;
char *strip_chars;
int daemon;
int check_only;
int allow_many;
int keep_all;
Expand All @@ -635,6 +639,7 @@ struct conf {

size_t max_size;
int timeout;
int fetch_freq;
int del_big;
int ignore_errors;
u_int lock_types;
Expand Down
13 changes: 10 additions & 3 deletions fetch-imap.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,19 @@ void
fetch_imap_desc(struct account *a, char *buf, size_t len)
{
struct fetch_imap_data *data = a->data;
char *folders;
char *folders, timeout[18];

folders = fmt_strings("folders ", data->folders);

if (a->timeout != 0)
snprintf(timeout,sizeof timeout," timeout %u", a->timeout);
else
timeout[0] = 0;

xsnprintf(buf, len,
"imap%s server \"%s\" port %s user \"%s\" %s",
"imap%s server \"%s\" port %s user \"%s\" %s%s%s",
data->server.ssl ? "s" : "", data->server.host, data->server.port,
data->user, folders);
data->user, folders,
data->server.insecure ? " insecure" : "", timeout);
xfree(folders);
}
11 changes: 9 additions & 2 deletions fetch-pop3.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,15 @@ void
fetch_pop3_desc(struct account *a, char *buf, size_t len)
{
struct fetch_pop3_data *data = a->data;
char timeout[18];

xsnprintf(buf, len, "pop3%s server \"%s\" port %s user \"%s\"",
if (a->timeout != 0)
snprintf(timeout,sizeof timeout," timeout %u", a->timeout);
else
timeout[0] = 0;

xsnprintf(buf, len, "pop3%s server \"%s\" port %s user \"%s\"%s%s",
data->server.ssl ? "s" : "", data->server.host, data->server.port,
data->user);
data->user,
data->server.insecure ? " insecure" : "", timeout);
}
8 changes: 8 additions & 0 deletions imap-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1120,9 +1120,17 @@ imap_state_close(struct account *a, struct fetch_ctx *fctx)
return (FETCH_AGAIN);
}

if (conf.daemon) {
data->folder = 0; // go back to the first folder.
fctx->state = imap_state_select1;
a->wakein = conf.fetch_freq;
return (FETCH_BLOCK);
}

if (imap_putln(a, "%u LOGOUT", ++data->tag) != 0)
return (FETCH_ERROR);
fctx->state = imap_state_quit;

return (FETCH_BLOCK);
}

Expand Down
2 changes: 1 addition & 1 deletion io.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ io_polln(struct io **iop, u_int n, struct io **rio, int timeout, char **cause)
xfree(pfds);

if (error == 0) {
if (timeout == 0) {
if (timeout != conf.timeout) {
errno = EAGAIN;
return (-1);
}
Expand Down
1 change: 1 addition & 0 deletions lex.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ static const struct token tokens[] = {
{ "exec", TOKEXEC },
{ "expire", TOKEXPIRE },
{ "fcntl", TOKFCNTL },
{ "fetch-frequency", TOKFETCHFREQ },
{ "file-group", TOKFILEGROUP },
{ "file-umask", TOKFILEUMASK },
{ "flock", TOKFLOCK },
Expand Down
19 changes: 17 additions & 2 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ yyerror(const char *fmt, ...)
%token TOKEXEC
%token TOKEXPIRE
%token TOKFCNTL
%token TOKFETCHFREQ
%token TOKFILEGROUP
%token TOKFILEUMASK
%token TOKFLOCK
Expand Down Expand Up @@ -310,7 +311,7 @@ yyerror(const char *fmt, ...)
%type <flag> insecure
%type <localgid> localgid
%type <locks> lock locklist
%type <number> size time numv retrc expire
%type <number> size time numv retrc expire timeout
%type <only> only imaponly
%type <poponly> poponly
%type <replstrs> replstrslist actions rmheaders accounts users
Expand Down Expand Up @@ -604,6 +605,10 @@ set: TOKSET TOKMAXSIZE size
{
conf.del_big = 1;
}
| TOKSET TOKFETCHFREQ time
{
conf.fetch_freq = $3;
}
| TOKSET TOKIGNOREERRORS
{
conf.ignore_errors = 1;
Expand Down Expand Up @@ -1060,6 +1065,15 @@ port: TOKPORT replstrv
xasprintf(&$$, "%lld", $2);
}

timeout: /* not present */
{
$$ = 0; /* use global value */
}
| TOKTIMEOUT time
{
$$ = $2;
}

server: TOKSERVER replstrv port
{
if (*$2 == '\0')
Expand Down Expand Up @@ -2382,7 +2396,7 @@ fetchtype: poptype server userpassnetrc poponly apop verify uidl starttls
data->server.ai = NULL;
}

account: TOKACCOUNT replstrv disabled users fetchtype keep
account: TOKACCOUNT replstrv disabled users fetchtype keep timeout
{
struct account *a;
char *su, desc[DESCBUFSIZE];
Expand All @@ -2397,6 +2411,7 @@ account: TOKACCOUNT replstrv disabled users fetchtype keep
a = xcalloc(1, sizeof *a);
strlcpy(a->name, $2, sizeof a->name);
a->keep = $6;
a->timeout = $7;
a->disabled = $3;
a->users = $4;
a->fetch = $5.fetch;
Expand Down