diff options
-rw-r--r-- | pttbbs/daemon/bpop3d/Makefile | 28 | ||||
-rw-r--r-- | pttbbs/daemon/bpop3d/bpop3d.c | 278 | ||||
l--------- | pttbbs/daemon/bpop3d/server.c | 1 | ||||
l--------- | pttbbs/daemon/bpop3d/server.h | 1 |
4 files changed, 123 insertions, 185 deletions
diff --git a/pttbbs/daemon/bpop3d/Makefile b/pttbbs/daemon/bpop3d/Makefile index 7fe4684c..8503c09b 100644 --- a/pttbbs/daemon/bpop3d/Makefile +++ b/pttbbs/daemon/bpop3d/Makefile @@ -1,26 +1,22 @@ # $Id$ + SRCROOT= ../.. .include "$(SRCROOT)/pttbbs.mk" -PROGRAMS= bpop3d +PROG= bpop3d +SRCS= bpop3d.c server.c +MAN= + UTILDIR= $(SRCROOT)/util UTILOBJ= $(UTILDIR)/util_var.o -LDLIBS+=$(SRCROOT)/common/bbs/libcmbbs.a \ +CFLAGS+= $(LIBEVENT_CFLAGS) +LDFLAGS+= $(LIBEVENT_LIBS_L) + +LDADD+= $(UTILOBJ) \ + $(SRCROOT)/common/bbs/libcmbbs.a \ $(SRCROOT)/common/sys/libcmsys.a \ $(SRCROOT)/common/osdep/libosdep.a \ - -lcrypt -levent - -all: ${PROGRAMS} - -.SUFFIXES: .c .cpp .o -.c.o: - $(CC) $(CFLAGS) -c $*.c -.cpp.o: - $(CXX) $(CXXFLAGS) -c $*.cpp - -bpop3d: bpop3d.o $(UTILOBJ) - ${CC} ${CFLAGS} ${LDFLAGS} -o $* $> $(LDLIBS) + $(LIBEVENT_LIBS_l) -lcrypt -clean: - rm -f *~ ${PROGRAMS} bpop3d.o +.include <bsd.prog.mk> diff --git a/pttbbs/daemon/bpop3d/bpop3d.c b/pttbbs/daemon/bpop3d/bpop3d.c index 116cf7ec..6838d6db 100644 --- a/pttbbs/daemon/bpop3d/bpop3d.c +++ b/pttbbs/daemon/bpop3d/bpop3d.c @@ -1,30 +1,22 @@ /* $Id$ */ + #define _GNU_SOURCE -#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <strings.h> -#include <sys/time.h> #include <sys/types.h> #include <unistd.h> -#include <event.h> - -#include "bbs.h" +#include <event2/buffer.h> +#include <event2/bufferevent.h> -static struct timeval tv = {600, 0}; -static struct event ev_listen; -static int clients = 0; +#include <cmsys.h> +#include <cmbbs.h> +#include <var.h> -#define READ_BLOCK 512 -#define MAX_CLIENTS 500 +#include "server.h" -struct client_state { - struct event ev; +struct pop3_ctx { int state; - int pop3_state; - struct evbuffer *evb_read; - struct evbuffer *evb_write; char userid[32]; int uid; }; @@ -38,63 +30,81 @@ enum { typedef struct { char *cmd; - void (*func)(struct client_state *cs, const char * arg); + void (*func)(struct bufferevent *, struct pop3_ctx *, int argc, char **); } CMD; +static const char msg_ok[] = "+OK\r\n"; +static const char msg_err_no_user[] = "-ERR user not found\r\n"; +static const char msg_err_no_msg[] = "-ERR no such message\r\n"; + void -cmd_unknown(struct client_state *cs, const char * arg) +cmd_unknown(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "-ERR unknown command\r\n"); + static const char msg[] = "-ERR unknown command\r\n"; + evbuffer_add_reference(bufferevent_get_output(bev), msg, strlen(msg), NULL, NULL); } void -cmd_capa(struct client_state *cs, const char * arg) +cmd_capa(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "+OK\r\nUSER\r\n.\r\n"); + static const char msg[] = "+OK\r\nUSER\r\n.\r\n"; + evbuffer_add_reference(bufferevent_get_output(bev), msg, strlen(msg), NULL, NULL); } void -cmd_user(struct client_state *cs, const char * arg) +cmd_user(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - cs->uid = searchuser(arg, cs->userid); - if (cs->uid < 1 || cs->uid > MAX_USERS) - evbuffer_add_printf(cs->evb_write, "-ERR user not found\r\n"); + ctx->uid = searchuser(*argv, ctx->userid); + if (ctx->uid < 1 || ctx->uid > MAX_USERS) + evbuffer_add_reference(bufferevent_get_output(bev), + msg_err_no_user, strlen(msg_err_no_user), NULL, NULL); else - evbuffer_add_printf(cs->evb_write, "+OK\r\n"); + evbuffer_add_reference(bufferevent_get_output(bev), + msg_ok, strlen(msg_ok), NULL, NULL); } void -cmd_pass(struct client_state *cs, const char * arg) +cmd_pass(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { userec_t xuser; char * pw; - if (passwd_query(cs->uid, &xuser) < 0) { - evbuffer_add_printf(cs->evb_write, "-ERR user not found\r\n"); + if (passwd_query(ctx->uid, &xuser) < 0) { + evbuffer_add_reference(bufferevent_get_output(bev), + msg_err_no_user, strlen(msg_err_no_user), NULL, NULL); return; } - pw = crypt(arg, xuser.passwd); + pw = crypt(*argv, xuser.passwd); if (strcmp(pw, xuser.passwd) == 0) { - evbuffer_add_printf(cs->evb_write, "+OK\r\n"); - cs->pop3_state = POP3_TRANS; + evbuffer_add_reference(bufferevent_get_output(bev), + msg_ok, strlen(msg_ok), NULL, NULL); + ctx->state = POP3_TRANS; + } else { + static const char msg[] = "-ERR password incorrect \r\n"; + evbuffer_add_reference(bufferevent_get_output(bev), + msg, strlen(msg), NULL, NULL); } - else - evbuffer_add_printf(cs->evb_write, "-ERR password incorrect \r\n"); } void -cmd_quit(struct client_state *cs, const char * arg) +cmd_quit(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "+OK bye\r\n"); + static const char msg[] = "+OK bye\r\n"; + evbuffer_add_reference(bufferevent_get_output(bev), + msg, strlen(msg), NULL, NULL); - if (cs->pop3_state == POP3_TRANS) - cs->pop3_state = POP3_UPDATE; + const struct timeval tv = {0, 1000}; + bufferevent_set_timeouts(bev, &tv, &tv); + + if (ctx->state == POP3_TRANS) + ctx->state = POP3_UPDATE; else - cs->pop3_state = POP3_CLEANUP; + ctx->state = POP3_CLEANUP; } static const CMD auth_cmdlist[] = { + {"user", cmd_user}, {"pass", cmd_pass}, {"quit", cmd_quit}, @@ -104,42 +114,49 @@ static const CMD auth_cmdlist[] = { /* Transaction state commands not implemented */ void -cmd_stat(struct client_state *cs, const char * arg) +cmd_stat(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "+OK 0 0\r\n"); + static const char msg[] = "+OK 0 0\r\n"; + evbuffer_add_reference(bufferevent_get_output(bev), msg, strlen(msg), NULL, NULL); } void -cmd_list(struct client_state *cs, const char * arg) +cmd_list(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - if (*arg) - evbuffer_add_printf(cs->evb_write, "-ERR no such message\r\n"); + static const char msg[] = "+OK\r\n.\r\n"; + if (*argv) + evbuffer_add_reference(bufferevent_get_output(bev), + msg_err_no_msg, strlen(msg_err_no_msg), NULL, NULL); else - evbuffer_add_printf(cs->evb_write, "+OK\r\n.\r\n"); + evbuffer_add_reference(bufferevent_get_output(bev), msg, strlen(msg), NULL, NULL); } void -cmd_retr(struct client_state *cs, const char * arg) +cmd_retr(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "-ERR no such message\r\n"); + evbuffer_add_reference(bufferevent_get_output(bev), + msg_err_no_msg, strlen(msg_err_no_msg), NULL, NULL); } void -cmd_dele(struct client_state *cs, const char * arg) +cmd_dele(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "-ERR no such message\r\n"); + evbuffer_add_reference(bufferevent_get_output(bev), + msg_err_no_msg, strlen(msg_err_no_msg), NULL, NULL); } void -cmd_noop(struct client_state *cs, const char * arg) +cmd_noop(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "+OK\r\n"); + evbuffer_add_reference(bufferevent_get_output(bev), + msg_ok, strlen(msg_ok), NULL, NULL); } void -cmd_rset(struct client_state *cs, const char * arg) +cmd_rset(struct bufferevent *bev, struct pop3_ctx *ctx, int argc, char **argv) { - evbuffer_add_printf(cs->evb_write, "+OK\r\n"); + evbuffer_add_reference(bufferevent_get_output(bev), + msg_ok, strlen(msg_ok), NULL, NULL); } static const CMD trans_cmdlist[] = { @@ -155,145 +172,68 @@ static const CMD trans_cmdlist[] = { }; void -cb_client(int cfd, short event, void *arg) +client_read_cb(struct bufferevent *bev, void *ctx) { - struct client_state *cs = arg; - char *p, *line = NULL; - int i; - - // ignore clients that timeout - if (event & EV_TIMEOUT) - cs->pop3_state = POP3_CLEANUP; - - if (event & EV_READ) - if (evbuffer_read(cs->evb_read, cfd, READ_BLOCK) <= 0) - cs->pop3_state = POP3_CLEANUP; - - if (event & EV_WRITE) - if (evbuffer_write(cs->evb_write, cfd) <= 0) - cs->pop3_state = POP3_CLEANUP; - - if ((line = evbuffer_readline(cs->evb_read)) == NULL) - goto out; + int argc, i; + char **argv; + size_t len; + struct evbuffer *input = bufferevent_get_input(bev); + char *line = evbuffer_readln(input, &len, EVBUFFER_EOL_CRLF); + struct pop3_ctx *pop3_ctx = ctx; + + if (!line) + return; - for (p = line; *p != ' ' && *p != '\0'; p++); - if (*p == ' ') - *p++ = '\0'; + argc = split_args(line, &argv); - if (cs->pop3_state == POP3_AUTH) { + if (pop3_ctx->state == POP3_AUTH) { for (i = 0; auth_cmdlist[i].cmd; i++) - if (strcasecmp(line, auth_cmdlist[i].cmd) == 0) + if (evutil_ascii_strcasecmp(argv[0], auth_cmdlist[i].cmd) == 0) break; - (auth_cmdlist[i].func)(cs, p); - } else if (cs->pop3_state == POP3_TRANS) { + (auth_cmdlist[i].func)(bev, ctx, argc - 1, argv + 1); + } else if (pop3_ctx->state == POP3_TRANS) { for (i = 0; trans_cmdlist[i].cmd; i++) - if (strcasecmp(line, trans_cmdlist[i].cmd) == 0) + if (evutil_ascii_strcasecmp(argv[0], trans_cmdlist[i].cmd) == 0) break; - (trans_cmdlist[i].func)(cs, p); - } - -out: - evbuffer_write(cs->evb_write, cfd); - - if (cs->pop3_state == POP3_UPDATE) { - cs->pop3_state = POP3_CLEANUP; + (trans_cmdlist[i].func)(bev, ctx, argc - 1, argv + 1); } - if (cs->pop3_state == POP3_CLEANUP) { - if (clients == MAX_CLIENTS) - event_add(&ev_listen, NULL); - close(cfd); - evbuffer_free(cs->evb_write); - evbuffer_free(cs->evb_read); - free(cs); - clients--; - return; - } - - if (EVBUFFER_LENGTH(cs->evb_write) > 0) - event_set(&cs->ev, cfd, EV_WRITE, (void *) cb_client, cs); - else - event_set(&cs->ev, cfd, EV_READ, (void *) cb_client, cs); - event_add(&cs->ev, &tv); + free(argv); + free(line); } void -setup_client(int fd) +client_event_cb(struct bufferevent *bev, short events, void *ctx) { - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); - - struct client_state *cs = calloc(1, sizeof(struct client_state)); - cs->state = EV_WRITE; - cs->pop3_state = POP3_AUTH; - cs->evb_read = evbuffer_new(); - cs->evb_write = evbuffer_new(); - - evbuffer_add_printf(cs->evb_write, "+OK PttBBS POP3 ready\r\n"); - event_set(&cs->ev, fd, EV_WRITE, (void *) cb_client, cs); - event_add(&cs->ev, &tv); + if (events & (BEV_EVENT_EOF | BEV_EVENT_TIMEOUT | BEV_EVENT_ERROR)) { + bufferevent_free(bev); + free(ctx); + } } -void -cb_listen(int fd, short event, void *arg) +void setup_client(struct event_base *base, evutil_socket_t fd, + struct sockaddr *address, int socklen) { - struct sockaddr_in clientaddr; - socklen_t len = sizeof(clientaddr); - int cfd; + struct pop3_ctx *ctx = calloc(1, sizeof(struct pop3_ctx)); + ctx->state = POP3_AUTH; - if ((cfd = accept(fd, (struct sockaddr *)&clientaddr, &len)) < 0 ) - return; + struct bufferevent *bev = bufferevent_socket_new(base, fd, + BEV_OPT_CLOSE_ON_FREE); + bufferevent_setcb(bev, client_read_cb, NULL, client_event_cb, ctx); + bufferevent_set_timeouts(bev, common_timeout, common_timeout); + bufferevent_enable(bev, EV_READ|EV_WRITE); - setup_client(cfd); - - clients++; - - if (clients > MAX_CLIENTS) - event_del(&ev_listen); + evbuffer_add_reference(bufferevent_get_output(bev), + "+OK PttBBS POP3 ready\r\n", 23, NULL, NULL); } -int main(int argc, char *argv[]) +void +setup_program() { - int ch, sfd=0, inetd = 0, daemon = 1; - char *iface_ip = "127.0.0.1:5140"; - - Signal(SIGPIPE, SIG_IGN); - while ((ch = getopt(argc, argv, "Dil:h")) != -1) - switch (ch) { - case 'D': - daemon = 0; - break; - case 'i': - inetd = 1; - break; - case 'l': - iface_ip = optarg; - break; - case 'h': - default: - fprintf(stderr, "usage: bpop3d [-D] [-i] [-l [interface_ip]:port]\n"); - return 1; - } - - if (!inetd) - if ((sfd = tobind(iface_ip)) < 0) - return 1; - setuid(BBSUID); setgid(BBSGID); + chdir(BBSHOME); - srandom(getpid() + time(NULL)); attach_SHM(); - - if (daemon) - daemonize(BBSHOME "/run/bpop3d.pid", NULL); - - event_init(); - if (!inetd) { - event_set(&ev_listen, sfd, EV_READ | EV_PERSIST, cb_listen, &ev_listen); - event_add(&ev_listen, NULL); - } else - setup_client(0); - event_dispatch(); - - return 0; } + diff --git a/pttbbs/daemon/bpop3d/server.c b/pttbbs/daemon/bpop3d/server.c new file mode 120000 index 00000000..88ec683f --- /dev/null +++ b/pttbbs/daemon/bpop3d/server.c @@ -0,0 +1 @@ +../barebone/server.c
\ No newline at end of file diff --git a/pttbbs/daemon/bpop3d/server.h b/pttbbs/daemon/bpop3d/server.h new file mode 120000 index 00000000..75e7076e --- /dev/null +++ b/pttbbs/daemon/bpop3d/server.h @@ -0,0 +1 @@ +../barebone/server.h
\ No newline at end of file |