Index: ossp-pkg/lmtp2nntp/argz.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/argz.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/argz.c,v' | diff -u /dev/null - -L'ossp-pkg/lmtp2nntp/argz.c' 2>/dev/null --- ossp-pkg/lmtp2nntp/argz.c +++ - 2024-04-26 07:22:13.828935886 +0200 @@ -0,0 +1,396 @@ +/* Routines for dealing with '\0' separated arg vectors. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "argz.h" + +/* Find the length of STRING, but scan at most MAXLEN characters. + If no '\0' terminator is found in that many characters, return MAXLEN. */ +static size_t my_strnlen(const char *string, size_t maxlen) +{ + const char *end = memchr(string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} + +static char *my_strndup(const char *s, size_t n) +{ + size_t len = my_strnlen(s, n); + char *new = malloc(len + 1); + + if (new == NULL) + return NULL; + new[len] = '\0'; + return (char *)memcpy(new, s, len); +} + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +static char *my_stpcpy(char *dest, const char *src) +{ + register char *d = dest; + register const char *s = src; + + do { + *d++ = *s; + } while (*s++ != '\0'); + return d - 1; +} + +int argz_add_sep(char **argz, size_t * argz_len, const char *string, int delim) +{ + size_t nlen = strlen(string) + 1; + + if (nlen > 1) { + const char *rp; + char *wp; + + *argz = (char *)realloc(*argz, *argz_len + nlen); + if (*argz == NULL) + return ENOMEM; + + wp = *argz + *argz_len; + rp = string; + do { + if (*rp == delim) { + if (wp > *argz && wp[-1] != '\0') + *wp++ = '\0'; + else + --nlen; + } + else + *wp++ = *rp; + } while (*rp++ != '\0'); + + *argz_len += nlen; + } + + return 0; +} + +/* Add BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */ +int argz_append(char **argz, size_t * argz_len, const char *buf, size_t buf_len) +{ + size_t new_argz_len = *argz_len + buf_len; + char *new_argz = realloc(*argz, new_argz_len); + if (new_argz) { + memcpy(new_argz + *argz_len, buf, buf_len); + *argz = new_argz; + *argz_len = new_argz_len; + return 0; + } + else + return ENOMEM; +} + +/* Add STR to the argz vector in ARGZ & ARGZ_LEN. This should be moved into + * argz.c in libshouldbelibc. */ +int argz_add(char **argz, size_t * argz_len, const char *str) +{ + return argz_append(argz, argz_len, str, strlen(str) + 1); +} + +/* Returns the number of strings in ARGZ. */ +size_t argz_count(const char *argz, size_t len) +{ + size_t count = 0; + while (len > 0) { + size_t part_len = strlen(argz); + argz += part_len + 1; + len -= part_len + 1; + count++; + } + return count; +} + +/* Make a '\0' separated arg vector from a unix argv vector, returning it in + * ARGZ, and the total length in LEN. If a memory allocation error occurs, + * ENOMEM is returned, otherwise 0. */ +int argz_create(char *const argv[], char **argz, size_t * len) +{ + int argc; + size_t tlen = 0; + char *const *ap; + char *p; + + for (argc = 0; argv[argc] != NULL; ++argc) + tlen += strlen(argv[argc]) + 1; + + if (tlen == 0) + *argz = NULL; + else { + *argz = malloc(tlen); + if (*argz == NULL) + return ENOMEM; + + for (p = *argz, ap = argv; *ap; ++ap, ++p) + p = my_stpcpy(p, *ap); + } + *len = tlen; + + return 0; +} + +int argz_create_sep(const char *string, int delim, char **argz, size_t * len) +{ + size_t nlen = strlen(string) + 1; + + if (nlen > 1) { + const char *rp; + char *wp; + + *argz = (char *)malloc(nlen); + if (*argz == NULL) + return ENOMEM; + + rp = string; + wp = *argz; + do + if (*rp == delim) { + if (wp > *argz && wp[-1] != '\0') + *wp++ = '\0'; + else + --nlen; + } + else + *wp++ = *rp; + while (*rp++ != '\0'); + + if (nlen == 0) { + free(*argz); + *argz = NULL; + *len = 0; + } + + *len = nlen; + } + else { + *argz = NULL; + *len = 0; + } + + return 0; +} + +/* Delete ENTRY from ARGZ & ARGZ_LEN, if any. */ +void argz_delete(char **argz, size_t * argz_len, char *entry) +{ + if (entry) + /* Get rid of the old value for NAME. */ + { + size_t entry_len = strlen(entry) + 1; + *argz_len -= entry_len; + memmove(entry, entry + entry_len, *argz_len - (entry - *argz)); + if (*argz_len == 0) { + free(*argz); + *argz = 0; + } + } +} + +/* Puts pointers to each string in ARGZ, plus a terminating 0 element, into + * ARGV, which must be large enough to hold them all. */ +void argz_extract(const char *argz, size_t len, char **argv) +{ + while (len > 0) { + size_t part_len = strlen(argz); + *argv++ = (char *)argz; + argz += part_len + 1; + len -= part_len + 1; + } + *argv = 0; +} + +/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an + * existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end. + * Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN, + * ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not + * in ARGZ, EINVAL is returned, else if memory can't be allocated for the new + * ARGZ, ENOMEM is returned, else 0. */ +int argz_insert(char **argz, size_t * argz_len, char *before, const char *entry) +{ + if (!before) + return argz_add(argz, argz_len, entry); + + if (before < *argz || before >= *argz + *argz_len) + return EINVAL; + + if (before > *argz) + /* Make sure before is actually the beginning of an entry. */ + while (before[-1]) + before--; + + { + size_t after_before = *argz_len - (before - *argz); + size_t entry_len = strlen(entry) + 1; + size_t new_argz_len = *argz_len + entry_len; + char *new_argz = realloc(*argz, new_argz_len); + + if (new_argz) { + before = new_argz + (before - *argz); + memmove(before + entry_len, before, after_before); + memmove(before, entry, entry_len); + *argz = new_argz; + *argz_len = new_argz_len; + return 0; + } + else + return ENOMEM; + } +} + +char *argz_next(const char *argz, size_t argz_len, const char *entry) +{ + if (entry) { + if (entry < argz + argz_len) + entry = strchr(entry, '\0') + 1; + + return entry >= argz + argz_len ? NULL : (char *)entry; + } + else if (argz_len > 0) + return (char *)argz; + else + return NULL; +} + +/* Append BUF, of length BUF_LEN to *TO, of length *TO_LEN, reallocating and + * updating *TO & *TO_LEN appropriately. If an allocation error occurs, + * *TO's old value is freed, and *TO is set to 0. */ +static void +str_append(char **to, size_t * to_len, const char *buf, const size_t buf_len) +{ + size_t new_len = *to_len + buf_len; + char *new_to = realloc(*to, new_len + 1); + + if (new_to) { + /* *((char *)__mempcpy(new_to + *to_len, buf, buf_len)) = '\0'; */ + memcpy(new_to + *to_len, buf, buf_len); + *(new_to + *to_len + buf_len) = '\0'; + *to = new_to; + *to_len = new_len; + } + else { + free(*to); + *to = 0; + } +} + +/* Replace any occurrences of the string STR in ARGZ with WITH, reallocating + * ARGZ as necessary. If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be + * incremented by number of replacements performed. */ +int argz_replace(char **argz, size_t * argz_len, const char *str, + const char *with, unsigned *replace_count) +{ + int err = 0; + + if (str && *str) { + char *arg = 0; + char *src = *argz; + size_t src_len = *argz_len; + char *dst = 0; + size_t dst_len = 0; + int delayed_copy = 1; /* True while we've avoided copying + * anything. */ + size_t str_len = strlen(str), with_len = strlen(with); + + while (!err && (arg = argz_next(src, src_len, arg))) { + char *match = strstr(arg, str); + if (match) { + char *from = match + str_len; + size_t to_len = match - arg; + char *to = my_strndup(arg, to_len); + + while (to && from) { + str_append(&to, &to_len, with, with_len); + if (to) { + match = strstr(from, str); + if (match) { + str_append(&to, &to_len, from, match - from); + from = match + str_len; + } + else { + str_append(&to, &to_len, from, strlen(from)); + from = 0; + } + } + } + + if (to) { + if (delayed_copy) + /* We avoided copying SRC to DST until we found a + * match; now that we've done so, copy everything + * from the start of SRC. */ + { + if (arg > src) + err = + argz_append(&dst, &dst_len, src, + (arg - src)); + delayed_copy = 0; + } + if (!err) + err = argz_add(&dst, &dst_len, to); + free(to); + } + else + err = ENOMEM; + + if (replace_count) + (*replace_count)++; + } + else if (!delayed_copy) + err = argz_add(&dst, &dst_len, arg); + } + + if (!err) { + if (!delayed_copy) + /* We never found any instances of str. */ + { + if (src) + free(src); + *argz = dst; + *argz_len = dst_len; + } + } + else if (dst_len > 0) + free(dst); + } + + return err; +} + +/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's + * except the last into the character SEP. */ +void argz_stringify(char *argz, size_t len, int sep) +{ + if (len > 0) { + while (1) { + size_t part_len = my_strnlen(argz, len); + argz += part_len; + len -= part_len; + if (len-- <= 1) /* includes final '\0' we want to stop + * at */ + break; + *argz++ = sep; + } + } + return; +} + Index: ossp-pkg/lmtp2nntp/argz.h RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/argz.h,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/argz.h,v' | diff -u /dev/null - -L'ossp-pkg/lmtp2nntp/argz.h' 2>/dev/null --- ossp-pkg/lmtp2nntp/argz.h +++ - 2024-04-26 07:22:13.831772880 +0200 @@ -0,0 +1,40 @@ +/* Routines for dealing with '\0' separated arg vectors. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _ARGZ_H_ +#define _ARGZ_H_ + +#include + +extern int argz_create (char *const _argv[], char **_argz, size_t * _len); +extern int argz_create_sep(const char *_string, int _sep, char **_argz, size_t * _len); +extern size_t argz_count (const char *_argz, size_t _len); +extern void argz_extract (const char *_argz, size_t _len, char **_argv); +extern void argz_stringify (char *_argz, size_t _len, int _sep); +extern int argz_append (char **_argz, size_t * _argz_len, const char *_buf, size_t _buf_len); +extern int argz_add (char **_argz, size_t * _argz_len, const char *_str); +extern int argz_add_sep (char **_argz, size_t * _argz_len, const char *_string, int _delim); +extern void argz_delete (char **_argz, size_t * _argz_len, char *_entry); +extern int argz_insert (char **_argz, size_t * _argz_len, char *_before, const char *_entry); +extern int argz_replace (char **_argz, size_t * _argz_len, const char *_str, const char *_with, unsigned int *_replace_count); +extern char *argz_next (const char *_argz, size_t _argz_len, const char *_entry); + +#endif /* _ARGZ_H_ */ + Index: ossp-pkg/lmtp2nntp/argz.html RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/argz.html,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/argz.html,v' | diff -u /dev/null - -L'ossp-pkg/lmtp2nntp/argz.html' 2>/dev/null --- ossp-pkg/lmtp2nntp/argz.html +++ - 2024-04-26 07:22:13.834320956 +0200 @@ -0,0 +1,238 @@ + + + + +Untitled Document + + +

Untitled Document

+

+


+ + + +

Argz Vectors

+ +

+ + + +argz vectors are vectors of strings in a contiguous block of +memory, each element separated from its neighbors by null-characters +('\0'). + + + + +

Argz Functions

+ +

+Each argz vector is represented by a pointer to the first element, of +type char *, and a size, of type size_t, both of which can +be initialized to 0 to represent an empty argz vector. All argz +functions accept either a pointer and a size argument, or pointers to +them, if they will be modified. + + +

+The argz functions use malloc/realloc to allocate/grow +argz vectors, and so any argz vector creating using these functions may +be freed by using free; conversely, any argz function that may +grow a string expects that string to have been allocated using +malloc (those argz functions that only examine their arguments or +modify them in place will work on any sort of memory). + + +

+All argz functions that do memory allocation have a return type of +int, and return 0 for success, and ENOMEM if an +allocation error occurs. + + +

+ +These functions are declared in the standard include file `argz.h'. + + +

+

+
Function: int argz_create (char *const argv[], char **argz, size_t *argz_len) +
+The argz_create function converts the Unix-style argument vector +argv (a vector of pointers to normal C strings, terminated by +(char *)0;) into an argz vector with +the same elements, which is returned in argz and argz_len. +
+ + +

+

+
Function: int argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len) +
+The argz_create_sep function converts the null-terminated string +string into an argz vector (returned in argz and +argz_len) by splitting it into elements at every occurrence of the +character sep. +
+ + +

+

+
Function: size_t argz_count (const char *argz, size_t arg_len) +
+Returns the number of elements in the argz vector argz and +argz_len. +
+ + +

+

+
Function: void argz_extract (char *argz, size_t argz_len, char **argv) +
+The argz_extract function converts the argz vector argz and +argz_len into a Unix-style argument vector stored in argv, +by putting pointers to every element in argz into successive +positions in argv, followed by a terminator of 0. +Argv must be pre-allocated with enough space to hold all the +elements in argz plus the terminating (char *)0 +((argz_count (argz, argz_len) + 1) * sizeof (char *) +bytes should be enough). Note that the string pointers stored into +argv point into argz---they are not copies--and so +argz must be copied if it will be changed while argv is +still active. This function is useful for passing the elements in +argz to an exec function. +
+ + +

+

+
Function: void argz_stringify (char *argz, size_t len, int sep) +
+The argz_stringify converts argz into a normal string with +the elements separated by the character sep, by replacing each +'\0' inside argz (except the last one, which terminates the +string) with sep. This is handy for printing argz in a +readable manner. +
+ + +

+

+
Function: int argz_add (char **argz, size_t *argz_len, const char *str) +
+The argz_add function adds the string str to the end of the +argz vector *argz, and updates *argz and +*argz_len accordingly. +
+ + +

+

+
Function: int argz_add_sep (char **argz, size_t *argz_len, const char *str, int delim) +
+The argz_add_sep function is similar to argz_add, but +str is split into separate elements in the result at occurrences of +the character delim. This is useful, for instance, for +adding the components of a Unix search path to an argz vector, by using +a value of ':' for delim. +
+ + +

+

+
Function: int argz_append (char **argz, size_t *argz_len, const char *buf, size_t buf_len) +
+The argz_append function appends buf_len bytes starting at +buf to the argz vector *argz, reallocating +*argz to accommodate it, and adding buf_len to +*argz_len. +
+ + +

+

+
Function: int argz_delete (char **argz, size_t *argz_len, char *entry) +
+If entry points to the beginning of one of the elements in the +argz vector *argz, the argz_delete function will +remove this entry and reallocate *argz, modifying +*argz and *argz_len accordingly. Note that as +destructive argz functions usually reallocate their argz argument, +pointers into argz vectors such as entry will then become invalid. +
+ + +

+

+
Function: int argz_insert (char **argz, size_t *argz_len, char *before, const char *entry) +
+The argz_insert function inserts the string entry into the +argz vector *argz at a point just before the existing +element pointed to by before, reallocating *argz and +updating *argz and *argz_len. If before +is 0, entry is added to the end instead (as if by +argz_add). Since the first element is in fact the same as +*argz, passing in *argz as the value of +before will result in entry being inserted at the beginning. +
+ + +

+

+
Function: char * argz_next (char *argz, size_t argz_len, const char *entry) +
+The argz_next function provides a convenient way of iterating +over the elements in the argz vector argz. It returns a pointer +to the next element in argz after the element entry, or +0 if there are no elements following entry. If entry +is 0, the first element of argz is returned. + + +

+This behavior suggests two styles of iteration: + + + +

+    char *entry = 0;
+    while ((entry = argz_next (argz, argz_len, entry)))
+      action;
+
+ +

+(the double parentheses are necessary to make some C compilers shut up +about what they consider a questionable while-test) and: + + + +

+    char *entry;
+    for (entry = argz;
+         entry;
+         entry = argz_next (argz, argz_len, entry))
+      action;
+
+ +

+Note that the latter depends on argz having a value of 0 if +it is empty (rather than a pointer to an empty block of memory); this +invariant is maintained for argz vectors created by the functions here. +

+ + +

+

+
Function: int argz_replace (char **argz, size_t *argz_len, const char *str, const char *with, unsigned *replace_count) +
+Replace any occurrences of the string str in argz with +with, reallocating argz as necessary. If +replace_count is non-zero, *replace_count will be +incremented by number of replacements performed. +
+ + +


+This document was generated on 25 July 2001 using +texi2html 1.56k. + + Index: ossp-pkg/lmtp2nntp/lmtp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.c,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.c,v' 2>/dev/null --- lmtp.c 2001/07/25 11:29:38 1.4 +++ lmtp.c 2001/07/25 15:02:57 1.5 @@ -22,7 +22,6 @@ int i; printf("lmtp = %ld \n", (long)lmtp); - printf("io.select = %ld \n", (long)lmtp->io.select); 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); @@ -98,8 +97,8 @@ { /* 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 _rfd_ and _wfd_ args are passed to the read(), write() + * 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 @@ -111,11 +110,9 @@ return NULL; if(io == NULL) { - lmtp->io.select = select; lmtp->io.read = read; lmtp->io.write = write; } else { - lmtp->io.select = io->select ? io->select : select; lmtp->io.read = io->read ? io->read : read; lmtp->io.write = io->write ? io->write : write; } @@ -138,18 +135,8 @@ void lmtp_destroy(lmtp_t *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() */ @@ -175,7 +162,8 @@ 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. + * 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 * CR/LF combination to a string terminating zero. Callers of this @@ -192,6 +180,7 @@ lmtp_rc_t rc = LMTP_OK; char *cpBuf; /* buffer as a whole */ + char *cpBufrealloc;/* buffer before realloc */ 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 */ @@ -211,10 +200,11 @@ 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); //FIXME double check isn't this a destroy() task? */ + if ((cpBufrealloc = (char *)realloc(cpBuf, nBuf)) == NULL) { + free(cpBuf); return LMTP_ERR_MEM; } + cpBuf = cpBufrealloc; *cppBuf = cpBuf; /* tell caller about the new buffer */ cpPtr = cpBuf + offset; /* recover write cursor */ cpLine = cpBuf + offsetline; /* recover start of line */ @@ -334,23 +324,6 @@ return rc; } -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; - - lmtp_msg_t *cpp = NULL; - if ((i = verbindex(lmtp, verb)) >= 0) cpp = lmtp->dispatch[i]->msg; - return cpp; -} - -void lmtp_reset(lmtp_t *lmtp) -{ - return; -} - char *lmtp_error(lmtp_t *lmtp, lmtp_rc_t rc) { /* get an error message matching the given lmtp_rc_t code usually @@ -358,14 +331,14 @@ */ 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"; + str = "LMTP: errorcode has no description"; + if (rc == LMTP_OK ) str = "LMTP: no error"; + else if (rc == LMTP_EOF ) str = "LMTP: eof"; + else if (rc == LMTP_ERR_SYSTEM ) str = "LMTP: see errno"; + else if (rc == LMTP_ERR_MEM ) str = "LMTP: dynamic memory allocation failed"; + 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; } @@ -419,7 +392,6 @@ lmtp->dispatch[i]->verb = strdup(verb); lmtp->dispatch[i]->cb = cb; lmtp->dispatch[i]->ctx = ctx; - lmtp->dispatch[i]->msg = NULL; return rc; } Index: ossp-pkg/lmtp2nntp/lmtp.h RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.h,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp.h,v' 2>/dev/null --- lmtp.h 2001/07/25 11:29:38 1.4 +++ lmtp.h 2001/07/25 15:02:57 1.5 @@ -11,7 +11,6 @@ typedef struct lmtp_st lmtp_t; typedef struct { - int (*select)(int nfds, fd_set *rfds, fd_set *wrfds, fd_set *efds, struct timeval *t); ssize_t (*read) (int fd, void *buf, size_t nbytes); ssize_t (*write) (int fd, const void *buf, size_t nbytes); } lmtp_io_t; @@ -27,12 +26,6 @@ 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 */ @@ -51,8 +44,6 @@ 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); -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); lmtp_rc_t lmtp_loop (lmtp_t *lmtp); Index: ossp-pkg/lmtp2nntp/lmtp2nntp.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/Attic/lmtp2nntp.c,v' 2>/dev/null --- lmtp2nntp.c 2001/07/25 11:29:38 1.4 +++ lmtp2nntp.c 2001/07/25 15:02:57 1.5 @@ -1,4 +1,3 @@ - /* * mail2nntp.c * @@ -13,6 +12,7 @@ */ +#include #include #include #include @@ -21,15 +21,25 @@ /* third party */ #include "str.h" +#include "argz.h" /* own headers */ #include "lmtp.h" +#ifndef FALSE +#define FALSE (1 != 1) +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + #define ERR_EXECUTION -1 #define ERR_DELIVERY -2 #define MESSAGE_MAXLEN 8*1024*1024 +extern void lmtp_debug_dumplmtp(lmtp_t *lmtp); + static ssize_t trace_read(int d, void *buf, size_t nbytes); static ssize_t trace_write(int d, const void *buf, size_t nbytes); @@ -41,80 +51,25 @@ 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); -static void test(void); - -int main(int argc, char **argv) -{ - int i; /* general purpose scratch int, index ... */ - - { - char buf[1000]; - int bufused = 0; - int tracefile; - -// printf("DEBUG: start of argdump\n", buf); - for (i=0; ioption_verbose = FALSE; + ctx->option_tracing = FALSE; + ctx->option_mode = MODE_MANY; + ctx->azNewsgroups = NULL; + ctx->asNewsgroups = 0; + ctx->rfc822message = NULL; + ctx->saw_lhlo = FALSE; + ctx->azRcpt = NULL; + ctx->asRcpt = 0; - /* printf("DEBUG: 99.\n"); */ - return; + /* read in the arguments */ + { + char buf[1000]; + int bufused = 0; + int tracefile; + + for (i=0; ioption_mode = MODE_ONCE; + else if (strcasecmp(argv[optind], "many") == 0) + ctx->option_mode = MODE_MANY; + else { + fprintf(stderr, "%s:Error: Invalid mode \"%s\" to option -m\n", progname, argv[optind]); + exit(ERR_EXECUTION); + } + break; + case 'd': // -t (tracing) + ctx->option_tracing = TRUE; + break; + case 'v': // -v (verbose) + ctx->option_verbose = TRUE; + break; + case '?': + default: + usage(progname); + exit(ERR_EXECUTION); + } + } + /* remaining arguments are newsgroup names */ + for (i = optind; i < argc; i++) + argz_add(&ctx->azNewsgroups, &ctx->asNewsgroups, argv[i]); + + /* initialize LMTP context */ + lmtp_io.read = trace_read; + lmtp_io.write = trace_write; + if ((lmtp = lmtp_create(STDIN_FILENO, STDOUT_FILENO, &lmtp_io)) == NULL) { + fprintf(stderr, "%s:Error: Unable to initialize LMTP library\n", progname); + exit(ERR_EXECUTION); + } + lmtp_register(lmtp, "LHLO", lmtp_cb_lhlo, ctx, NULL, NULL); + lmtp_register(lmtp, "MAIL", lmtp_cb_mail, ctx, NULL, NULL); + lmtp_register(lmtp, "RCPT", lmtp_cb_rcpt, ctx, NULL, NULL); + lmtp_register(lmtp, "DATA", lmtp_cb_data, ctx, NULL, NULL); + lmtp_register(lmtp, "NOOP", lmtp_cb_noop, ctx, NULL, NULL); + lmtp_register(lmtp, "RSET", lmtp_cb_rset, ctx, NULL, NULL); + lmtp_register(lmtp, "QUIT", lmtp_cb_quit, ctx, NULL, NULL); + + /* loop for LMTP protocol */ + lmtp_loop(lmtp); + + return 0; } -static lmtp_rc_t lmtp_cb_lhlo(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *ctx) + +static lmtp_rc_t lmtp_cb_lhlo(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx) { - lmtp_res_t res; + /* + * RFC821 [excerpt] 4.1. SMTP COMMANDS + * 4.1.1. COMMAND SEMANTICS, HELO + * This command and an OK reply to it confirm that both the sender-SMTP + * and the receiver-SMTP are in the initial state, that is, there is no + * transaction in progress and all state tables and buffers are cleared. + * + */ lmtp_rc_t rc = LMTP_OK; + lmtp_res_t res; + lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx; + + //FIXME use rset() not lmtp_cb_rset() + ctx->saw_lhlo = TRUE; + res.statuscode = "250"; res.dsncode = NULL; /* DSN not used for greeting */ res.statusmsg = "ENHANCEDSTATUSCODES\nDSN\nPIPELINING\n8BITMIME"; + res.statusmsg = "ENHANCEDSTATUSCODES\nDSN\n8BITMIME"; /* * RFC2034 = EHANCEDSTATUSCODES * RFC1894 = DSN @@ -219,71 +239,80 @@ return rc; } -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_mail(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 = "553"; - res.dsncode = "5.1.8"; - res.statusmsg = "Bad sender FIXME"; - res.statuscode = "250"; - res.dsncode = "2.1.0"; - res.statusmsg = "Sender ok FIXME"; - lmtp_response(lmtp, &res); + lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx; + + if (ctx->saw_lhlo == TRUE) { + res.statuscode = "250"; + res.dsncode = "2.1.0"; + res.statusmsg = "Sender ok FIXME"; + lmtp_response(lmtp, &res); + } else { + res.statuscode = "553"; + res.dsncode = "5.1.8"; + res.statusmsg = "friendly people say LHLO to open a transmission channel"; + 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) +static lmtp_rc_t lmtp_cb_rcpt(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx) { lmtp_rc_t rc = LMTP_OK; lmtp_res_t res; - char **cp; + lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx; + argz_add(&ctx->azRcpt, &ctx->asRcpt, req->msg); 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; } -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_data(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx) { lmtp_res_t res; lmtp_rc_t rc = LMTP_OK; + lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx; char *buf; char errorstring[128]; + char *rcpt; res.statuscode = "354"; res.dsncode = NULL; /* DSN not used for data */ res.statusmsg = "Enter mail, end with \".\" on a line by itself"; lmtp_response(lmtp, &res); rc = lmtp_readmsg(lmtp, &buf, MESSAGE_MAXLEN); - if(rc == LMTP_OK) { -// printf("DEBUG: message=***%s***\n", buf); - res.statuscode = "250"; - res.dsncode = "2.0.0"; - res.statusmsg = "Message accepted for delivery"; - } else if (rc == LMTP_ERR_OVERFLOW) { - res.statuscode = "500"; - res.dsncode = "5.0.0"; - res.statusmsg = "Message accepted for delivery"; - } else if (rc == LMTP_ERR_SYSTEM) { - res.statuscode = "500"; - res.dsncode = "5.0.0"; - str_format(errorstring, sizeof(errorstring), - "Message accepted for delivery %s", strerror(errno)); - res.statusmsg = errorstring; + + rcpt = NULL; + while ((rcpt = argz_next(ctx->azRcpt, ctx->asRcpt, rcpt)) != NULL) + { + if(rc == LMTP_OK) { + res.statuscode = "250"; + res.dsncode = "2.0.0"; + // res.statusmsg = "Message accepted for delivery"; + str_format(errorstring, sizeof(errorstring), + "Message accepted for delivery to %s", rcpt); + res.statusmsg = errorstring; + } else if (rc == LMTP_ERR_OVERFLOW) { + res.statuscode = "500"; + res.dsncode = "5.0.0"; + res.statusmsg = "Message accepted for delivery"; + } else if (rc == LMTP_ERR_SYSTEM) { + res.statuscode = "500"; + res.dsncode = "5.0.0"; + str_format(errorstring, sizeof(errorstring), + "Message accepted for delivery %s", strerror(errno)); + res.statusmsg = errorstring; + } + lmtp_response(lmtp, &res); } - lmtp_response(lmtp, &res); return rc; } @@ -297,10 +326,17 @@ 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) +static lmtp_rc_t lmtp_cb_rset(lmtp_t *lmtp, lmtp_io_t *io, lmtp_req_t *req, void *_ctx) { + lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx; lmtp_res_t res; lmtp_rc_t rc = LMTP_OK; + + if (ctx->azRcpt != NULL) { + free(ctx->azRcpt); + ctx->azRcpt = NULL; + ctx->asRcpt = 0; + } res.statuscode = "250"; res.dsncode = "2.0.0"; res.statusmsg = "Reset state.";