Index: ossp-pkg/lmtp2nntp/lmtp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.c,v rcsdiff -q -kk '-r1.5' '-r1.6' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.c,v' 2>/dev/null --- lmtp.c 2001/07/25 15:02:57 1.5 +++ lmtp.c 2001/07/25 19:51:12 1.6 @@ -1,96 +1,88 @@ +/* + * lmtp.c: LMTP library (implementation) + * + * Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) + * Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) + * + * This file is part of OSSP lmtp2nntp, an LMTP speaking local + * mailer which forwards mails as Usenet news articles via NNTP. + * It can be found at http://www.ossp.com/pkg/lmtp2nntp/. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose with or without fee is hereby granted, provided that + * the above copyright notice and this permission notice appear in all + * copies. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR + * 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. + */ -/* standard headers */ #include #include #include #include #include +#include -/* third-party headers */ -// #include "str.h" - -/* own headers */ #include "lmtp.h" -#include "lmtp_p.h" -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); +/* maximum LMTP protocol line length */ +#define LMTP_LINE_MAXLEN 1024 +/* maximum number of verbs/callbacks to be registered */ +#define LMTP_MAXVERBS 32 -void lmtp_debug_dumplmtp(lmtp_t *lmtp) -{ - int i; +typedef struct { + int rl_cnt; + char *rl_bufptr; + char rl_buf[LMTP_LINE_MAXLEN]; +} lmtp_readline_t; + +typedef struct { + char *verb; + lmtp_cb_t cb; + void *ctx; +} lmtp_dispatch_t; + +struct lmtp_st { + lmtp_io_t io; /* select, read, write functions */ + lmtp_readline_t rl; /* a function to read in a single line */ + lmtp_dispatch_t **dispatch; /* LMTP commands to be dispatched */ + int rfd; /* file descriptor for reading */ + int wfd; /* file descriptor for writing */ +}; - printf("lmtp = %ld \n", (long)lmtp); - printf("io.read = %ld \n", (long)lmtp->io.read); - printf("io.write = %ld \n", (long)lmtp->io.write); - printf("rl.cnt = %d \n", lmtp->rl.rl_cnt); - printf("rl.bufptr =*%39s*\n", lmtp->rl.rl_bufptr); - printf("rl.buf =*%39s*\n", lmtp->rl.rl_buf); - for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) { - printf("dispatch[i].verb =*%39s*\n", lmtp->dispatch[i]->verb); - printf("dispatch[i].cb = %ld \n", (long)lmtp->dispatch[i]->cb); - printf("dispatch[i].ctx = %ld \n", (long)lmtp->dispatch[i]->ctx); - // printf("dispatch[i].msg =*%39s*\n", lmtp->dispatch[i]->msg); - } - printf("rfd = %d \n", lmtp->rfd); - printf("wfd = %d \n", lmtp->wfd); - - return; -} -/*************************************************************************/ - -static int readline(lmtp_t *lmtp, char *buf, size_t buflen) +static int verbindex(lmtp_t *lmtp, char *verb) { - /* 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; - - for (n = 0; n < buflen-1;) { - - /* 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 -3; /* error see errno */ - if (rl->rl_cnt == 0) - return -1; /* EOF */ - rl->rl_bufptr = rl->rl_buf; - } - - /* act on fetched character */ - rl->rl_cnt--; - c = *rl->rl_bufptr++; - if (c == '\r') - continue; /* skip copying CR */ - if (c == '\n') - break; /* end of line */ - buf[n++] = c; /* output char into given buffer */ + /* returns the index of the verb or -1 if verb not registered */ + int i; - } - buf[n] = '\0'; /* string termination */ - return (n == (buflen-1)) ? -2 : n; + for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) + if (strcasecmp(lmtp->dispatch[i]->verb, verb) == 0) + return i; + return -1; } -int verbindex(lmtp_t *lmtp, char *verb) +static lmtp_rc_t lmtp_cb_default(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx) { - /* returns the index of the verb or -1 if verb not registered */ + lmtp_res_t res; + lmtp_rc_t rc = LMTP_OK; - int i; - for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) { - if (strcasecmp(lmtp->dispatch[i]->verb, verb) == 0) return i; - } - return -1; + res.statuscode = "500"; + res.dsncode = "5.5.1"; + res.statusmsg = "Command unrecognized."; + lmtp_response(lmtp, &res); + return rc; } lmtp_t *lmtp_create(int rfd, int wfd, lmtp_io_t *io) @@ -110,12 +102,13 @@ return NULL; if(io == NULL) { - lmtp->io.read = read; - lmtp->io.write = write; + lmtp->io.read = read; + lmtp->io.write = write; } else { - lmtp->io.read = io->read ? io->read : read; - lmtp->io.write = io->write ? io->write : write; + 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; lmtp->rl.rl_buf[0] = '\0'; @@ -124,7 +117,6 @@ if ((lmtp->dispatch = (lmtp_dispatch_t **)malloc(sizeof(void *)*LMTP_MAXVERBS)) == NULL) return NULL; - lmtp->dispatch[0] = NULL; lmtp_register(lmtp, "", lmtp_cb_default, NULL, NULL, NULL); @@ -136,9 +128,8 @@ { int i; - for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) { + for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) free(lmtp->dispatch[i]); /* lmtp_register() */ - } free(lmtp->dispatch); /* lmtp_create() */ free(lmtp); /* lmtp_create() */ return; @@ -146,17 +137,38 @@ 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; + /* read a line (characters until NL) from input stream */ + size_t n; + char c; + lmtp_readline_t *rl = &lmtp->rl; + + for (n = 0; n < buflen-1;) { + + /* fetch one character (but read more) */ + if (rl->rl_cnt <= 0) { + do { + rl->rl_cnt = lmtp->io.read(lmtp->rfd, rl->rl_buf, LMTP_LINE_MAXLEN); + } while (rl->rl_cnt == -1 && errno == EINTR); + if (rl->rl_cnt == -1) + return LMTP_ERR_SYSTEM; + if (rl->rl_cnt == 0) + return LMTP_EOF; + rl->rl_bufptr = rl->rl_buf; + } + + /* act on fetched character */ + rl->rl_cnt--; + c = *rl->rl_bufptr++; + if (c == '\r') + continue; /* skip copying CR */ + if (c == '\n') + break; /* end of line */ + buf[n++] = c; /* output char into given buffer */ - rc = readline(lmtp, buf, buflen); - 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 */ + } + buf[n] = '\0'; /* string termination */ + if (n == (buflen-1)) + return LMTP_ERR_OVERFLOW; return LMTP_OK; } @@ -165,7 +177,7 @@ /* read lines until end of message, unescape dots. * on success, returns a buffer which has to be free(3)d by the caller * - * NOTE: the lmtp_readline()'s underlying readline() already reduces any + * NOTE: the underlying lmtp_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. @@ -177,7 +189,6 @@ * 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; char *cpBuf; /* buffer as a whole */ char *cpBufrealloc;/* buffer before realloc */ @@ -195,11 +206,13 @@ while (1) { rc = lmtp_readline(lmtp, cpPtr, nBuf-(cpPtr-cpBuf)); if (rc == LMTP_ERR_OVERFLOW) { - if (nBuf == maxlen) return LMTP_ERR_OVERFLOW; + 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 (nBuf > maxlen) + nBuf = maxlen; /* but don't exceed maximum */ if ((cpBufrealloc = (char *)realloc(cpBuf, nBuf)) == NULL) { free(cpBuf); return LMTP_ERR_MEM; @@ -244,29 +257,24 @@ * 4.1.2. COMMAND SYNTAX * ::= the space character (ASCII code 32) */ - lmtp_rc_t rc; char *verb; int verblen; int i; req->verb = NULL; - if ((req->msg = (char *)malloc(LMTP_LINE_MAXLEN)) == (char *)NULL) return LMTP_ERR_MEM; - if ((rc = lmtp_readline(lmtp, req->msg, LMTP_LINE_MAXLEN)) != LMTP_OK) return rc; - for (i = 0; (i < LMTP_MAXVERBS) && (lmtp->dispatch[i] != NULL); i++) { 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] == ' ') - ) - ) { + 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; } @@ -283,8 +291,9 @@ * dash after the status for every line but the last one */ lmtp_rc_t rc = LMTP_OK; + int rv; int dash; - int len; + int len; char *cpS; char *cpE; char formatbuf[LMTP_LINE_MAXLEN]; @@ -292,18 +301,19 @@ if ( strlen(res->statuscode) != 3 || !isdigit(res->statuscode[0]) || !isdigit(res->statuscode[1]) - || !isdigit(res->statuscode[2]) - ) return LMTP_ERR_ARG; + || !isdigit(res->statuscode[2])) + return LMTP_ERR_ARG; - if (res->dsncode != NULL) + if (res->dsncode != NULL) { if ( (strlen(res->dsncode) != 5) || !isdigit(res->dsncode[0]) || (res->dsncode[1] != '.') || !isdigit(res->dsncode[2]) || (res->dsncode[3] != '.') || !isdigit(res->dsncode[4]) - || (res->dsncode[0] != res->statuscode[0]) - ) return LMTP_ERR_ARG; + || (res->dsncode[0] != res->statuscode[0])) + return LMTP_ERR_ARG; + } cpS = res->statusmsg; for (dash = 1; dash == 1; ) { @@ -318,7 +328,11 @@ strncpy(formatbuf+len, cpS, cpE-cpS); len += (cpE-cpS); formatbuf[len++] = '\n'; - lmtp->io.write(lmtp->wfd, formatbuf, len); + do { + rv = lmtp->io.write(lmtp->wfd, formatbuf, len); + } while (rv == -1 && errno == EINTR); + if (rv == -1) + return LMTP_ERR_SYSTEM; cpS = cpE+1; } return rc; @@ -330,7 +344,6 @@ * returned by a previously called function */ char *str; - str = "LMTP: errorcode has no description"; if (rc == LMTP_OK ) str = "LMTP: no error"; else if (rc == LMTP_EOF ) str = "LMTP: eof"; @@ -339,7 +352,6 @@ else if (rc == LMTP_ERR_OVERFLOW) str = "LMTP: static allocated memory exhausted"; else if (rc == LMTP_ERR_ARG ) str = "LMTP: invalid arg was passed to function"; else if (rc == LMTP_ERR_UNKNOWN ) str = "LMTP: guru meditation"; - return str; } @@ -359,36 +371,43 @@ * previous registration; */ lmtp_rc_t rc = LMTP_OK; - int overload=0; /* overload (replacement) detected has to return old oldcb - and/or oldctx, no overload requires growth of dispatch - 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; + 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; + overload = 1; + if (oldcb != NULL) + *oldcb = lmtp->dispatch[i]->cb; + if (oldctx != NULL) + *oldctx = lmtp->dispatch[i]->ctx; break; } } - if (i > LMTP_MAXVERBS-2) return LMTP_ERR_OVERFLOW; + if (i > LMTP_MAXVERBS-2) + return LMTP_ERR_OVERFLOW; if (!overload) { if ((lmtp->dispatch[i] = (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; @@ -414,26 +433,17 @@ res.statuscode = "220"; res.dsncode = NULL; res.statusmsg = "LMTP server ready (lmtp2nntp)"; - if ((rc = lmtp_response(lmtp, &res)) != LMTP_OK) return rc; + if ((rc = lmtp_response(lmtp, &res)) != LMTP_OK) + return rc; while ((rc = lmtp_request(lmtp, &req)) == LMTP_OK) { verb = req.verb; if ((i = verbindex(lmtp, verb)) != -1) { rc = lmtp->dispatch[i]->cb(lmtp, &lmtp->io, &req, lmtp->dispatch[i]->ctx); - if (rc != LMTP_OK) break; + if (rc != LMTP_OK) + break; } } return rc; } -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 = "500"; - res.dsncode = "5.5.1"; - res.statusmsg = "Command unrecognized."; - lmtp_response(lmtp, &res); - return rc; -} - Index: ossp-pkg/lmtp2nntp/lmtp.h RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.h,v rcsdiff -q -kk '-r1.5' '-r1.6' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.h,v' 2>/dev/null --- lmtp.h 2001/07/25 15:02:57 1.5 +++ lmtp.h 2001/07/25 19:51:12 1.6 @@ -1,3 +1,31 @@ +/* + * lmtp.h: LMTP library (API definition) + * + * Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) + * Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) + * + * This file is part of OSSP lmtp2nntp, an LMTP speaking local + * mailer which forwards mails as Usenet news articles via NNTP. + * It can be found at http://www.ossp.com/pkg/lmtp2nntp/. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose with or without fee is hereby granted, provided that + * the above copyright notice and this permission notice appear in all + * copies. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR + * 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. + */ #ifndef __LMTP_H__ #define __LMTP_H__ @@ -11,41 +39,42 @@ typedef struct lmtp_st lmtp_t; typedef struct { - ssize_t (*read) (int fd, void *buf, size_t nbytes); - ssize_t (*write) (int fd, const void *buf, size_t nbytes); + ssize_t (*read)(int, void *, size_t); + ssize_t (*write)(int, const void *, size_t); } lmtp_io_t; typedef struct { - char *verb; /* verb found */ - char *msg; /* wholly message including verb */ + char *verb; + char *msg; } lmtp_req_t; typedef struct { - char *statuscode; /* digit digit digit NUL */ - char *dsncode; /* digit dot digit dot digit NUL */ - char *statusmsg; /* message with >=0*NLs, not terminating with NL. NUL */ + char *statuscode; + char *dsncode; + char *statusmsg; } lmtp_res_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_ARG, /* invalid arg was passed to function */ - LMTP_ERR_UNKNOWN /* guru meditation */ + LMTP_EOF, + LMTP_ERR_SYSTEM, + LMTP_ERR_MEM, + LMTP_ERR_OVERFLOW, + LMTP_ERR_ARG, + LMTP_ERR_UNKNOWN } lmtp_rc_t; -typedef lmtp_rc_t (*lmtp_cb_t)(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx); +typedef lmtp_rc_t (*lmtp_cb_t)(lmtp_t *, lmtp_io_t *, lmtp_req_t *, void *); -lmtp_t *lmtp_create (int rfd, int wfd, lmtp_io_t *io); -void lmtp_destroy (lmtp_t *lmtp); -lmtp_rc_t lmtp_readline(lmtp_t *lmtp, char *buf, size_t buflen); -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_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); -lmtp_rc_t lmtp_loop (lmtp_t *lmtp); +lmtp_t *lmtp_create (int, int, lmtp_io_t *); +void lmtp_destroy (lmtp_t *); +lmtp_rc_t lmtp_readline(lmtp_t *, char *, size_t); +lmtp_rc_t lmtp_readmsg (lmtp_t *, char **, size_t); +lmtp_rc_t lmtp_request (lmtp_t *, lmtp_req_t *); +lmtp_rc_t lmtp_response(lmtp_t *, lmtp_res_t *); +char *lmtp_error (lmtp_t *, lmtp_rc_t); +lmtp_rc_t lmtp_register(lmtp_t *, char *, lmtp_cb_t, void *, lmtp_cb_t *, void **); +lmtp_rc_t lmtp_loop (lmtp_t *); #endif /* __LMTP_H__ */ + Index: ossp-pkg/lmtp2nntp/lmtp.pod RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.pod,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.pod,v' | diff -u /dev/null - -L'ossp-pkg/lmtp2nntp/lmtp.pod' 2>/dev/null --- ossp-pkg/lmtp2nntp/lmtp.pod +++ - 2024-04-26 11:01:52.076883155 +0200 @@ -0,0 +1,203 @@ +## +## lmtp.pod: LMTP library (Unix manual page) +## +## Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) +## Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) +## +## This file is part of OSSP lmtp2nntp, an LMTP speaking local +## mailer which forwards mails as Usenet news articles via NNTP. +## It can be found at http://www.ossp.com/pkg/lmtp2nntp/. +## +## Permission to use, copy, modify, and distribute this software for +## any purpose with or without fee is hereby granted, provided that +## the above copyright notice and this permission notice appear in all +## copies. +## +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR +## 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. +## + +=pod + +=head1 NAME + +B - Local Mail Transfer Protocol (LMTP) Library + +=head1 SYNOPSIS + +=over 4 + +=item Headers: + +B. + +=item Types: + +B, +B, +B, +B, +B, +B. + +=item Functions: + +B, +B, +B, +B, +B, +B, +B, +B, +B. + +=item Return Codes: + +B, +B, +B, +B, +B, +B, +B. + +=back + +=head1 DESCRIPTION + +This library provides a generic framework for implementing the Local Mail +Transport Protocol (LMTP) in a server application. + +The following data types are declared: + +=over 4 + +=item B + +This is the opaque data type which forms the LMTP session handle. +It is passed through every API function as its context. + +=item B + +This is a simple I/O structure which can be passed to ltmp_create(3) in +order override the underlying I/O routines used by the LMTP library. +It contains the following two attributes which match the prototype of +read(2) and write(2). + + ssize_t (*read)(int, void *, size_t); + ssize_t (*write)(int, const void *, size_t); + +=item B + +This is a simple Request structure. +It contains the following two attributes: + + char *verb; /* LMTP request verb */ + char *msg; /* LMTP request message (whole line) */ + +=item B + +... + + char *statuscode; /* digit digit digit NUL */ + char *dsncode; /* digit dot digit dot digit NUL */ + char *statusmsg; /* message with >=0*NLs, not terminating with NL. NUL */ + +=item B + +... + + 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_ARG /* invalid arg was passed to function */ + LMTP_ERR_UNKNOWN /* guru meditation */ + +=item B + +... + +lmtp_rc_t (*B)(lmtp_t *I, lmtp_io_t *I, lmtp_req_t +*I, void *I); + +=back + +The following API functions are provided: + +=item lmtp_t *B(int I, int I, lmtp_io_t *I); + +... + +=item void B(lmtp_t *I); + +... + +=item lmtp_rc_t B(lmtp_t *I, char *I, size_t I); + +... + +=item lmtp_rc_t B(lmtp_t *I, char **I, size_t I); + +... + +=item lmtp_rc_t B(lmtp_t *I, lmtp_req_t *I); + +... + +=item lmtp_rc_t B(lmtp_t *I, lmtp_res_t *I); + +... + +=item char *B(lmtp_t *I, lmtp_rc_t I); + +... + +=item lmtp_rc_t B(lmtp_t *I, char *I, lmtp_cb_t I, void *I, lmtp_cb_t *I, void **I); + +... + +=item lmtp_rc_t B(lmtp_t *I); + +... + +=back + +=head1 EXAMPLE + +... + +=head1 STANDARDS + +RFC 2033: Local Mail Transfer Protocol (SMTP) + +RFC 821, STD 90: Simple Mail Transfer Protocol (SMTP) + +RFC 1891: Delivery Status Notification (DSN) + +RFC 2920: SMTP Service Extension for Command Pipelining + +=head1 AUTHORS + + Thomas Lotterer + thomas.lotterer@cw.com + Cable & Wireless Deutschland GmbH + + Ralf S. Engelschall + ralf.engelschall@cw.com + Cable & Wireless Deutschland GmbH + +=cut +