--- lmtp.c 2001/07/23 12:14:06 1.2
+++ lmtp.c 2001/07/24 11:32:07 1.3
@@ -1,67 +1,21 @@
+/* standard headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
+/* third-party headers */
+// #include "str.h"
+
+/* own headers */
#include "lmtp.h"
#include "lmtp_p.h"
-lmtp_rc_t lmtp_cb_default(lmtp_io_t *io, lmtp_req_t *req, lmtp_res_t *res, void *ctx);
-lmtp_rc_t lmtp_cb_lhlo(lmtp_io_t *io, lmtp_req_t *req, lmtp_res_t *res, void *ctx);
-lmtp_rc_t lmtp_cb_quit(lmtp_io_t *io, lmtp_req_t *req, lmtp_res_t *res, void *ctx);
-
int verbindex(lmtp_t *lmtp, char *verb);
+lmtp_rc_t lmtp_cb_default(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
-/*
- * test a function
- *
- */
-
-void lmtp_debug_dumplmtp(lmtp_t *lmtp);
-void test(void)
-{
- lmtp_t *lmtp;
- lmtp_rc_t rc;
- lmtp_req_t req;
- lmtp_res_t res;
-#define BUFLEN 100
- char buf[BUFLEN];
-
-
- printf("DEBUG: 01 lmtp_create\n"); lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO, NULL);
- // printf("DEBUG: 02\n"); lmtp_debug_dumplmtp(lmtp);
- printf("DEBUG: 03 lmtp_register\n"); lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, NULL, NULL, NULL);
- printf("DEBUG: 03 lmtp_register\n"); lmtp_register(lmtp, "QUIT", lmtp_cb_quit, NULL, NULL, NULL);
- // printf("DEBUG: 04\n"); lmtp_debug_dumplmtp(lmtp);
-
- /*
- printf("DEBUG: 05 lmtp_response\n"); res.statuscode="123";
- res.dsncode="1.2.3";
- res.statusmsg="Hello,\nthis is a\nmultiline\nmessage";
- lmtp_response(lmtp, &res);
- */
-
- /*
- do {
- rc = lmtp_readline(lmtp, buf, BUFLEN);
- printf("DEBUG: 06 lmtp_readline=%d ***%s***\n", rc, buf);
- } while(rc == LMTP_OK);
- */
-
- /*
- do {
- rc = lmtp_request(lmtp, &req);
- printf("DEBUG: 07 lmtp_request=%d ***%s***%s***\n", rc, req.verb, req.msg);
- } while(rc == LMTP_OK || rc == LMTP_ERR_VERB);
- */
-
- printf("DEBUG: 08 lmtp_loop=%d\n", lmtp_loop(lmtp));
-
- printf("DEBUG: 99.\n");
- return;
-}
void lmtp_debug_dumplmtp(lmtp_t *lmtp)
{
@@ -88,10 +42,10 @@
/*************************************************************************/
/*
- * return > 0 number of chars read
- * return = 0 end of file, no chars inside
- * return = -1 buffer overrun, chars inside but no newline seen
- * return = -2 io error (errno), buffer content undefined
+ * return >= 0 number of chars read, zero is empty line
+ * return = -1 end of file, no chars inside
+ * return = -2 buffer overrun, chars inside but no newline seen
+ * return = -3 io error (errno), buffer content undefined
*/
static int readline(lmtp_t *lmtp, char *buf, size_t buflen)
{
@@ -104,9 +58,9 @@
/* fetch one character (but read more) */
if (rl->rl_cnt <= 0) {
if ((rl->rl_cnt = lmtp->io.read(lmtp->rfd, rl->rl_buf, LMTP_LINE_MAXLEN)) < 0)
- return -2; /* error see errno */
+ return -3; /* error see errno */
if (rl->rl_cnt == 0)
- return 0; /* EOF */
+ return -1; /* EOF */
rl->rl_bufptr = rl->rl_buf;
}
@@ -121,7 +75,7 @@
}
buf[n] = '\0'; /* string termination */
- return (n == (buflen-1)) ? -1 : n;
+ return (n == (buflen-1)) ? -2 : n;
}
int verbindex(lmtp_t *lmtp, char *verb)
@@ -144,12 +98,12 @@
if(io == NULL) {
lmtp->io.select = select;
- lmtp->io.read = read;
- lmtp->io.write = write;
+ lmtp->io.read = read;
+ lmtp->io.write = write;
} else {
- lmtp->io.select = io->select;
- lmtp->io.read = io->read;
- lmtp->io.write = io->write;
+ lmtp->io.select = io->select ? io->select : select;
+ lmtp->io.read = io->read ? io->read : read;
+ lmtp->io.write = io->write ? io->write : write;
}
lmtp->rl.rl_cnt = 0;
lmtp->rl.rl_bufptr = NULL;
@@ -162,6 +116,8 @@
lmtp->dispatch[0] = NULL;
+ lmtp_register(lmtp, "", lmtp_cb_default, NULL, NULL, NULL);
+
return lmtp;
}
@@ -176,13 +132,13 @@
lmtp_rc_t rc;
rc = readline(lmtp, buf, buflen);
- if(rc == -2) return LMTP_ERR_SYSTEM; /* io error (errno), buffer content undefined */
- if(rc == -1) return LMTP_ERR_OVERFLOW; /* buffer overrun, chars inside but no newline seen */
- if(rc == 0) return LMTP_EOF; /* end of file, no chars inside */
+ if(rc == -3) return LMTP_ERR_SYSTEM; /* io error (errno), buffer content undefined */
+ if(rc == -2) return LMTP_ERR_OVERFLOW; /* buffer overrun, chars inside but no newline seen */
+ if(rc == -1) return LMTP_EOF; /* end of file, no chars inside */
return LMTP_OK;
}
-lmtp_rc_t lmtp_readmsg(lmtp_t *lmtp, char *buf, size_t buflen)
+lmtp_rc_t lmtp_readmsg(lmtp_t *lmtp, char **cppBuf, size_t maxlen)
{
/* read lines until end of message, unescape dots
*
@@ -194,12 +150,57 @@
*/
lmtp_rc_t rc = LMTP_OK;
- do {
- rc = lmtp_readline(lmtp, buf, buflen);
- printf("DEBUG: 06 lmtp_readline=%d ***%s***\n", rc, buf);
- if (strcmp(buf, ".") == 0) break;
- } while(rc == LMTP_OK);
-/*FIXME escaping and more missing*/
+ char *cpBuf; /* buffer as a whole */
+ char *cpPtr; /* write cursor */
+ char *cpLine; /* start of the current line (see offsetline) */
+ size_t nBuf; /* size of buffer, doubled through realloc until maximum reached */
+ size_t offset; /* required when cpBuf changed through realloc */
+ size_t offsetline; /* memorizing start of line when reallocing in the middle of a line */
+
+ nBuf = 4096;
+ if ((cpBuf = (char *)malloc(nBuf)) == NULL)
+ return LMTP_ERR_MEM;
+ *cppBuf = cpBuf;
+ cpPtr = cpBuf;
+ cpLine = cpBuf;
+ while (1) {
+// printf("DEBUG: cpPtr-cpBuf=%d, nBuf=%d, nBuf-(cpPtr-cpBuf)=%d\n", cpPtr-cpBuf, nBuf, nBuf-(cpPtr-cpBuf));
+ rc = lmtp_readline(lmtp, cpPtr, nBuf-(cpPtr-cpBuf));
+// printf("DEBUG: lmtp_readline()=***%s***, rc=%d\n", cpPtr, rc);
+ if (rc == LMTP_ERR_OVERFLOW) {
+ if (nBuf == maxlen)
+ return LMTP_ERR_OVERFLOW;
+ offset = nBuf-1;
+ offsetline = cpLine - cpBuf;
+ nBuf *= 2;
+ if (nBuf > maxlen)
+ nBuf = maxlen;
+ if ((cpBuf = (char *)realloc(cpBuf, nBuf)) == NULL) {
+ free(cpBuf);
+ return LMTP_ERR_MEM;
+ }
+ *cppBuf = cpBuf;
+ cpPtr = cpBuf + offset;
+ cpLine = cpBuf + offsetline;
+ }
+ else if (rc == LMTP_OK) {
+ if (strcmp(cpLine, ".") == 0) {
+// printf("DEBUG: \".\" found ***%s***\n", cpLine);
+ *cpLine = '\0';
+ break;
+ }
+ if (*cpLine == '.')
+ memmove(cpLine, cpLine+1, strlen(cpLine+1)+1); /* escaped dot */
+ cpPtr += strlen(cpPtr);
+ *cpPtr++ = '\n';
+ *cpPtr = '\0';
+ cpLine = cpPtr;
+ }
+ else {
+ /* rc == LMTP_ERR_SYSTEM, etc. */
+ break;
+ }
+ }
return rc;
}
@@ -230,8 +231,9 @@
for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) {
if ((verb = lmtp->dispatch[i]->verb) != NULL) {
- verblen = strlen(verb);
- if( (strlen(req->msg) >= verblen)
+ if ((verblen = strlen(verb)) == 0)
+ continue;
+ if( (strlen(req->msg) >= verblen) //FIXME check for verb\s
&& (strncasecmp(req->msg, verb, verblen) == 0)
) {
req->verb = verb;
@@ -318,7 +320,7 @@
int i;
for (i = 0; lmtp->dispatch[i] != NULL; i++) {
- if (strcmp(verb, lmtp->dispatch[i]->verb) == 0) {
+ if (strcasecmp(verb, lmtp->dispatch[i]->verb) == 0) {
overload=1;
if(oldcb != NULL) *oldcb = lmtp->dispatch[i]->cb;
if(oldctx != NULL) *oldctx = lmtp->dispatch[i]->ctx;
@@ -348,46 +350,36 @@
{
lmtp_req_t req;
lmtp_res_t res;
- lmtp_rc_t rc;
+ lmtp_rc_t rc = LMTP_OK;
+ char *verb;
int i;
+
+ res.statuscode = "220";
+ res.dsncode = NULL;
+ res.statusmsg = "LMTP server ready (lmtp2nntp)";
+ if ((rc = lmtp_response(lmtp, &res)) != LMTP_OK) return rc;
+
while ((rc = lmtp_request(lmtp, &req)) == LMTP_OK || (rc == LMTP_ERR_VERB)) {
- if (rc != LMTP_ERR_VERB) {
- if ((i = verbindex(lmtp, req.verb)) == -1)
- return LMTP_ERR_VERB;
- rc = lmtp->dispatch[i]->cb(&lmtp->io, &req, &res, lmtp->dispatch[i]->ctx);
- } else {
- rc = lmtp_cb_default(&lmtp->io, &req, &res, NULL);
- }
- if (lmtp_response(lmtp, &res) != LMTP_OK) break;
- if (rc != LMTP_OK) break;
+ verb = req.verb;
+ if (rc == LMTP_ERR_VERB)
+ verb = "";
+ if ((i = verbindex(lmtp, verb)) == -1)
+ return LMTP_ERR_VERB;
+ rc = lmtp->dispatch[i]->cb(lmtp, &lmtp->io, &req, lmtp->dispatch[i]->ctx);
+ if (rc != LMTP_OK)
+ break;
}
- return LMTP_OK;
-}
-
-lmtp_rc_t lmtp_cb_default(lmtp_io_t *io, lmtp_req_t *req, lmtp_res_t *res, void *ctx)
-{
- lmtp_rc_t rc = LMTP_OK;
- res->statuscode = "500";
- res->dsncode = "5.5.1";
- res->statusmsg = "Command unrecognized.";
return rc;
}
-lmtp_rc_t lmtp_cb_lhlo(lmtp_io_t *io, lmtp_req_t *req, lmtp_res_t *res, void *ctx)
+lmtp_rc_t lmtp_cb_default(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
{
+ lmtp_res_t res;
lmtp_rc_t rc = LMTP_OK;
- res->statuscode = "250";
- res->dsncode = NULL; /* DSN not used for greeting */
- res->statusmsg = "ENHANCEDSTATUSCODES\nDSN"; /* RFC2034, RFC1894 */
- return rc;
-}
-
-lmtp_rc_t lmtp_cb_quit(lmtp_io_t *io, lmtp_req_t *req, lmtp_res_t *res, void *ctx)
-{
- lmtp_rc_t rc = LMTP_EOF;
- res->statuscode = "221";
- res->dsncode = "2.0.0";
- res->statusmsg = "Closing connection.";
+ res.statuscode = "500";
+ res.dsncode = "5.5.1";
+ res.statusmsg = "Command unrecognized.";
+ lmtp_response(lmtp, &res);
return rc;
}
|