* - close idle connections
* - cope better with garbage in feed file
* - cope better with NULs in feed file
+ * - check all structs initialised
+ * - check all fd watches properly undone
+ * - check all init functions called
* - -k kill mode ?
*/
#define _GNU_SOURCE
-#include "inn/list.h"
#include "config.h"
#include "storage.h"
#include "nntp.h"
#include "libinn.h"
#include "inndcomm.h"
+#include "inn/list.h"
+#include "inn/innconf.h"
+
#include <sys/uio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <glob.h>
#include <time.h>
+#include <math.h>
#include <oop.h>
#include <oop-read.h>
/*----- configuration options -----*/
-static char *sitename, *feedfile;
+static const char *sitename, *feedfile, *pathoutgoing;
static const char *remote_host;
static int quiet_multiple=0, become_daemon=1;
/*========== logging ==========*/
-static void logcore(int sysloglevel, const char *fmt, ...)
- __attribute__((__format__(printf,2,3)));
+#define VA va_list al; va_start(al,fmt)
+#define PRINTF(f,a) __attribute__((__format__(printf,f,a)))
+#define NORET_PRINTF(f,a) __attribute__((__noreturn__,__format__(printf,f,a)))
+
+static void logcore(int sysloglevel, const char *fmt, ...) PRINTF(2,3);
static void logcore(int sysloglevel, const char *fmt, ...) {
- va_list al;
- va_start(al,fmt);
+ VA;
if (become_daemon) {
vsyslog(sysloglevel,fmt,al);
} else {
}
static void logv(int sysloglevel, const char *pfx, int errnoval,
- const char *fmt, va_list al)
- __attribute__((__format__(printf,5,0)));
+ const char *fmt, va_list al) PRINTF(5,0);
static void logv(int sysloglevel, const char *pfx, int errnoval,
const char *fmt, va_list al) {
char msgbuf[256]; /* NB do not call xvasprintf here or you'll recurse */
}
#define diewrap(fn, pfx, sysloglevel, err, estatus) \
- static void fn(const char *fmt, ...) \
- __attribute__((__noreturn__,__format__(printf,1,2))); \
+ static void fn(const char *fmt, ...) NORET_PRINTF(1,2); \
static void fn(const char *fmt, ...) { \
- va_list al; \
- va_start(al,fmt); \
+ VA; \
logv(sysloglevel, pfx, err, fmt, al); \
exit(estatus); \
}
#define logwrap(fn, pfx, sysloglevel, err) \
- static void fn(const char *fmt, ...) \
- __attribute__((__format__(printf,1,2))); \
+ static void fn(const char *fmt, ...) PRINTF(1,2); \
static void fn(const char *fmt, ...) { \
- va_list al; \
- va_start(al,fmt); \
+ VA; \
logv(sysloglevel, pfx, err, fmt, al); \
va_end(al); \
}
/*========== utility functions etc. ==========*/
-static char *xvasprintf(const char *fmt, va_list al)
- __attribute__((__format__(printf,1,0)));
+static char *xvasprintf(const char *fmt, va_list al) PRINTF(1,0);
static char *xvasprintf(const char *fmt, va_list al) {
char *str;
int rc= vasprintf(&str,fmt,al);
if (rc<0) sysdie("vasprintf(\"%s\",...) failed", fmt);
return str;
}
-static char *xasprintf(const char *fmt, ...)
- __attribute__((__format__(printf,1,2)));
+static char *xasprintf(const char *fmt, ...) PRINTF(1,2);
static char *xasprintf(const char *fmt, ...) {
- va_list al;
- va_start(al,fmt);
+ VA;
char *str= xvasprintf(fmt,al);
va_end(al);
return str;
}
}
-static void vconnfail(Conn *conn, const char *fmt, va_list al)
- __attribute__((__format__(printf,2,0)));
-
+static void vconnfail(Conn *conn, const char *fmt, va_list al) PRINTF(2,0);
static void vconnfail(Conn *conn, const char *fmt, va_list al) {
int requeue[art_MaxState];
check_master_queue();
}
-static void connfail(Conn *conn, const char *fmt, ...)
- __attribute__((__format__(printf,2,3)));
+static void connfail(Conn *conn, const char *fmt, ...) PRINTF(2,3);
static void connfail(Conn *conn, const char *fmt, ...) {
va_list al;
va_start(al,fmt);
/*========== option parsing ==========*/
-static void vbadusage(const char *fmt, va_list al)
- __attribute__((__noreturn__,__format__(printf,1,0)));
+/*---------- generic option parser and logging ----------*/
+
+static void vbadusage(const char *fmt, va_list al) NORET_PRINTF(1,0);
static void vbadusage(const char *fmt, va_list al) {
abort();
}
-static void badusage(const char *fmt, ...)
- __attribute__((__noreturn__,__format__(printf,1,2)));
+static void badusage(const char *fmt, ...) NORET_PRINTF(1,2);
static void badusage(const char *fmt, ...) {
va_list al;
va_start(al,fmt);
const char *lng;
void *store;
OptionParser *fn;
- int noarg;
+ int noarg, intval;
};
+/*---------- specific option types ----------*/
+
static void op_integer(const Option *o, const char *val) {
char *ep;
errno= 0;
}
static void op_string(const Option *o, const char *val) {
- char **store= o->store;
- free(*store);
+ const char **store= o->store;
*store= val;
}
static void op_seconds(const Option *o, const char *val) {
int *store= o->store;
char *ep;
+ int unit;
double v= strtod(val,&ep);
if (ep==val) badusage("bad time/duration value for %s",o->lng);
*store /= PERIOD_SECONDS;
}
-static void op_periods_booltrue(const Option *o, const char *val) {
+static void op_setint(const Option *o, const char *val) {
int *store= o->store;
- *store= 1;
-}
-static void op_periods_boolfalse(const Option *o, const char *val) {
- int *store= o->store;
- *store= 0;
+ *store= o->intval;
}
+/*---------- specific options ----------*/
+
static const Option options[]= {
{'f',"feedfile", &feedfile, op_string },
-{'q',"quiet-multiple", &quiet_multiple, op_booltrue, 1 },
+{'q',"quiet-multiple", &quiet_multiple, op_setint, 1,1 },
-{ 0, "max-connections", &max_connections op_integer },
-{ 0, "max-queue-per-conn", &max_queue_per_conn op_integer },
+{ 0, "max-connections", &max_connections, op_integer },
+{ 0, "max-queue-per-conn", &max_queue_per_conn, op_integer },
-{ 0, "streaming", &try_stream, op_booltrue, 1 },
-{ 0, "no-streaming", &try_stream, op_boolfalse, 1 },
-{'P',"port", &port op_integer },
+{ 0, "streaming", &try_stream, op_setint, 1,1 },
+{ 0, "no-streaming", &try_stream, op_setint, 1,0 },
+{'P',"port", &port, op_integer },
{ 0, "inndconf", &inndconffile, op_string },
-{'d',"daemon", &become_daemon, op_booltrue, 1 },
-{ 0, "no-daemon", &become_daemon, op_boolfalse, 1 },
+{'d',"daemon", &become_daemon, op_setint, 1,1 },
+{ 0, "no-daemon", &become_daemon, op_setint, 1,0 },
{ 0, "no-check-proportion", &nocheck_thresh_pct, op_double },
{ 0, "no-check-filter", &nocheck_decay_articles, op_double },
{ 0, "reconnect-interval", &reconnect_delay_periods, op_periods_rndup },
{ 0, "flush-retry-interval", &flushfail_retry_periods, op_periods_rndup },
-{ 0, "connection-timeout", &connection_timeout, op_seconds },
{ 0, "inndcomm-timeout", &inndcomm_flush_timeout, op_seconds },
};
if (strchr(feedfile, c))
badusage("feed filename may not contain metacharacter %c",c);
- loop= oop_sys_new();
- if (!loop) sysdie("could not create liboop event loop");
+ oop_source_sys *sysloop= oop_sys_new();
+ if (!sysloop) sysdie("could not create liboop event loop");
+ loop= (oop_source*)sysloop;
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
sysdie("could not ignore SIGPIPE");
if (become_daemon) {
+ int i;
for (i=3; i<255; i++)
/* do this now before we open syslog, etc. */
close(i);
notice("starting");
- if (!filemon_init()) {
+ if (!filemon_method_init()) {
warn("no file monitoring available, polling");
filepoll_schedule();
}
statemc_init();
- loop->execute.
+ void *r= oop_sys_run(sysloop);
+ assert(r == OOP_ERROR);
+ sysdie("event loop failed");
}