Prepare some administrivia.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
include mk/cflags.mk
-CFLAGS += --std=gnu99 -D_GNU_SOURCE -D_FORTIFY_SOURCE=2
+CFLAGS += --std=gnu99 -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 $(shell pkg-config --cflags lua5.1)
PROGRAMS = postlicyd
GENERATED = tokens.h tokens.c
postlicyd_SOURCES = \
- str.h buffer.h job.h postfix.h \
- str.c buffer.c job.c postfix.c \
+ str.h buffer.h daemon.h postfix.h \
+ str.c buffer.c daemon.c postfix.c \
postlicyd.c $(GENERATED)
-postlicyd_LIBADD = -lpthread
+postlicyd_LIBADD = -lpthread $(shell pkg-config --libs lua5.1)
# RULES ###################################################################{{{
.%.o: %.c Makefile
$(CC) $(CFLAGS) -MMD -MT ".$*.dep $@" -MF .$*.dep -g -c -o $@ $<
-.%.dep: %.c Makefile
- $(CC) $(CFLAGS) -MM -MT ".$*.o $@" -MF .$*.dep $<
+.%.dep: .%.o
.SECONDEXPANSION:
--- /dev/null
+/******************************************************************************/
+/* postlicyd: a postfix policy daemon with a lot of features */
+/* ~~~~~~~~~ */
+/* ________________________________________________________________________ */
+/* */
+/* 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 names of its contributors may not 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. */
+/******************************************************************************/
+
+/*
+ * Copyright © 2007 Pierre Habouzit
+ */
+
+#include <sys/un.h>
+
+#include "postlicyd.h"
+#include "daemon.h"
+
+int tcp_listen(const struct sockaddr *addr, socklen_t len)
+{
+ int sock;
+
+ switch (addr->sa_family) {
+ case AF_UNIX:
+ unlink(((struct sockaddr_un *)addr)->sun_path);
+ sock = socket(PF_UNIX, SOCK_STREAM, 0);
+ break;
+ case AF_INET:
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ break;
+ case AF_INET6:
+ sock = socket(PF_INET6, SOCK_STREAM, 0);
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (sock < 0) {
+ UNIXERR("socket");
+ return -1;
+ }
+
+ if (addr->sa_family != AF_UNIX) {
+ int v = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)) < 0) {
+ UNIXERR("setsockopt(SO_REUSEADDR)");
+ close(sock);
+ return -1;
+ }
+ }
+
+ if (bind(sock, addr, len) < 0) {
+ UNIXERR("bind");
+ close(sock);
+ return -1;
+ }
+
+ if (listen(sock, 0) < 0) {
+ UNIXERR("bind");
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
--- /dev/null
+/******************************************************************************/
+/* postlicyd: a postfix policy daemon with a lot of features */
+/* ~~~~~~~~~ */
+/* ________________________________________________________________________ */
+/* */
+/* 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 names of its contributors may not 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. */
+/******************************************************************************/
+
+/*
+ * Copyright © 2007 Pierre Habouzit
+ */
+
+#ifndef POSTLICYD_DAEMON_H
+#define POSTLICYD_DAEMON_H
+
+int tcp_listen(const struct sockaddr *addr, socklen_t len);
+
+#endif
+++ /dev/null
-/******************************************************************************/
-/* postlicyd: a postfix policy daemon with a lot of features */
-/* ~~~~~~~~~ */
-/* ________________________________________________________________________ */
-/* */
-/* 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 names of its contributors may not 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. */
-/******************************************************************************/
-
-/*
- * Copyright © 2007 Pierre Habouzit
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <syslog.h>
-#include <sysexits.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#ifndef EPOLLRDHUP
-# include <linux/poll.h>
-# ifdef POLLRDHUP
-# define EPOLLRDHUP POLLRDHUP
-# else
-# define EPOLLRDHUP 0
-# endif
-#endif
-
-#include "job.h"
-
-static int epollfd = -1;
-static bool sigint = false;
-
-void job_delete(job_t **job)
-{
- if (*job) {
- if ((*job)->stop) {
- (*job)->stop(*job);
- }
- if ((*job)->fd >= 0) {
- close((*job)->fd);
- }
- p_delete(job);
- }
-}
-
-static job_t *job_register_fd(job_t *job)
-{
- struct epoll_event event = { .data.ptr = job, .events = EPOLLRDHUP };
-
- if (job->mode & (JOB_READ | JOB_LISTEN)) {
- event.events |= EPOLLIN;
- }
-
- if (job->mode & (JOB_WRITE | JOB_CONN)) {
- event.events |= EPOLLOUT;
- }
-
- if (epoll_ctl(epollfd, EPOLL_CTL_ADD, job->fd, &event) < 0) {
- syslog(LOG_ERR, "epoll_ctl error: %m");
- job->error = true;
- job_delete(&job);
- }
-
- return job;
-}
-
-void job_update_mode(job_t *job, int mode)
-{
- struct epoll_event event = { .data.ptr = job, .events = EPOLLRDHUP };
-
- if (job->mode == mode)
- return;
-
- job->mode = mode;
- if (job->mode & (JOB_READ | JOB_LISTEN)) {
- event.events |= EPOLLIN;
- }
-
- if (job->mode & (JOB_WRITE | JOB_CONN)) {
- event.events |= EPOLLOUT;
- }
-
- if (epoll_ctl(epollfd, EPOLL_CTL_MOD, job->fd, &event) < 0) {
- syslog(LOG_ERR, "epoll_ctl error: %m");
- job->error = true;
- }
-}
-
-job_t *job_accept(job_t *listener, int mode)
-{
- int sock;
- job_t *res;
-
- if ((sock = accept(listener->fd, NULL, 0)) < 0) {
- syslog(LOG_ERR, "accept error: %m");
- return NULL;
- }
-
- if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK)) {
- syslog(LOG_ERR, "fcntl error: %m");
- return NULL;
- }
-
- res = job_new();
- res->fd = sock;
- res->mode = mode;
- res->process = listener->process;
- res->stop = listener->stop;
- return job_register_fd(res);
-}
-
-static void job_sighandler(int sig)
-{
- static time_t lastintr = 0;
- time_t now = time(NULL);
-
- switch (sig) {
- case SIGINT:
- if (sigint) {
- if (now - lastintr >= 1)
- break;
- } else {
- lastintr = now;
- sigint = true;
- }
- return;
-
- case SIGTERM:
- break;
-
- default:
- return;
- }
-
- syslog(LOG_ERR, "Killed...");
- exit(-1);
-}
-
-void job_initialize(void)
-{
- signal(SIGPIPE, SIG_IGN);
- signal(SIGINT, &job_sighandler);
- signal(SIGTERM, &job_sighandler);
-
- epollfd = epoll_create(128);
- if (epollfd < 0) {
- syslog(LOG_ERR, "epoll_create error: %m");
- exit(EX_OSERR);
- }
-}
-
-void job_loop(void)
-{
- while (!sigint) {
- struct epoll_event events[FD_SETSIZE];
- int todo = epoll_wait(epollfd, events, countof(events), -1);
-
- if (todo < 0) {
- if (errno == EAGAIN || errno == EINTR)
- continue;
- syslog(LOG_ERR, "epoll_wait error: %m");
- exit(EX_OSERR);
- }
-
- while (todo) {
- job_t *job = events[--todo].data.ptr;
-
- assert (job->process);
- job->process(job);
-
- if (job->error || job->done) {
- job_delete(&job);
- }
- }
- }
-}
-
-void job_shutdown(void)
-{
- if (epollfd >= 0) {
- close(epollfd);
- epollfd = -1;
- }
-}
# warn about variable use before initialization
CFLAGS += -Wuninitialized
# warn about variables which are initialized with themselves
-CFLAGS += -Winit-self
+CFLAGS += $(if $(GCC4),-Winit-self)
# warn about pointer arithmetic on void* and function pointers
CFLAGS += -Wpointer-arith
# warn about multiple declarations
CFLAGS += -Wformat-nonliteral
# do not warn about zero-length formats.
CFLAGS += -Wno-format-zero-length
-# missing prototypes
-CFLAGS += -Wmissing-prototypes
+# do not warn about strftime format with y2k issues
+CFLAGS += -Wno-format-y2k
# warn about functions without format attribute that should have one
CFLAGS += -Wmissing-format-attribute
-# barf if we change constness
-#CFLAGS += -Wcast-qual
-
* Copyright © 2006-2007 Pierre Habouzit
*/
-#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "job.h"
+#include "postlicyd.h"
#include "postfix.h"
#include "buffer.h"
#include "tokens.h"
+#if 0
+
#define ishspace(c) ((c) == ' ' || (c) == '\t')
-struct jpriv_t {
+typedef struct jpriv_t {
buffer_t ibuf;
buffer_t obuf;
query_t query;
-};
+} jpriv_t;
static jpriv_t *postfix_jpriv_init(jpriv_t *jp)
{
DO_NEW(jpriv_t, postfix_jpriv);
DO_DELETE(jpriv_t, postfix_jpriv);
-static void postfix_stop(job_t *job)
-{
- postfix_jpriv_delete(&job->jdata);
-}
-
static int postfix_parsejob(query_t *query)
{
#define PARSE_CHECK(expr, error, ...) \
if (job->jdata->obuf.len)
return;
- job_update_mode(job, JOB_READ);
-
/* fall through */
case JOB_READ:
return;
}
- job_update_mode(job, JOB_IDLE);
-
/* TODO: run the scenario */
return;
return;
}
}
+#endif
/******************************************************************************/
/*
- * Copyright © 2006 Pierre Habouzit
+ * Copyright © 2006-2007 Pierre Habouzit
*/
-#include <stdbool.h>
-#include <stdio.h>
-#include <sysexits.h>
-#include <syslog.h>
+#include <signal.h>
+#include <time.h>
+#include <getopt.h>
-#include "job.h"
+#include "postlicyd.h"
-bool cleanexit = false;
+static bool cleanexit = false;
+static bool sigint = false;
+
+static void main_sighandler(int sig)
+{
+ static time_t lastintr = 0;
+ time_t now = time(NULL);
+
+ switch (sig) {
+ case SIGINT:
+ if (sigint) {
+ if (now - lastintr >= 1)
+ break;
+ } else {
+ lastintr = now;
+ sigint = true;
+ }
+ return;
+
+ case SIGTERM:
+ break;
+
+ default:
+ return;
+ }
+
+ syslog(LOG_ERR, "Killed...");
+ exit(-1);
+}
static void main_initialize(void)
{
openlog("postlicyd", LOG_PID, LOG_MAIL);
- job_initialize();
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, &main_sighandler);
+ signal(SIGTERM, &main_sighandler);
syslog(LOG_INFO, "Starting...");
}
+static void main_loop(void)
+{
+ while (!sigint) {
+ int fd = accept(-1, NULL, 0);
+
+ if (fd < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ syslog(LOG_ERR, "accept error: %m");
+ return;
+ }
+
+ //pthread_create(NULL, NULL, job_run, (intptr_t)fd);
+ }
+}
+
static void main_shutdown(void)
{
syslog(LOG_INFO, cleanexit ? "Stopping..." : "Unclean exit...");
- job_shutdown();
closelog();
}
{
if (atexit(main_shutdown)) {
fputs("Cannot hook my atexit function, quitting !\n", stderr);
- return EX_CONFIG;
+ return EXIT_FAILURE;
}
main_initialize();
-
- job_loop();
-
+ main_loop();
cleanexit = true;
main_shutdown();
- return 0;
+ return EXIT_SUCCESS;
}
* Copyright © 2007 Pierre Habouzit
*/
-#ifndef POSTLICYD_JOB_H
-#define POSTLICYD_JOB_H
-
-#include "mem.h"
-
-enum job_mode {
- JOB_IDLE = 0x00,
- JOB_READ = 0x01,
- JOB_WRITE = 0x02,
- JOB_RDWR = JOB_READ | JOB_WRITE,
- JOB_LISTEN = 0x04,
- JOB_CONN = 0x08,
-};
-
-typedef struct jpriv_t jpriv_t;
-typedef struct job_t {
- unsigned mode : 6; /* 4 are enough, 2 used as padding */
- unsigned done : 1;
- unsigned error : 1;
- unsigned state : 24;
-
- int fd;
-
- void (*process)(struct job_t *);
- void (*stop)(struct job_t *);
-
- jpriv_t *jdata;
-} job_t;
-
-static inline job_t *job_new(void) {
- job_t *job = p_new(job_t, 1);
- job->fd = -1;
- return job;
-}
-void job_delete(job_t **job);
-
-void job_update_mode(job_t *job, int mode);
-job_t *job_accept(job_t *listener, int mode);
-
-void job_initialize(void);
-void job_loop(void);
-void job_shutdown(void);
+#ifndef POSTLICYD_H
+#define POSTLICYD_H
+
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define UNIXERR(fun) \
+ syslog(LOG_ERR, "%s:%d:%s: %s: %m", \
+ __FILE__, __LINE__, __func__, fun)
#endif