OSSP CVS Repository

ossp - Check-in [567]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 567
Date: 2001-Jul-25 13:29:38 (local)
2001-Jul-25 11:29:38 (UTC)
User:thl
Branch:
Comment: shortly before lmtp_message/lmtp_reset are vanished
Tickets:
Inspections:
Files:
ossp-pkg/lmtp2nntp/00TODO      1.4 -> 1.5     6 inserted, 0 deleted
ossp-pkg/lmtp2nntp/lmtp.c      1.3 -> 1.4     152 inserted, 70 deleted
ossp-pkg/lmtp2nntp/lmtp.h      1.3 -> 1.4     7 inserted, 2 deleted
ossp-pkg/lmtp2nntp/lmtp2nntp.c      1.3 -> 1.4     73 inserted, 8 deleted

ossp-pkg/lmtp2nntp/00TODO 1.4 -> 1.5

--- 00TODO       2001/07/24 11:32:06     1.4
+++ 00TODO       2001/07/25 11:29:38     1.5
@@ -58,3 +58,9 @@
 o cw.alert@news.de.cw.net
   cw.alert: "|lmtp2nntp ... -d cw.alert"
 
+ID logging problem
+
+lmtp_reset() is to be called from a callback, usually RSET. It cleans up all
+messages, see lmtp_message().
+
+


ossp-pkg/lmtp2nntp/lmtp.c 1.3 -> 1.4

--- lmtp.c       2001/07/24 11:32:07     1.3
+++ lmtp.c       2001/07/25 11:29:38     1.4
@@ -41,14 +41,19 @@
 }
 /*************************************************************************/
 
-/*
- * 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)
 {
+    /*  read a line
+     *
+     *  NOTE: the underlying readline() already reduces any CR/LF combination
+     *        to a string terminating zero.
+     *
+     *  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
+     */
+
     size_t n;
     char c;
     lmtp_readline_t *rl = &lmtp->rl;
@@ -91,6 +96,15 @@
 
 lmtp_t *lmtp_create(int rfd, int wfd, lmtp_io_t *io)
 {
+    /*  create a lmtp structure allocating memory for it and initializing it.
+     *  A lmtp_cb_default() callback is registered for the default "" verb.
+     *  The _rfd_ and _wfd_ args are passed to the read(), write() and
+     *  select() functions and must have meaning for them. If _io_ is NULL,
+     *  the system io functions are used. You can provide an _io_ structure
+     *  and specify alternate functions. Ommiting one or more functions inside
+     *  the _io_ structure by NULLing it causes use of the system default
+     *  function.
+     */
     lmtp_t *lmtp = NULL;
 
     if ((lmtp = (lmtp_t *)malloc(sizeof(lmtp_t))) == NULL) 
@@ -123,12 +137,33 @@
 
 void lmtp_destroy(lmtp_t *lmtp)
 {
-    free(lmtp);
+    int i;
+    lmtp_msg_t *msg;
+    lmtp_msg_t *next;
+
+    //_readmsg : if ((cpBuf = (char *)malloc(nBuf)) == NULL)
+
+    for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) {
+        msg  = lmtp->dispatch[i]->msg;
+        do {
+            next = lmtp->dispatch[i]->msg->next;
+            free(msg);              /* linked messages */
+            msg  = next;
+        } while(next != NULL);
+        free(lmtp->dispatch[i]);    /* lmtp_register() */
+    }
+    free(lmtp->dispatch);           /* lmtp_create() */
+    free(lmtp);                     /* lmtp_create() */
     return;
 }
 
 lmtp_rc_t lmtp_readline(lmtp_t *lmtp, char *buf, size_t buflen)
 {
+    /*  read a line
+     *
+     *  NOTE: the underlying readline() already reduces any CR/LF combination
+     *        to a string terminating zero.
+     */
     lmtp_rc_t rc;
 
     rc = readline(lmtp, buf, buflen);
@@ -140,13 +175,19 @@
 
 lmtp_rc_t lmtp_readmsg(lmtp_t *lmtp, char **cppBuf, size_t maxlen)
 {
-    /* read lines until end of message, unescape dots
+    /*  read lines until end of message, unescape dots
      *
-     * RFC821 "Simple Mail Transfer Protocol" [...] 4.5.2. TRANSPARENCY [...]
-     * When a line of mail text is received by the receiver-SMTP it checks
-     * the line.  If the line is composed of a single period it is the end of
-     * mail.  If the first character is a period and there are other
-     * characters on the line, the first character is deleted. [...]
+     *  NOTE: the lmtp_readline()'s underlying readline() already reduces any
+     *        CR/LF combination to a string terminating zero. Callers of this
+     *        function must assume multiline messages have lines terminated
+     *        with NL only.
+     *
+     *  RFC821 "Simple Mail Transfer Protocol" [excerpt]
+     *  4.5.2. TRANSPARENCY
+     *  When a line of mail text is received by the receiver-SMTP it checks
+     *  the line.  If the line is composed of a single period it is the end of
+     *  mail.  If the first character is a period and there are other
+     *  characters on the line, the first character is deleted.
      */
 
     lmtp_rc_t rc = LMTP_OK;
@@ -158,48 +199,39 @@
     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;
+    if ((cpBuf = (char *)malloc(nBuf)) == NULL) return LMTP_ERR_MEM;
+    *cppBuf = cpBuf;                           /* tell caller about the buffer */
+    cpPtr = cpBuf;                             /* initialize write cursor */
+    cpLine = cpBuf;                            /* initialize start of line */
     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 (nBuf == maxlen) return LMTP_ERR_OVERFLOW;
+            offset = nBuf-1;                    /* write cursor offset is end of buffer */
+            offsetline = cpLine - cpBuf;        /* remember start of line offset */
+            nBuf *= 2;                          /* increase buffer */
+            if (nBuf > maxlen) nBuf = maxlen;   /* but don't exceed maximum */
             if ((cpBuf = (char *)realloc(cpBuf, nBuf)) == NULL) {
-                free(cpBuf);
+                free(cpBuf); //FIXME double check isn't this a destroy() task?  */
                 return LMTP_ERR_MEM;
             }
-            *cppBuf = cpBuf;
-            cpPtr = cpBuf + offset;
-            cpLine = cpBuf + offsetline;
+            *cppBuf = cpBuf;                    /* tell caller about the new buffer */
+            cpPtr = cpBuf + offset;             /* recover write cursor */
+            cpLine = cpBuf + offsetline;        /* recover start of line */
         }
         else if (rc == LMTP_OK) {
-            if (strcmp(cpLine, ".") == 0) {
-// printf("DEBUG: \".\" found ***%s***\n", cpLine);
-                *cpLine = '\0';
+            if (strcmp(cpLine, ".") == 0) {     /* dot alone is end of message */
+                *cpLine = '\0';                 /* hide dot from caller */
                 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;
+            if (*cpLine == '.')                 /* escaped dot */
+                memmove(cpLine, cpLine+1, strlen(cpLine+1)+1);
+            cpPtr += strlen(cpPtr);             /* write cursor to the end */
+            *cpPtr++ = '\n';                    /* artifical NL */
+            *cpPtr = '\0';                      /* artifical end of string */
+            cpLine = cpPtr;                     /* start of line */
         }
+        else break;                             /* rc == LMTP_ERR* */
     }
     return rc;
 }
@@ -210,10 +242,17 @@
      *  pulls the verb out and attaches the verb to req->verb;
      * 
      *  LMTP_OK           req->msg set, req->verb set  means normal operation
+     *  LMTP_OK           req->msg set, req->verb ""   means no verb seen
      *  LMTP_EOF          req->msg set, req->verb NULL means eof
      *  LMTP_ERR_OVERFLOW req->msg set, req->verb NULL means buf overflow
      *  LMTP_ERR_SYSTEM   req->msg set, req->verb NULL means system error
-     *  LMTP_ERR_VERB     req->msg set, req->verb NULL means no verb seen
+     *
+     *  RFC821 "Simple Mail Transfer Protocol" [excerpts]
+     *  4.1.1. COMMAND SEMANTICS
+     *  The command codes themselves are alphabetic characters terminated by
+     *  <SP> if parameters follow and <CRLF> otherwise.
+     *  4.1.2. COMMAND SYNTAX
+     *  <SP> ::= the space character (ASCII code 32)
      */
 
     lmtp_rc_t rc;
@@ -230,18 +269,21 @@
         return rc;
 
     for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) {
-        if ((verb = lmtp->dispatch[i]->verb) != NULL) {
-            if ((verblen = strlen(verb)) == 0)
-                continue;
-            if(   (strlen(req->msg) >= verblen) //FIXME check for verb\s
+        if ((verb = lmtp->dispatch[i]->verb) != NULL) {  /* skip NULL verb */
+            if ((verblen = strlen(verb)) == 0) continue; /* skip  ""  verb */
+            if(   (strlen(req->msg) >= verblen)
                && (strncasecmp(req->msg, verb, verblen) == 0)
+               && (   (req->msg[verblen] == '\0')
+                   || (req->msg[verblen] == ' ')
+                   )
                ) {
                 req->verb = verb;
                 return LMTP_OK;
             }
         }
     }
-    return LMTP_ERR_VERB;
+    req->verb = "";
+    return LMTP_OK;
 }
 
 lmtp_rc_t lmtp_response(lmtp_t *lmtp, lmtp_res_t *res)
@@ -292,13 +334,15 @@
     return rc;
 }
 
-char **lmtp_message(lmtp_t *lmtp, char *verb)
+lmtp_msg_t *lmtp_message(lmtp_t *lmtp, char *verb)
 {
+    /*  get the first message attached to a verb's dispatch structure. The
+     *  messages are fifo linked lists.
+     */
     int i;
 
-    char **cpp = NULL;
-    if ((i = verbindex(lmtp, verb)) >= 0)
-        cpp = lmtp->dispatch[i]->msg;
+    lmtp_msg_t *cpp = NULL;
+    if ((i = verbindex(lmtp, verb)) >= 0) cpp = lmtp->dispatch[i]->msg;
     return cpp;
 }
 
@@ -309,21 +353,56 @@
 
 char *lmtp_error(lmtp_t *lmtp, lmtp_rc_t rc)
 {
-    char *str = NULL;
+    /*  get an error message matching the given lmtp_rc_t code usually
+     *  returned by a previously called function
+     */
+    char *str;
+
+                                 str = "LMTP: errorcode has no description";
+    if (rc == LMTP_OK          ) str = "LMTP: no error";
+    if (rc == LMTP_EOF         ) str = "LMTP: eof";
+    if (rc == LMTP_ERR_SYSTEM  ) str = "LMTP: see errno";
+    if (rc == LMTP_ERR_MEM     ) str = "LMTP: dynamic memory allocation failed";
+    if (rc == LMTP_ERR_OVERFLOW) str = "LMTP: static allocated memory exhausted";
+    if (rc == LMTP_ERR_ARG     ) str = "LMTP: invalid arg was passed to function";
+    if (rc == LMTP_ERR_UNKNOWN ) str = "LMTP: guru meditation";
+
     return str;
 }
 
 lmtp_rc_t lmtp_register(lmtp_t *lmtp, char *verb, lmtp_cb_t cb, void *ctx, lmtp_cb_t *oldcb, void **oldctx)
 {
+    /*  For _lmtp_ structure, register a _verb_ and associate a callback
+     *  function _cb_ to it. A context can be specified which will be passed
+     *  to the callback function for every call. Consider the context being
+     *  user data. The library itself does not care about the context except
+     *  passing it along.  If the verb was registered previously, the
+     *  registration is replaced and if _oldcb_ and/or _oldctx_ is given, the
+     *  previous registration is returned. Calling the previously registered
+     *  callbacks from within the newly registered callback effectively allows
+     *  hooking or chaining to a previous registered callback. The _ctx_,
+     *  _oldcb_ and _oldctx_ are optional and might be passed as NULL in case
+     *  you don't care. Setting _cb_ to NULL means to check only for a
+     *  previous registration;
+     */
     lmtp_rc_t rc = LMTP_OK;
-    int overload=0; /* overload returns old, no overload increases table */
+    int overload=0; /* overload (replacement) detected has to return old oldcb
+                       and/or oldctx, no overload requires growth of dispatch
+                       table */
     int i;
 
+    if (cb == NULL) { /* checking for existing callback only */
+        i = verbindex(lmtp, verb);
+        if (oldcb  != NULL) *oldcb  = (i == -1) ? NULL : lmtp->dispatch[i]->cb;
+        if (oldctx != NULL) *oldctx = (i == -1) ? NULL : lmtp->dispatch[i]->ctx;
+        return LMTP_OK;
+    }
+
     for (i = 0; lmtp->dispatch[i] != NULL; i++) {
         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;
+            if (oldcb  != NULL) *oldcb  = lmtp->dispatch[i]->cb;
+            if (oldctx != NULL) *oldctx = lmtp->dispatch[i]->ctx;
             break;
         }
     }
@@ -334,10 +413,9 @@
             (lmtp_dispatch_t *)malloc(sizeof(lmtp_dispatch_t))) == NULL)
             return LMTP_ERR_MEM;
         lmtp->dispatch[i+1] = NULL;
-        if(oldcb  != NULL)  *oldcb = NULL;
-        if(oldctx != NULL) *oldctx = NULL;
+        if (oldcb  != NULL) *oldcb  = NULL;
+        if (oldctx != NULL) *oldctx = NULL;
     }
-
     lmtp->dispatch[i]->verb = strdup(verb);
     lmtp->dispatch[i]->cb   = cb;
     lmtp->dispatch[i]->ctx  = ctx;
@@ -348,9 +426,16 @@
 
 lmtp_rc_t lmtp_loop(lmtp_t *lmtp)
 {
+    /*  Print a welcome message then execute a request/ dispatch loop until
+     *  request signals no more data. Each request is checked to contain a
+     *  registered verb and if a verb is found the correspondig callback is
+     *  executed. The create() function usually cares to register a default
+     *  callback in order to handle unregistered verbs. The psoudoverb for
+     *  default is the empty string "".
+     */
+    lmtp_rc_t rc = LMTP_OK;
     lmtp_req_t req;
     lmtp_res_t res;
-    lmtp_rc_t rc = LMTP_OK;
     char *verb;
     int i;
 
@@ -359,15 +444,12 @@
     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)) {
+    while ((rc = lmtp_request(lmtp, &req)) == LMTP_OK) {
         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;
+        if ((i = verbindex(lmtp, verb)) != -1) {
+            rc = lmtp->dispatch[i]->cb(lmtp, &lmtp->io, &req, lmtp->dispatch[i]->ctx);
+            if (rc != LMTP_OK) break;
+        }
     }
     return rc;
 }


ossp-pkg/lmtp2nntp/lmtp.h 1.3 -> 1.4

--- lmtp.h       2001/07/24 11:32:07     1.3
+++ lmtp.h       2001/07/25 11:29:38     1.4
@@ -27,13 +27,18 @@
     char *statusmsg;    /* message with >=0*NLs, not terminating with NL. NUL */
 } lmtp_res_t;
 
+struct lmtp_msg_st {
+    struct lmtp_msg_st *next;
+    char *msg;
+};
+typedef struct lmtp_msg_st lmtp_msg_t;
+
 typedef enum {
     LMTP_OK,
     LMTP_EOF,           /* eof */
     LMTP_ERR_SYSTEM,    /* see errno */
     LMTP_ERR_MEM,       /* dynamic memory allocation failed */
     LMTP_ERR_OVERFLOW,  /* static allocated memory exhausted */
-    LMTP_ERR_VERB,      /* search for verb failed */
     LMTP_ERR_ARG,       /* invalid arg was passed to function */
     LMTP_ERR_UNKNOWN    /* guru meditation */
 } lmtp_rc_t;
@@ -46,7 +51,7 @@
 lmtp_rc_t   lmtp_readmsg (lmtp_t *lmtp, char **buf, size_t maxlen);
 lmtp_rc_t   lmtp_request (lmtp_t *lmtp, lmtp_req_t *req);
 lmtp_rc_t   lmtp_response(lmtp_t *lmtp, lmtp_res_t *res);
-char      **lmtp_message (lmtp_t *lmtp, char *verb);
+lmtp_msg_t *lmtp_message (lmtp_t *lmtp, char *verb);
 void        lmtp_reset   (lmtp_t *lmtp);
 char       *lmtp_error   (lmtp_t *lmtp, lmtp_rc_t rc);
 lmtp_rc_t   lmtp_register(lmtp_t *lmtp, char *verb, lmtp_cb_t cb, void *ctx, lmtp_cb_t *oldcb, void **oldctx);


ossp-pkg/lmtp2nntp/lmtp2nntp.c 1.3 -> 1.4

--- lmtp2nntp.c  2001/07/24 11:32:07     1.3
+++ lmtp2nntp.c  2001/07/25 11:29:38     1.4
@@ -37,6 +37,8 @@
 static lmtp_rc_t lmtp_cb_mail   (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
 static lmtp_rc_t lmtp_cb_rcpt   (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
 static lmtp_rc_t lmtp_cb_data   (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
+static lmtp_rc_t lmtp_cb_noop   (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
+static lmtp_rc_t lmtp_cb_rset   (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
 static lmtp_rc_t lmtp_cb_quit   (lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx);
 
 static void usage(char *command);
@@ -44,9 +46,30 @@
 
 int main(int argc, char **argv)
 {
-    int i; // general purpose scratch int, index ...
+    int i; /* general purpose scratch int, index ... */
 
-    // read in the arguments
+    {
+        char buf[1000];
+        int bufused = 0;
+        int tracefile;
+
+// printf("DEBUG: start of argdump\n", buf);
+        for (i=0; i<argc; i++) {
+// printf("DEBUG: [%d]=***%s***\n", i, argv[i]);
+            bufused+=sprintf(buf+bufused, "[%d]=\"%s\"\n", i, argv[i]);
+        }
+// printf("DEBUG: buffer ***%s***\n", buf);
+        if ((tracefile = open("/tmp/t", O_CREAT|O_WRONLY|O_APPEND, 0664)) != -1) {
+            write(tracefile, buf, bufused);
+// printf("DEBUG: writing\n", buf);
+            close(tracefile);
+        }
+// printf("DEBUG: end of argdump\n", buf);
+    }
+
+    /* read in the arguments */
+
+#if 0
 
     while ((i = getopt(argc, argv, "p:l:h:m:tv")) != -1)
         switch (i) {
@@ -68,7 +91,8 @@
                 //FIXME exit(ERR_EXECUTION);
         }
     argc -= optind; argv += optind; // remaining args is/are newsgroup/s
-
+#endif
+    
     //FIXME printf("Hello, World!\n");
     test();
     //FIXME printf("Hello, Again!\n");
@@ -133,6 +157,7 @@
     lmtp_io_t io;
 #define BUFLEN 100
     char buf[BUFLEN];
+    lmtp_cb_t oldcb = NULL;
     
 
     io.read=trace_read;
@@ -140,10 +165,14 @@
     io.select=select;
     lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO, &io);
     // lmtp_debug_dumplmtp(lmtp);
-    lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, NULL, NULL, NULL);
+    lmtp_register(lmtp, "LHLO",         NULL, NULL,&oldcb,NULL); // printf("DEBUG: 1 oldcb=%d\n", (int)oldcb);
+    lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, NULL,&oldcb,NULL); // printf("DEBUG: 2 oldcb=%d\n", (int)oldcb);
+    lmtp_register(lmtp, "LHLO",         NULL, NULL,&oldcb,NULL); // printf("DEBUG: 3 oldcb=%d\n", (int)oldcb);
     lmtp_register(lmtp, "MAIL", lmtp_cb_mail, NULL, NULL, NULL);
     lmtp_register(lmtp, "RCPT", lmtp_cb_rcpt, NULL, NULL, NULL);
     lmtp_register(lmtp, "DATA", lmtp_cb_data, NULL, NULL, NULL);
+    lmtp_register(lmtp, "NOOP", lmtp_cb_noop, NULL, NULL, NULL);
+    lmtp_register(lmtp, "RSET", lmtp_cb_rset, NULL, NULL, NULL);
     lmtp_register(lmtp, "QUIT", lmtp_cb_quit, NULL, NULL, NULL);
     // lmtp_debug_dumplmtp(lmtp);
 
@@ -179,7 +208,13 @@
     lmtp_rc_t rc = LMTP_OK;
     res.statuscode = "250";
     res.dsncode    = NULL; /* DSN not used for greeting */
-    res.statusmsg  = "ENHANCEDSTATUSCODES\nDSN"; /* RFC2034, RFC1894 */
+    res.statusmsg  = "ENHANCEDSTATUSCODES\nDSN\nPIPELINING\n8BITMIME";
+        /*
+         *  RFC2034 = EHANCEDSTATUSCODES
+         *  RFC1894 = DSN
+         *  RFC1854 = PIPELINING
+         *  RFC1652 = 8BITMIME
+         */
     lmtp_response(lmtp, &res);
     return rc;
 }
@@ -190,22 +225,32 @@
     lmtp_rc_t rc = LMTP_OK;
     res.statuscode = "553";
     res.dsncode    = "5.1.8";
-    res.statusmsg  = "bad sender FIXME";
+    res.statusmsg  = "Bad sender FIXME";
     res.statuscode = "250";
     res.dsncode    = "2.1.0";
-    res.statusmsg  = "sender ok FIXME";
+    res.statusmsg  = "Sender ok FIXME";
     lmtp_response(lmtp, &res);
     return rc;
 }
 
 static lmtp_rc_t lmtp_cb_rcpt(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
 {
-    lmtp_res_t res;
     lmtp_rc_t rc = LMTP_OK;
+    lmtp_res_t res;
+    char **cp;
+
     res.statuscode = "250";
     res.dsncode    = "2.1.5";
     res.statusmsg  = "Recipient ok FIXME";
     lmtp_response(lmtp, &res);
+
+    cp = lmtp_message(lmtp, "RCPT");
+    if (cp == NULL) {
+        printf("DEBUG: cp=NULL\n");
+    } else {
+        printf("DEBUG: cp=%d\n", cp);
+    }
+
     return rc;
 }
 
@@ -242,6 +287,26 @@
     return rc;
 }
 
+static lmtp_rc_t lmtp_cb_noop(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    = "2.0.0";
+    res.statusmsg  = "OK";
+    lmtp_response(lmtp, &res);
+    return rc;
+}
+static lmtp_rc_t lmtp_cb_rset(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    = "2.0.0";
+    res.statusmsg  = "Reset state.";
+    lmtp_response(lmtp, &res);
+    return rc;
+}
 static lmtp_rc_t lmtp_cb_quit(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx)
 {
     lmtp_res_t res;

CVSTrac 2.0.1