Index: ossp-pkg/lmtp2nntp/lmtp2nntp_config.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.c,v rcsdiff -q -kk '-r1.14' '-r1.15' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.c,v' 2>/dev/null --- lmtp2nntp_config.c 2002/01/24 08:54:25 1.14 +++ lmtp2nntp_config.c 2002/01/24 12:04:46 1.15 @@ -1,3 +1,4 @@ + /* ** Copyright (c) 2001-2002 The OSSP Project ** Copyright (c) 2001-2002 Cable & Wireless Deutschland @@ -21,7 +22,7 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ** USA, or contact the OSSP project . ** -** FIXME lmtp2nntp_config.c: LMTP to NNTP configuration parsing +** lmtp2nntp_config.c: config handling */ #include @@ -53,10 +54,12 @@ #if defined(HAVE_DMALLOC_H) && defined(DMALLOC) #include "dmalloc.h" #endif +#include "lmtp2nntp_option.h" #include "lmtp2nntp_config.h" #include "lmtp2nntp_lmtp.h" #include "lmtp2nntp_nntp.h" #include "lmtp2nntp_msg.h" +#include "fixme.h" #define _LMTP2NNTP_VERSION_C_AS_HEADER_ #include "lmtp2nntp_version.c" #undef _LMTP2NNTP_VERSION_C_AS_HEADER_ @@ -72,615 +75,7 @@ #define NUL '\0' #endif -static void die(char *msg) -{ - printf("ERROR: %s\n", msg); - exit(-1); -} - -struct optionconfig_s { - optionconfig_t *next; /* cleanup chain for destroy */ - lmtp2nntp_option_t *parent; /* include needs access to parent */ - /**/ - char *longname; /* the long name (optional if shortname given) */ - char shortname; /* the short name (optional if longname given) */ - char *descrip; /* description for autohelp */ - char *argdescrip; /* argument description for autohelp */ - optiontype_t type; /* OPT_FLAG, OPT_SINGLE, OPT_MULTI */ - optionloop_cb_t *cb; /* callback for first iteration - syntax check and include */ - void *cbctx; /* context for pass1 */ - val_t *val; /* val we are registered under */ - /**/ - int number; /* number of this option for popt */ - struct { /* option data as read from configuration */ - int f; /* OPT_FLAG */ - void *foo1, *foo2, *foo3, *foo4, *foo5, *foo6, *foo7, *foo8, *foo9; - char *s; /* OPT_SINGLE */ - void *bar1, *bar2, *bar3, *bar4, *bar5, *bar6, *bar7, *bar8, *bar9; - char **m; /* OPT_MULTI */ - } data; - int ndata; -}; - -static val_rc_t dumper(void *ctx, const char *name, int type, const char *desc, void *data) -{ - optionconfig_t *oc; - int i; - - if (type != VAL_TYPE_PTR) - return VAL_OK; - - oc = (optionconfig_t *)data; - - switch (oc->type) { - case OPT_FLAG: - printf("DEBUG: <%5s>, name=<%20s>, OPT_FLAG, desc=<%20s>, data@%.8lx->[%d]%d\n", (char *)ctx, name, desc, (long)oc, oc->ndata, oc->data.f); break; - case OPT_SINGLE: - printf("DEBUG: <%5s>, name=<%20s>, OPT_SINGLE, desc=<%20s>, data@%.8lx->[%d]\"%s\"\n", (char *)ctx, name, desc, (long)oc, oc->ndata, oc->data.s == NULL ? "NULL" : oc->data.s); - break; - case OPT_MULTI: - printf("DEBUG: <%5s>, name=<%20s>, OPT_MULTI, desc=<%20s>, data@%.8lx->[%d]%.8lx\n", (char *)ctx, name, desc, (long)oc, oc->ndata, (long)oc->data.m); - for (i = 0; i < oc->ndata; i++) { -#if 0 - { - int j; - printf("DEBUG: "); - for (j=0; j<8; j++) printf("%.2x ", (unsigned char)oc->data.m[i][j]); - printf(" "); - for (j=0; j<8; j++) printf("%c", isprint(oc->data.m[i][j]) ? oc->data.m[i][j] : '.'); - printf(" "); - } -#endif - printf("DEBUG: [%3d] %.8lx \"%s\"\n", i, (long)oc->data.m[i], oc->data.m[i]); - } - break; - default: - break; - } - return VAL_OK; -} -//lmtp2nntp_option_rc_t option_find(lmtp2nntp_option_t *o, int number, optionconfig_t **ocp); -static lmtp2nntp_option_rc_t option_find(lmtp2nntp_option_t *o, int number, optionconfig_t **ocp) -{ - lmtp2nntp_option_rc_t rc = VAL_OK; - - if (o == NULL || ocp == NULL) - return OPTION_ERR_ARG; - - *ocp = o->first; - while (*ocp != NULL && (*ocp)->number != number) - *ocp = (*ocp)->next; - - return rc; -} - - -lmtp2nntp_option_rc_t option_register(lmtp2nntp_option_t *o, char *longname, char shortname, optiontype_t type, optionloop_cb_t *cb, char *cbctx, char *descrip, char *argdescrip) -{ - lmtp2nntp_option_rc_t rc = VAL_OK; - optionconfig_t *oc; - - //printf("DEBUG: enter option_register(%.8lx, \"%s\", '%c', %d, %.8lx, %.8lx, \"%s\", \"%s\")\n", (long)o, longname, shortname, type, (long)cb, (long)cbctx, descrip, argdescrip); - - if (o == NULL || longname == NULL) - return OPTION_ERR_ARG; - - /* create a optionconfig_t structure */ - if ((oc = (optionconfig_t *)malloc(sizeof(optionconfig_t))) == NULL) - return OPTION_ERR_MEM; - //printf("DEBUG: optionconfig_t structure malloc'ed\n"); - oc->next = NULL; - oc->parent = o; - oc->longname = strdup(longname); - oc->shortname = shortname; - oc->descrip = descrip == NULL ? NULL : strdup(descrip); - oc->argdescrip = argdescrip == NULL ? NULL : strdup(argdescrip); - oc->type = type; - oc->cb = cb; - oc->cbctx = cbctx; - oc->val = o->vo; - oc->number = o->pi + 1; /* 0 is a reserved val in popt, so offset 1 */ - oc->data.f = 0; - oc->data.s = NULL; /* just in case a pointer is larger than int */ - oc->data.m = NULL; - oc->ndata = 0; - if ( ( oc->longname == NULL) - || (descrip != NULL && oc->descrip == NULL) - || (argdescrip != NULL && oc->argdescrip == NULL) - ) - CU(OPTION_ERR_MEM); - - //printf("DEBUG: optionconfig_t structure created\n"); - - /* feed lib_val */ - if (val_reg(oc->val, oc->longname, VAL_TYPE_PTR, oc->descrip, oc) != VAL_OK) - CU(OPTION_ERR_USE); - - //printf("DEBUG: val_reg'ed\n"); - - /* feed lib_popt */ - //printf("DEBUG: o->pi=%d, o->pn=%d\n", o->pi, o->pn); - if (o->pi >= (o->pn-2)) { /* correction by two here, in malloc and realloc is for AUTOHELP and TABLEEND */ - if (o->pt == NULL) { - //printf("DEBUG: malloc\n"); - o->pt = (struct popt_option *)malloc( (1 + 2) * sizeof(struct popt_option)); - o->pn = 1; - } - else { - //printf("DEBUG: realloc\n"); - o->pt = (struct popt_option *)realloc(o->pt, (o->pn * 2 + 2) * sizeof(struct popt_option)); - o->pn = o->pn * 2; - } - } - if (o->pt == NULL) - CU(OPTION_ERR_MEM); - o->pt[o->pi].longName = oc->longname; - o->pt[o->pi].shortName = oc->shortname; - o->pt[o->pi].argInfo = oc->type == OPT_FLAG ? POPT_ARG_NONE : POPT_ARG_STRING; - o->pt[o->pi].arg = NULL; - o->pt[o->pi].val = oc->number; - o->pt[o->pi].descrip = oc->descrip; - o->pt[o->pi].argDescrip = oc->argdescrip; - - /* append POPT_AUTOHELP */ - o->pt[o->pi+1].longName = NULL; - o->pt[o->pi+1].shortName = '\0'; - o->pt[o->pi+1].argInfo = POPT_ARG_INCLUDE_TABLE; - o->pt[o->pi+1].arg = popt_helpoptions; - o->pt[o->pi+1].val = 0; - o->pt[o->pi+1].descrip = "Help options:"; - o->pt[o->pi+1].argDescrip = NULL; - - /* append POPT_TABLEEND */ - o->pt[o->pi+2].longName = NULL; - o->pt[o->pi+2].shortName = '\0'; - o->pt[o->pi+2].argInfo = 0; - o->pt[o->pi+2].arg = 0; - o->pt[o->pi+2].val = 0; - o->pt[o->pi+2].descrip = NULL; - o->pt[o->pi+2].argDescrip = NULL; - o->pi++; - //printf("DEBUG: popt'ed\n"); - - /* link in this new optionconfig_t structure */ - if (o->first == NULL) { - o->first = oc; - o->last = oc; - } - else { - o->last->next = oc; - o->last = oc; - } - //printf("DEBUG: linked\n"); - - return rc; - - CUS: - if (oc != NULL) { - if (oc->argdescrip != NULL) free(oc->argdescrip); - if (oc->descrip != NULL) free(oc->descrip); - if (oc->longname != NULL) free(oc->longname); - free(oc); - } - return rc; -} - -lmtp2nntp_option_rc_t option_create(lmtp2nntp_option_t **op) -{ - //printf("DEBUG: enter option_create(%.8lx)\n", (long)op); - - if (op == NULL) - return OPTION_ERR_ARG; - - if ((*op = (lmtp2nntp_option_t *)malloc(sizeof(lmtp2nntp_option_t))) == NULL) - return OPTION_ERR_MEM; - (*op)->childsmax = 0; - (*op)->daemonize = 0; - (*op)->kill = 0; - (*op)->pidfile = 0; - (*op)->acl.as = 0; - (*op)->acl.az = NULL; - (*op)->bind = NULL; - (*op)->client = NULL; - (*op)->destination.as = 0; - (*op)->destination.az = NULL; - (*op)->groupmode = NULL; - (*op)->headervalue.as = 0; - (*op)->headervalue.az = NULL; - (*op)->include.as = 0; - (*op)->include.az = NULL; - (*op)->size = 0; - (*op)->timeoutlmtpaccept = 0; - (*op)->timeoutlmtpread = 0; - (*op)->timeoutlmtpwrite = 0; - (*op)->timeoutnntpconnect = 0; - (*op)->timeoutnntpread = 0; - (*op)->timeoutnntpwrite = 0; - (*op)->mailfrom = NULL; - (*op)->nodename = NULL; - (*op)->operationmode = NULL; - (*op)->l2spec = NULL; - (*op)->uid = NULL; - (*op)->restrictheader.as = 0; - (*op)->restrictheader.az = NULL; - (*op)->newsgroup.as = 0; - (*op)->newsgroup.az = NULL; - /**/ - (*op)->first = NULL; - (*op)->last = NULL; - (*op)->vo = NULL; - (*op)->pn = 0; - (*op)->pi = 0; - (*op)->pt = NULL; - - if (val_create(&((*op)->vo)) != VAL_OK) { - free(*op); - return OPTION_ERR_VAL; - } - return OPTION_OK; -} - -static lmtp2nntp_option_rc_t option_parse_internal(lmtp2nntp_option_t *o, int argc, char **argv) -{ - int i; - char *cp; - optionconfig_t *ocp; - popt_context poptCon; /* context for parsing command-line options */ - -#if 0 - { - int i; - - for (i=0; ipt, 0); - popt_setotheroptionhelp(poptCon, "[OPTIONS]* [newsgroup ...]"); - //printf("DEBUG: argc=%d\n", argc); - if (argc < 2) { - popt_printusage(poptCon, stderr, 0); - exit(1); - } - while ((i = popt_getnextopt(poptCon)) >= 0) { - (void)option_find(o, i, &ocp); - //printf("DEBUG: ocp->type=%d\n", ocp->type); - if (ocp->cb != NULL) - ocp->cb(ocp, cp = (ocp->type == OPT_FLAG ? NULL : (char *)popt_getoptarg(poptCon)), ocp->cbctx); - //printf("DEBUG: popt_getnextopt returned %d \"%s\", \"%s\"\n", i-1, o->pt[i-1].longName, ocp->longname); - //printf("DEBUG: popt_getoptarg returned \"%s\"\n", cp); - } - //printf("DEBUG: current popt error is \"%s\"(%d)\n", popt_strerror(i), i); - //printf("DEBUG: ----\n"); - - { - int largc; - char **largv; - char *cpNew; - - if ((largv = (char **)malloc((1 + 1) * sizeof(char **))) == NULL) - return OPTION_ERR_MEM; - largc = 0; - largv[largc++] = "leftover"; - largv[largc] = NULL; - while ((cp = (char *)popt_getarg(poptCon)) != NULL) { - //printf("DEBUG: popt_getarg returned \"%s\"\n", cp); - if ((largv = (char **)realloc(largv, (largc + 2) * sizeof(char **))) == NULL) - return OPTION_ERR_MEM; - largv[largc++] = "--newsgroup"; - largv[largc] = NULL; - if ((cpNew = strdup(cp)) == NULL) - return OPTION_ERR_MEM; - //printf("DEBUG: cpNew = \"%s\"\n", cpNew); - largv[largc++] = cpNew; - largv[largc] = NULL; - //printf("DEBUG: largc = \"%d\"\n", largc); -#if 0 - for (i=0; i 1) - option_parse_internal(o, largc, largv); - } - //printf("DEBUG: current popt error is \"%s\"(%d)\n", popt_strerror(i), i); - popt_freecontext(poptCon); - return OPTION_OK; -} - -static lmtp2nntp_option_rc_t stdsyntax(optionconfig_t *oc, char *arg, char *cbctx) -{ - //printf("DEBUG: enter stdsyntax %.8lx, \"%s\", \"%s\"\n", (long)oc, arg, cbctx); - - //printf("DEBUG: oc->type=%d\n", oc->type); - switch (oc->type) { - case OPT_FLAG: - //printf("DEBUG: flag %20s = %s should match %s\n", oc->longname, arg, cbctx); - if (arg != NULL || cbctx != NULL) - return OPTION_ERR_ARG; - if (oc->ndata >= 1) - return OPTION_ERR_USE; - oc->data.f = 1; - oc->ndata = 1; - break; - case OPT_SINGLE: - //printf("DEBUG: single %20s = %s should match %s\n", oc->longname, arg, cbctx); - if (arg == NULL) - return OPTION_ERR_ARG; - /* use this if repeated overwriting definitions are not allowed - * if (oc->ndata >= 1 || oc->data.s != NULL) - * return OPTION_ERR_USE; - */ - if (cbctx != NULL) - if (str_parse(arg, cbctx) <= 0) { - //printf("DEBUG: \"%s\" does NOT match \"%s\"\n", arg, cbctx); - return OPTION_ERR_USE; - } - //printf("DEBUG: \"%s\" does match \"%s\"\n", arg, cbctx); - if ((oc->data.s = strdup(arg)) == NULL) - return OPTION_ERR_MEM; - oc->ndata = 1; - break; - case OPT_MULTI: - //printf("DEBUG: multi %20s = %s should match %s\n", oc->longname, arg, cbctx); - if (arg == NULL) - return OPTION_ERR_ARG; - if (oc->ndata >= 1 && oc->data.m == NULL) - return OPTION_ERR_USE; - if (cbctx != NULL) - if (str_parse(arg, cbctx) <= 0) { - //printf("DEBUG: \"%s\" does NOT match \"%s\"\n", arg, cbctx); - return OPTION_ERR_USE; - } - //printf("DEBUG: \"%s\" does match \"%s\"\n", arg, cbctx); - /* malloc/realloc existing + this new + terminating NULL */ - if (oc->data.m == NULL) { - //printf("DEBUG: before malloc, oc->data.m = %.8lx - ", (long)oc->data.m); - //printf("DEBUG: requesting %d bytes\n", ( 0 + 1 + 1) * sizeof(char **)); - if ((oc->data.m = (char **)malloc( ( 0 + 1 + 1) * sizeof(char **))) == NULL) - return OPTION_ERR_MEM; - //printf("DEBUG: after malloc, oc->data.m = %.8lx\n", (long)oc->data.m); - } - else { - //printf("DEBUG: before realloc, oc->data.m = %.8lx\n", (long)oc->data.m); - //printf("DEBUG: requesting %d bytes\n", (oc->ndata + 1 + 1) * sizeof(char **)); - if ((oc->data.m = (char **)realloc(oc->data.m, (oc->ndata + 1 + 1) * sizeof(char **))) == NULL) - return OPTION_ERR_MEM; - //printf("DEBUG: after realloc, oc->data.m = %.8lx\n", (long)oc->data.m); - } - if ((oc->data.m[oc->ndata] = strdup(arg)) == NULL) - return OPTION_ERR_MEM; - oc->ndata++; - oc->data.m[oc->ndata] = NULL; -#if 0 - { - int i; - printf("DEBUG: oc->ndata=%d\n", oc->ndata); - for (i=0; i<=oc->ndata; i++) - printf("DEBUG: oc->data[%3d] at %.8lx points to %.8lx = %s\n", i, (long)&oc->data.m[i], (long)oc->data.m[i], oc->data.m[i]); - } -#endif - break; - default: - return OPTION_ERR_ARG; - break; - } - return OPTION_OK; -} - -static lmtp2nntp_option_rc_t includeit(optionconfig_t *oc, char *arg, char *cbctx) +void config_context(lmtp2nntp_t *ctx) { - lmtp2nntp_option_t *o; - char *cpBuf = NULL; - int argc = 0; - char **argv = NULL; - - //printf("DEBUG: enter includeit %.8lx, \"%s\", \"%s\"\n", (long)oc, arg, cbctx); - - if ((o = oc->parent) == NULL) - return OPTION_ERR_USE; - - stdsyntax(oc, arg, cbctx); - //printf("DEBUG: *** 1 *** file going to be read in now\n"); - { - const char *filename = arg; - struct stat sb; - int fd; - - if (stat(filename, &sb) == -1) die("stat"); - if ((cpBuf = (char *)malloc((size_t)sb.st_size + 1)) == NULL) die("malloc"); - if ((fd = open(filename, O_RDONLY)) == -1) die("open"); - if (read(fd, (void *)cpBuf, (size_t)sb.st_size) != (ssize_t)sb.st_size) die("read"); - cpBuf[(int)sb.st_size] = '\0'; - if (close(fd) == -1) - die("close"); - } - //printf("DEBUG: *** 2 *** file as it was just read in ***\n%s***\n", cpBuf); - - { - char *cpI; /* pointer to next character to be read */ - char *cpO; /* pointer to next character to be written. Used for eliminating - backslash+newline at a line continuation */ - char *cpL; /* pointer to start of line */ - int pline; /* current physical (disregarding line continuation) line number */ - int lline; /* current logical lines first physical line number */ - int eline; /* flag signaling empty or just whitespace-filled line */ - char c; /* current character */ - char p; /* previous character */ - int eof; /* flag signaling end of file detected */ - - cpI = cpBuf; - cpO = cpBuf; - eof = FALSE; - pline = 1; - p = NUL; - - cpL = cpO; - lline = pline; - eline = TRUE; - while(!eof) { - c = *cpI++; - *cpO++ = c; - if (c == NUL) - eof = TRUE; - else - if (!isspace(c)) - eline = FALSE; - if (eof || (c == '\n')) { - pline++; - if (!eof && (p == '\\')) { /* line continuation situation */ - cpO-=2; /* need to remove both backslash+newline */ - } - else { - if (!eline) { /* process logical line unless it's empty */ - *(cpO-1) = NUL; - if (lline == (pline-1)) - ;//printf("DEBUG: line[%3d] = ***%s***\n", lline, cpL); - else - ;//printf("DEBUG: [%3d-%3d] = ***%s***\n", lline, pline-1, cpL); - { - char *cp = cpL; - char *option; - char *value; - char *cpNew; - argz_t Newarg; - - Newarg.as = 0; - Newarg.az = NULL; - if ((option = str_token(&cp, " \t", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL) - //printf("DEBUG: no command - comment only\n") - ;/* don't care about comments */ - else { - //printf("DEBUG: option = ***%s***\n", option); - if (argv == NULL) { - if ((argv = (char **)malloc( ( 1 + 1) * sizeof(char **))) == NULL) - return OPTION_ERR_MEM; - argc = 0; - argv[argc++] = "include"; - argv[argc] = NULL; - } - - if ((cpNew = (char *)malloc(2 + strlen(option) + 1)) == NULL) - return OPTION_ERR_MEM; - cpNew[0]=NUL; - strcat(cpNew, "--"); - strcat(cpNew, option); - if ((argv = (char **)realloc(argv, (argc + 1) * sizeof(char **))) == NULL) - return OPTION_ERR_MEM; - argv[argc++] = cpNew; - argv[argc] = NULL; - - if ((value = str_token(&cp, " \t", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL) - ;//printf("DEBUG: no value - section\n"); - else { - while(isspace((int)*value)) value++; - //printf("DEBUG: value = ***%s***\n", value); - if ((cpNew = strdup(value)) == NULL) - return OPTION_ERR_MEM; - if ((argv = (char **)realloc(argv, (argc + 1) * sizeof(char **))) == NULL) - return OPTION_ERR_MEM; - argv[argc++] = cpNew; - argv[argc] = NULL; - } - } - } - } - cpL = cpO; - lline = pline; - eline = TRUE; - } - } - p = c; - } - } - return option_parse_internal(o, argc, argv); -} - -lmtp2nntp_option_rc_t option_parse(lmtp2nntp_option_t *o, int argc, char **argv) -{ - lmtp2nntp_option_rc_t rc; - //printf("DEBUG: enter option_parse(%.8lx, %d, %.8lx)\n", (long)o, argc, (long)argv); - - if (o == NULL) - return OPTION_ERR_ARG; - - (void)option_register(o, "childsmax", 'C', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "childsmax" ); - (void)option_register(o, "daemonize", 'D', OPT_FLAG, &stdsyntax, NULL, "foo", NULL ); - (void)option_register(o, "kill", 'K', OPT_FLAG, &stdsyntax, NULL, "foo", NULL ); - (void)option_register(o, "pidfile", 'P', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "pidfile" ); - (void)option_register(o, "veryverbose", 'V', OPT_FLAG, &stdsyntax, NULL, "foo", NULL ); - (void)option_register(o, "acl", 'a', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "addr[/mask]" ); - (void)option_register(o, "bind", 'b', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "addr[:port]|-|path[:perms]" ); - (void)option_register(o, "client", 'c', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "addr[:port]" ); - (void)option_register(o, "destination", 'd', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "addr[:port]" ); - (void)option_register(o, "groupmode", 'g', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "groupmode" ); - (void)option_register(o, "headervalue", 'h', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "header: value" ); - (void)option_register(o, "include", 'i', OPT_MULTI, &includeit, "m/.*/", "foo", "configfile" ); - (void)option_register(o, "size", 's', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "bytes" ); - (void)option_register(o, "timeoutlmtpaccept", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); - (void)option_register(o, "timeoutlmtpread", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); - (void)option_register(o, "timeoutlmtpwrite", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); - (void)option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); - (void)option_register(o, "timeoutnntpread", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); - (void)option_register(o, "timeoutnntpwrite", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); - (void)option_register(o, "mailfrom", 'm', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "regex" ); - (void)option_register(o, "nodename", 'n', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "nodename" ); - (void)option_register(o, "operationmode", 'o', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "post|feed" ); - (void)option_register(o, "l2spec", 'l', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "spec" ); - (void)option_register(o, "uid", 'u', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "number|name" ); - (void)option_register(o, "restrictheader", 'r', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "regex" ); - (void)option_register(o, "newsgroup", NUL, OPT_MULTI, &stdsyntax, "m/.*/", "foo", "newsgroup"); - -#if 0 - { - int i; - - for (i=0; i<26; i++) { - printf("DEBUG: o->pt[%3d].longName = %s \n", i, o->pt[i].longName ); - printf("DEBUG: o->pt[%3d].shortName = %c \n", i, o->pt[i].shortName ); - printf("DEBUG: o->pt[%3d].argInfo = %d \n", i, o->pt[i].argInfo ); - printf("DEBUG: o->pt[%3d].arg = %.8lx\n", i, (long)o->pt[i].arg ); - printf("DEBUG: o->pt[%3d].val = %d \n", i, o->pt[i].val ); - printf("DEBUG: o->pt[%3d].descrip = %s \n", i, o->pt[i].descrip ); - printf("DEBUG: o->pt[%3d].argDescrip = %s \n", i, o->pt[i].argDescrip); - } - } -#endif - - //val_apply(o->vo, "", 9, dumper, "all" ); - rc = option_parse_internal(o, argc, argv); - val_apply(o->vo, "", 9, dumper, "all" ); - return rc; -} - -lmtp2nntp_option_rc_t option_destroy(lmtp2nntp_option_t *o) -{ - optionconfig_t *oc; - int i; - - //printf("DEBUG: option_destroy %.8lx\n", (long)o); - - if (o == NULL) - return OPTION_ERR_ARG; - - oc = o->first; - while (oc != NULL) { - if (oc->type == OPT_SINGLE && oc->data.s != NULL) - free(oc->data.s); - if (oc->type == OPT_MULTI && oc->data.m != NULL) { - for (i = 0; i < oc->ndata; i++) - if (oc->data.m[i] == NULL) - break; - else - free(oc->data.m[i]); - free(oc->data.m); - } - oc = oc->next; - } - if (o->vo != NULL) - val_destroy(o->vo); - free(o); - - return OPTION_OK; + return; } Index: ossp-pkg/lmtp2nntp/lmtp2nntp_config.h RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.h,v rcsdiff -q -kk '-r1.5' '-r1.6' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.h,v' 2>/dev/null --- lmtp2nntp_config.h 2002/01/22 16:09:47 1.5 +++ lmtp2nntp_config.h 2002/01/24 12:04:46 1.6 @@ -21,67 +21,11 @@ ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ** USA, or contact the OSSP project . ** -** FIXME lmtp2nntp_option.h: LMTP to NNTP configuration parsing +** lmtp2nntp_config.h: config handling */ #include "lmtp2nntp_global.h" -#include "val.h" - -struct optionconfig_s; -typedef struct optionconfig_s optionconfig_t; - -typedef struct { - int childsmax; - int daemonize; - int kill; - char *pidfile; - argz_t acl; - char *bind; - char *client; - argz_t destination; - char *groupmode; - argz_t headervalue; - argz_t include; - char *size; - int *timeoutlmtpaccept; - int *timeoutlmtpread; - int *timeoutlmtpwrite; - int *timeoutnntpconnect; - int *timeoutnntpread; - int *timeoutnntpwrite; - char *mailfrom; - char *nodename; - char *operationmode; - char *l2spec; - char *uid; - argz_t restrictheader; - argz_t newsgroup; - /*FIXME above*/ - optionconfig_t *first; - optionconfig_t *last; - val_t *vo; /* val_t for all options */ - int pi; /* popt index to next record */ - int pn; /* popt number of available records */ - struct popt_option *pt; /* popt table */ - -} lmtp2nntp_option_t; - -typedef enum { - OPTION_OK, - OPTION_ERR_ARG, /* invalid args passed into function */ - OPTION_ERR_USE, /* invalid usage, bad data passed into function */ - OPTION_ERR_MEM, /* out of memory */ - OPTION_ERR_VAL /* libval failed */ -} lmtp2nntp_option_rc_t; - -typedef enum { - OPT_FLAG, - OPT_SINGLE, - OPT_MULTI -} optiontype_t; - -typedef lmtp2nntp_option_rc_t (optionloop_cb_t)(optionconfig_t *oc, char *arg, char *cbctx); -lmtp2nntp_option_rc_t option_create (lmtp2nntp_option_t **); -lmtp2nntp_option_rc_t option_register(lmtp2nntp_option_t *, char *, char, optiontype_t, optionloop_cb_t *, char *, char *, char *); -lmtp2nntp_option_rc_t option_parse (lmtp2nntp_option_t *, int, char **); -lmtp2nntp_option_rc_t option_destroy (lmtp2nntp_option_t *); +#include "fixme.h" +//#include "val.h" +//void config_context(lmtp2nntp_t *); +void config_context(lmtp2nntp_t *); Index: ossp-pkg/lmtp2nntp/lmtp2nntp_option.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.c,v' | diff -u /dev/null - -L'ossp-pkg/lmtp2nntp/lmtp2nntp_option.c' 2>/dev/null --- ossp-pkg/lmtp2nntp/lmtp2nntp_option.c +++ - 2025-04-12 00:43:05.338343996 +0200 @@ -0,0 +1,691 @@ +/* +** Copyright (c) 2001-2002 The OSSP Project +** Copyright (c) 2001-2002 Cable & Wireless Deutschland +** +** 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.org/pkg/lmtp2nntp/. +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version +** 2.0 of the License, or (at your option) any later version. +** +** This program 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 +** General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this file; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact the OSSP project . +** +** lmtp2nntp_option.h: option parsing +*/ + +#include +#include +#include + +/* third party (included) */ +#include "lmtp2nntp_argz.h" +#include "lmtp2nntp_popt.h" + +/* third party (linked in) */ +#include +#include + +/* library version check (compile-time) */ +#define STR_VERSION_HEX_REQ 0x009206 +#define STR_VERSION_STR_REQ "0.9.6" +#ifdef STR_VERSION_HEX +#if STR_VERSION_HEX < STR_VERSION_HEX_REQ +#error "require a newer version of OSSP Str" +#endif +#endif + +/* own headers */ +#include "lmtp2nntp_global.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#if defined(HAVE_DMALLOC_H) && defined(DMALLOC) +#include "dmalloc.h" +#endif +#include "lmtp2nntp_option.h" +#include "lmtp2nntp_config.h" +#include "lmtp2nntp_lmtp.h" +#include "lmtp2nntp_nntp.h" +#include "lmtp2nntp_msg.h" +#define _LMTP2NNTP_VERSION_C_AS_HEADER_ +#include "lmtp2nntp_version.c" +#undef _LMTP2NNTP_VERSION_C_AS_HEADER_ + +#ifndef FALSE +#define FALSE (1 != 1) +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifndef NUL +#define NUL '\0' +#endif + +static void die(char *msg) +{ + printf("ERROR: %s\n", msg); + exit(-1); +} + +struct optionconfig_s { + optionconfig_t *next; /* cleanup chain for destroy */ + lmtp2nntp_option_t *parent; /* include needs access to parent */ + /**/ + char *longname; /* the long name (optional if shortname given) */ + char shortname; /* the short name (optional if longname given) */ + char *descrip; /* description for autohelp */ + char *argdescrip; /* argument description for autohelp */ + optiontype_t type; /* OPT_FLAG, OPT_SINGLE, OPT_MULTI */ + optionloop_cb_t *cb; /* callback for first iteration - syntax check and include */ + void *cbctx; /* context for pass1 */ + val_t *val; /* val we are registered under */ + /**/ + int number; /* number of this option for popt */ + struct { /* option data as read from configuration */ + int f; /* OPT_FLAG */ + void *foo1, *foo2, *foo3, *foo4, *foo5, *foo6, *foo7, *foo8, *foo9; + char *s; /* OPT_SINGLE */ + void *bar1, *bar2, *bar3, *bar4, *bar5, *bar6, *bar7, *bar8, *bar9; + char **m; /* OPT_MULTI */ + } data; + int ndata; +}; + +static val_rc_t dumper(void *ctx, const char *name, int type, const char *desc, void *data) +{ + optionconfig_t *oc; + int i; + + if (type != VAL_TYPE_PTR) + return VAL_OK; + + oc = (optionconfig_t *)data; + + switch (oc->type) { + case OPT_FLAG: + printf("DEBUG: <%5s>, name=<%20s>, OPT_FLAG, desc=<%20s>, data@%.8lx->[%d]%d\n", (char *)ctx, name, desc, (long)oc, oc->ndata, oc->data.f); break; + case OPT_SINGLE: + printf("DEBUG: <%5s>, name=<%20s>, OPT_SINGLE, desc=<%20s>, data@%.8lx->[%d]\"%s\"\n", (char *)ctx, name, desc, (long)oc, oc->ndata, oc->data.s == NULL ? "NULL" : oc->data.s); + break; + case OPT_MULTI: + printf("DEBUG: <%5s>, name=<%20s>, OPT_MULTI, desc=<%20s>, data@%.8lx->[%d]%.8lx\n", (char *)ctx, name, desc, (long)oc, oc->ndata, (long)oc->data.m); + for (i = 0; i < oc->ndata; i++) { +#if 0 + { + int j; + printf("DEBUG: "); + for (j=0; j<8; j++) printf("%.2x ", (unsigned char)oc->data.m[i][j]); + printf(" "); + for (j=0; j<8; j++) printf("%c", isprint(oc->data.m[i][j]) ? oc->data.m[i][j] : '.'); + printf(" "); + } +#endif + printf("DEBUG: [%3d] %.8lx \"%s\"\n", i, (long)oc->data.m[i], oc->data.m[i]); + } + break; + default: + break; + } + return VAL_OK; +} +//lmtp2nntp_option_rc_t option_find(lmtp2nntp_option_t *o, int number, optionconfig_t **ocp); +static lmtp2nntp_option_rc_t option_find(lmtp2nntp_option_t *o, int number, optionconfig_t **ocp) +{ + lmtp2nntp_option_rc_t rc = VAL_OK; + + if (o == NULL || ocp == NULL) + return OPTION_ERR_ARG; + + *ocp = o->first; + while (*ocp != NULL && (*ocp)->number != number) + *ocp = (*ocp)->next; + + return rc; +} + + +lmtp2nntp_option_rc_t option_register(lmtp2nntp_option_t *o, char *longname, char shortname, optiontype_t type, optionloop_cb_t *cb, char *cbctx, char *descrip, char *argdescrip) +{ + lmtp2nntp_option_rc_t rc = VAL_OK; + optionconfig_t *oc; + + //printf("DEBUG: enter option_register(%.8lx, \"%s\", '%c', %d, %.8lx, %.8lx, \"%s\", \"%s\")\n", (long)o, longname, shortname, type, (long)cb, (long)cbctx, descrip, argdescrip); + + if (o == NULL || longname == NULL) + return OPTION_ERR_ARG; + + /* create a optionconfig_t structure */ + if ((oc = (optionconfig_t *)malloc(sizeof(optionconfig_t))) == NULL) + return OPTION_ERR_MEM; + //printf("DEBUG: optionconfig_t structure malloc'ed\n"); + oc->next = NULL; + oc->parent = o; + oc->longname = strdup(longname); + oc->shortname = shortname; + oc->descrip = descrip == NULL ? NULL : strdup(descrip); + oc->argdescrip = argdescrip == NULL ? NULL : strdup(argdescrip); + oc->type = type; + oc->cb = cb; + oc->cbctx = cbctx; + oc->val = o->vo; + oc->number = o->pi + 1; /* 0 is a reserved val in popt, so offset 1 */ + oc->data.f = 0; + oc->data.s = NULL; /* just in case a pointer is larger than int */ + oc->data.m = NULL; + oc->ndata = 0; + if ( ( oc->longname == NULL) + || (descrip != NULL && oc->descrip == NULL) + || (argdescrip != NULL && oc->argdescrip == NULL) + ) + CU(OPTION_ERR_MEM); + + //printf("DEBUG: optionconfig_t structure created\n"); + + /* feed lib_val */ + if (val_reg(oc->val, oc->longname, VAL_TYPE_PTR, oc->descrip, oc) != VAL_OK) + CU(OPTION_ERR_USE); + + //printf("DEBUG: val_reg'ed\n"); + + /* feed lib_popt */ + //printf("DEBUG: o->pi=%d, o->pn=%d\n", o->pi, o->pn); + if (o->pi >= (o->pn-2)) { /* correction by two here, in malloc and realloc is for AUTOHELP and TABLEEND */ + if (o->pt == NULL) { + //printf("DEBUG: malloc\n"); + o->pt = (struct popt_option *)malloc( (1 + 2) * sizeof(struct popt_option)); + o->pn = 1; + } + else { + //printf("DEBUG: realloc\n"); + o->pt = (struct popt_option *)realloc(o->pt, (o->pn * 2 + 2) * sizeof(struct popt_option)); + o->pn = o->pn * 2; + } + } + if (o->pt == NULL) + CU(OPTION_ERR_MEM); + o->pt[o->pi].longName = oc->longname; + o->pt[o->pi].shortName = oc->shortname; + o->pt[o->pi].argInfo = oc->type == OPT_FLAG ? POPT_ARG_NONE : POPT_ARG_STRING; + o->pt[o->pi].arg = NULL; + o->pt[o->pi].val = oc->number; + o->pt[o->pi].descrip = oc->descrip; + o->pt[o->pi].argDescrip = oc->argdescrip; + + /* append POPT_AUTOHELP */ + o->pt[o->pi+1].longName = NULL; + o->pt[o->pi+1].shortName = '\0'; + o->pt[o->pi+1].argInfo = POPT_ARG_INCLUDE_TABLE; + o->pt[o->pi+1].arg = popt_helpoptions; + o->pt[o->pi+1].val = 0; + o->pt[o->pi+1].descrip = "Help options:"; + o->pt[o->pi+1].argDescrip = NULL; + + /* append POPT_TABLEEND */ + o->pt[o->pi+2].longName = NULL; + o->pt[o->pi+2].shortName = '\0'; + o->pt[o->pi+2].argInfo = 0; + o->pt[o->pi+2].arg = 0; + o->pt[o->pi+2].val = 0; + o->pt[o->pi+2].descrip = NULL; + o->pt[o->pi+2].argDescrip = NULL; + o->pi++; + //printf("DEBUG: popt'ed\n"); + + /* link in this new optionconfig_t structure */ + if (o->first == NULL) { + o->first = oc; + o->last = oc; + } + else { + o->last->next = oc; + o->last = oc; + } + //printf("DEBUG: linked\n"); + + return rc; + + CUS: + if (oc != NULL) { + if (oc->argdescrip != NULL) free(oc->argdescrip); + if (oc->descrip != NULL) free(oc->descrip); + if (oc->longname != NULL) free(oc->longname); + free(oc); + } + return rc; +} + +lmtp2nntp_option_rc_t option_create(lmtp2nntp_option_t **op, val_t *parent) +{ + //printf("DEBUG: enter option_create(%.8lx)\n", (long)op); + + if (op == NULL) + return OPTION_ERR_ARG; + + if ((*op = (lmtp2nntp_option_t *)malloc(sizeof(lmtp2nntp_option_t))) == NULL) + return OPTION_ERR_MEM; + (*op)->childsmax = 0; + (*op)->daemonize = 0; + (*op)->kill = 0; + (*op)->pidfile = 0; + (*op)->acl.as = 0; + (*op)->acl.az = NULL; + (*op)->bind = NULL; + (*op)->client = NULL; + (*op)->destination.as = 0; + (*op)->destination.az = NULL; + (*op)->groupmode = NULL; + (*op)->headervalue.as = 0; + (*op)->headervalue.az = NULL; + (*op)->include.as = 0; + (*op)->include.az = NULL; + (*op)->size = 0; + (*op)->timeoutlmtpaccept = 0; + (*op)->timeoutlmtpread = 0; + (*op)->timeoutlmtpwrite = 0; + (*op)->timeoutnntpconnect = 0; + (*op)->timeoutnntpread = 0; + (*op)->timeoutnntpwrite = 0; + (*op)->mailfrom = NULL; + (*op)->nodename = NULL; + (*op)->operationmode = NULL; + (*op)->l2spec = NULL; + (*op)->uid = NULL; + (*op)->restrictheader.as = 0; + (*op)->restrictheader.az = NULL; + (*op)->newsgroup.as = 0; + (*op)->newsgroup.az = NULL; + /**/ + (*op)->first = NULL; + (*op)->last = NULL; + (*op)->vo = NULL; + (*op)->pn = 0; + (*op)->pi = 0; + (*op)->pt = NULL; + + if (val_create(&((*op)->vo)) != VAL_OK) { + free(*op); + return OPTION_ERR_VAL; + } + if (val_reg(parent, "option", VAL_TYPE_VAL, "option", (void *)&((*op)->vo)) != VAL_OK) { + free(*op); + return OPTION_ERR_VAL; + } + return OPTION_OK; +} + +static lmtp2nntp_option_rc_t option_parse_internal(lmtp2nntp_option_t *o, int argc, char **argv) +{ + int i; + char *cp; + optionconfig_t *ocp; + popt_context poptCon; /* context for parsing command-line options */ + +#if 0 + { + int i; + + for (i=0; ipt, 0); + popt_setotheroptionhelp(poptCon, "[OPTIONS]* [newsgroup ...]"); + //printf("DEBUG: argc=%d\n", argc); + if (argc < 2) { + popt_printusage(poptCon, stderr, 0); + exit(1); + } + while ((i = popt_getnextopt(poptCon)) >= 0) { + (void)option_find(o, i, &ocp); + //printf("DEBUG: ocp->type=%d\n", ocp->type); + if (ocp->cb != NULL) + ocp->cb(ocp, cp = (ocp->type == OPT_FLAG ? NULL : (char *)popt_getoptarg(poptCon)), ocp->cbctx); + //printf("DEBUG: popt_getnextopt returned %d \"%s\", \"%s\"\n", i-1, o->pt[i-1].longName, ocp->longname); + //printf("DEBUG: popt_getoptarg returned \"%s\"\n", cp); + } + //printf("DEBUG: current popt error is \"%s\"(%d)\n", popt_strerror(i), i); + //printf("DEBUG: ----\n"); + + { + int largc; + char **largv; + char *cpNew; + + if ((largv = (char **)malloc((1 + 1) * sizeof(char **))) == NULL) + return OPTION_ERR_MEM; + largc = 0; + largv[largc++] = "leftover"; + largv[largc] = NULL; + while ((cp = (char *)popt_getarg(poptCon)) != NULL) { + //printf("DEBUG: popt_getarg returned \"%s\"\n", cp); + if ((largv = (char **)realloc(largv, (largc + 2) * sizeof(char **))) == NULL) + return OPTION_ERR_MEM; + largv[largc++] = "--newsgroup"; + largv[largc] = NULL; + if ((cpNew = strdup(cp)) == NULL) + return OPTION_ERR_MEM; + //printf("DEBUG: cpNew = \"%s\"\n", cpNew); + largv[largc++] = cpNew; + largv[largc] = NULL; + //printf("DEBUG: largc = \"%d\"\n", largc); +#if 0 + for (i=0; i 1) + option_parse_internal(o, largc, largv); + } + //printf("DEBUG: current popt error is \"%s\"(%d)\n", popt_strerror(i), i); + popt_freecontext(poptCon); + return OPTION_OK; +} + +static lmtp2nntp_option_rc_t stdsyntax(optionconfig_t *oc, char *arg, char *cbctx) +{ + printf("DEBUG: enter stdsyntax %.8lx, \"%s\", \"%s\"\n", (long)oc, arg, cbctx); + + //printf("DEBUG: oc->type=%d\n", oc->type); + switch (oc->type) { + case OPT_FLAG: + //printf("DEBUG: flag %20s = %s should match %s\n", oc->longname, arg, cbctx); + if (arg != NULL || cbctx != NULL) + return OPTION_ERR_ARG; + if (oc->ndata >= 1) + return OPTION_ERR_USE; + oc->data.f = 1; + oc->ndata = 1; + break; + case OPT_SINGLE: + //printf("DEBUG: single %20s = %s should match %s\n", oc->longname, arg, cbctx); + if (arg == NULL) + return OPTION_ERR_ARG; + /* use this if repeated overwriting definitions are not allowed + * if (oc->ndata >= 1 || oc->data.s != NULL) + * return OPTION_ERR_USE; + */ + if (cbctx != NULL) + if (str_parse(arg, cbctx) <= 0) { + //printf("DEBUG: \"%s\" does NOT match \"%s\"\n", arg, cbctx); + return OPTION_ERR_USE; + } + //printf("DEBUG: \"%s\" does match \"%s\"\n", arg, cbctx); + if ((oc->data.s = strdup(arg)) == NULL) + return OPTION_ERR_MEM; + oc->ndata = 1; + break; + case OPT_MULTI: + //printf("DEBUG: multi %20s = %s should match %s\n", oc->longname, arg, cbctx); + if (arg == NULL) + return OPTION_ERR_ARG; + if (oc->ndata >= 1 && oc->data.m == NULL) + return OPTION_ERR_USE; + if (cbctx != NULL) + if (str_parse(arg, cbctx) <= 0) { + //printf("DEBUG: \"%s\" does NOT match \"%s\"\n", arg, cbctx); + return OPTION_ERR_USE; + } + //printf("DEBUG: \"%s\" does match \"%s\"\n", arg, cbctx); + /* malloc/realloc existing + this new + terminating NULL */ + if (oc->data.m == NULL) { + //printf("DEBUG: before malloc, oc->data.m = %.8lx - ", (long)oc->data.m); + //printf("DEBUG: requesting %d bytes\n", ( 0 + 1 + 1) * sizeof(char **)); + if ((oc->data.m = (char **)malloc( ( 0 + 1 + 1) * sizeof(char **))) == NULL) + return OPTION_ERR_MEM; + //printf("DEBUG: after malloc, oc->data.m = %.8lx\n", (long)oc->data.m); + } + else { + //printf("DEBUG: before realloc, oc->data.m = %.8lx\n", (long)oc->data.m); + //printf("DEBUG: requesting %d bytes\n", (oc->ndata + 1 + 1) * sizeof(char **)); + if ((oc->data.m = (char **)realloc(oc->data.m, (oc->ndata + 1 + 1) * sizeof(char **))) == NULL) + return OPTION_ERR_MEM; + //printf("DEBUG: after realloc, oc->data.m = %.8lx\n", (long)oc->data.m); + } + if ((oc->data.m[oc->ndata] = strdup(arg)) == NULL) + return OPTION_ERR_MEM; + oc->ndata++; + oc->data.m[oc->ndata] = NULL; +#if 0 + { + int i; + printf("DEBUG: oc->ndata=%d\n", oc->ndata); + for (i=0; i<=oc->ndata; i++) + printf("DEBUG: oc->data[%3d] at %.8lx points to %.8lx = %s\n", i, (long)&oc->data.m[i], (long)oc->data.m[i], oc->data.m[i]); + } +#endif + break; + default: + return OPTION_ERR_ARG; + break; + } + return OPTION_OK; +} + +static lmtp2nntp_option_rc_t includeit(optionconfig_t *oc, char *arg, char *cbctx) +{ + lmtp2nntp_option_t *o; + char *cpBuf = NULL; + int argc = 0; + char **argv = NULL; + + //printf("DEBUG: enter includeit %.8lx, \"%s\", \"%s\"\n", (long)oc, arg, cbctx); + + if ((o = oc->parent) == NULL) + return OPTION_ERR_USE; + + stdsyntax(oc, arg, cbctx); + //printf("DEBUG: *** 1 *** file going to be read in now\n"); + { + const char *filename = arg; + struct stat sb; + int fd; + + if (stat(filename, &sb) == -1) die("stat"); + if ((cpBuf = (char *)malloc((size_t)sb.st_size + 1)) == NULL) die("malloc"); + if ((fd = open(filename, O_RDONLY)) == -1) die("open"); + if (read(fd, (void *)cpBuf, (size_t)sb.st_size) != (ssize_t)sb.st_size) die("read"); + cpBuf[(int)sb.st_size] = '\0'; + if (close(fd) == -1) + die("close"); + } + //printf("DEBUG: *** 2 *** file as it was just read in ***\n%s***\n", cpBuf); + + { + char *cpI; /* pointer to next character to be read */ + char *cpO; /* pointer to next character to be written. Used for eliminating + backslash+newline at a line continuation */ + char *cpL; /* pointer to start of line */ + int pline; /* current physical (disregarding line continuation) line number */ + int lline; /* current logical lines first physical line number */ + int eline; /* flag signaling empty or just whitespace-filled line */ + char c; /* current character */ + char p; /* previous character */ + int eof; /* flag signaling end of file detected */ + + cpI = cpBuf; + cpO = cpBuf; + eof = FALSE; + pline = 1; + p = NUL; + + cpL = cpO; + lline = pline; + eline = TRUE; + while(!eof) { + c = *cpI++; + *cpO++ = c; + if (c == NUL) + eof = TRUE; + else + if (!isspace(c)) + eline = FALSE; + if (eof || (c == '\n')) { + pline++; + if (!eof && (p == '\\')) { /* line continuation situation */ + cpO-=2; /* need to remove both backslash+newline */ + } + else { + if (!eline) { /* process logical line unless it's empty */ + *(cpO-1) = NUL; + if (lline == (pline-1)) + ;//printf("DEBUG: line[%3d] = ***%s***\n", lline, cpL); + else + ;//printf("DEBUG: [%3d-%3d] = ***%s***\n", lline, pline-1, cpL); + { + char *cp = cpL; + char *option; + char *value; + char *cpNew; + argz_t Newarg; + + Newarg.as = 0; + Newarg.az = NULL; + if ((option = str_token(&cp, " \t", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL) + //printf("DEBUG: no command - comment only\n") + ;/* don't care about comments */ + else { + //printf("DEBUG: option = ***%s***\n", option); + if (argv == NULL) { + if ((argv = (char **)malloc( ( 1 + 1) * sizeof(char **))) == NULL) + return OPTION_ERR_MEM; + argc = 0; + argv[argc++] = "include"; + argv[argc] = NULL; + } + + if ((cpNew = (char *)malloc(2 + strlen(option) + 1)) == NULL) + return OPTION_ERR_MEM; + cpNew[0]=NUL; + strcat(cpNew, "--"); + strcat(cpNew, option); + if ((argv = (char **)realloc(argv, (argc + 1) * sizeof(char **))) == NULL) + return OPTION_ERR_MEM; + argv[argc++] = cpNew; + argv[argc] = NULL; + + if ((value = str_token(&cp, " \t", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL) + ;//printf("DEBUG: no value - section\n"); + else { + while(isspace((int)*value)) value++; + //printf("DEBUG: value = ***%s***\n", value); + if ((cpNew = strdup(value)) == NULL) + return OPTION_ERR_MEM; + if ((argv = (char **)realloc(argv, (argc + 1) * sizeof(char **))) == NULL) + return OPTION_ERR_MEM; + argv[argc++] = cpNew; + argv[argc] = NULL; + } + } + } + } + cpL = cpO; + lline = pline; + eline = TRUE; + } + } + p = c; + } + } + return option_parse_internal(o, argc, argv); +} + +lmtp2nntp_option_rc_t option_parse(lmtp2nntp_option_t *o, int argc, char **argv) +{ + lmtp2nntp_option_rc_t rc; + //printf("DEBUG: enter option_parse(%.8lx, %d, %.8lx)\n", (long)o, argc, (long)argv); + + if (o == NULL) + return OPTION_ERR_ARG; + + (void)option_register(o, "childsmax", 'C', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "childsmax" ); + (void)option_register(o, "daemonize", 'D', OPT_FLAG, &stdsyntax, NULL, "foo", NULL ); + (void)option_register(o, "kill", 'K', OPT_FLAG, &stdsyntax, NULL, "foo", NULL ); + (void)option_register(o, "pidfile", 'P', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "pidfile" ); + (void)option_register(o, "veryverbose", 'V', OPT_FLAG, &stdsyntax, NULL, "foo", NULL ); + (void)option_register(o, "acl", 'a', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "addr[/mask]" ); + (void)option_register(o, "bind", 'b', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "addr[:port]|-|path[:perms]" ); + (void)option_register(o, "client", 'c', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "addr[:port]" ); + (void)option_register(o, "destination", 'd', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "addr[:port]" ); + (void)option_register(o, "groupmode", 'g', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "groupmode" ); + (void)option_register(o, "headervalue", 'h', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "header: value" ); + (void)option_register(o, "include", 'i', OPT_MULTI, &includeit, "m/.*/", "foo", "configfile" ); + (void)option_register(o, "size", 's', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "bytes" ); + (void)option_register(o, "timeoutlmtpaccept", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); + (void)option_register(o, "timeoutlmtpread", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); + (void)option_register(o, "timeoutlmtpwrite", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); + (void)option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); + (void)option_register(o, "timeoutnntpread", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); + (void)option_register(o, "timeoutnntpwrite", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "sec" ); + (void)option_register(o, "mailfrom", 'm', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "regex" ); + (void)option_register(o, "nodename", 'n', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "nodename" ); + (void)option_register(o, "operationmode", 'o', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "post|feed" ); + (void)option_register(o, "l2spec", 'l', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "spec" ); + (void)option_register(o, "uid", 'u', OPT_SINGLE, &stdsyntax, "m/.*/", "foo", "number|name" ); + (void)option_register(o, "restrictheader", 'r', OPT_MULTI, &stdsyntax, "m/.*/", "foo", "regex" ); + (void)option_register(o, "newsgroup", NUL, OPT_MULTI, &stdsyntax, "m/.*/", "foo", "newsgroup"); + +#if 0 + { + int i; + + for (i=0; i<26; i++) { + printf("DEBUG: o->pt[%3d].longName = %s \n", i, o->pt[i].longName ); + printf("DEBUG: o->pt[%3d].shortName = %c \n", i, o->pt[i].shortName ); + printf("DEBUG: o->pt[%3d].argInfo = %d \n", i, o->pt[i].argInfo ); + printf("DEBUG: o->pt[%3d].arg = %.8lx\n", i, (long)o->pt[i].arg ); + printf("DEBUG: o->pt[%3d].val = %d \n", i, o->pt[i].val ); + printf("DEBUG: o->pt[%3d].descrip = %s \n", i, o->pt[i].descrip ); + printf("DEBUG: o->pt[%3d].argDescrip = %s \n", i, o->pt[i].argDescrip); + } + } +#endif + + //val_apply(o->vo, "", 9, dumper, "all" ); + rc = option_parse_internal(o, argc, argv); + val_apply(o->vo, "", 9, dumper, "all" ); + return rc; +} + +lmtp2nntp_option_rc_t option_destroy(lmtp2nntp_option_t *o) +{ + optionconfig_t *oc; + int i; + + //printf("DEBUG: option_destroy %.8lx\n", (long)o); + + if (o == NULL) + return OPTION_ERR_ARG; + + oc = o->first; + while (oc != NULL) { + if (oc->type == OPT_SINGLE && oc->data.s != NULL) + free(oc->data.s); + if (oc->type == OPT_MULTI && oc->data.m != NULL) { + for (i = 0; i < oc->ndata; i++) + if (oc->data.m[i] == NULL) + break; + else + free(oc->data.m[i]); + free(oc->data.m); + } + oc = oc->next; + } + if (o->vo != NULL) + val_destroy(o->vo); + free(o); + + return OPTION_OK; +} Index: ossp-pkg/lmtp2nntp/lmtp2nntp_option.h RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.h,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.h,v' | diff -u /dev/null - -L'ossp-pkg/lmtp2nntp/lmtp2nntp_option.h' 2>/dev/null --- ossp-pkg/lmtp2nntp/lmtp2nntp_option.h +++ - 2025-04-12 00:43:05.341784501 +0200 @@ -0,0 +1,87 @@ +/* +** Copyright (c) 2001-2002 The OSSP Project +** Copyright (c) 2001-2002 Cable & Wireless Deutschland +** +** 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.org/pkg/lmtp2nntp/. +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version +** 2.0 of the License, or (at your option) any later version. +** +** This program 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 +** General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this file; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +** USA, or contact the OSSP project . +** +** lmtp2nntp_option.h: option parsing +*/ + +#include "lmtp2nntp_global.h" +#include "val.h" + +struct optionconfig_s; +typedef struct optionconfig_s optionconfig_t; + +typedef struct { + int childsmax; + int daemonize; + int kill; + char *pidfile; + argz_t acl; + char *bind; + char *client; + argz_t destination; + char *groupmode; + argz_t headervalue; + argz_t include; + char *size; + int *timeoutlmtpaccept; + int *timeoutlmtpread; + int *timeoutlmtpwrite; + int *timeoutnntpconnect; + int *timeoutnntpread; + int *timeoutnntpwrite; + char *mailfrom; + char *nodename; + char *operationmode; + char *l2spec; + char *uid; + argz_t restrictheader; + argz_t newsgroup; + /*FIXME above*/ + optionconfig_t *first; + optionconfig_t *last; + val_t *vo; /* val_t for all options */ + int pi; /* popt index to next record */ + int pn; /* popt number of available records */ + struct popt_option *pt; /* popt table */ + +} lmtp2nntp_option_t; + +typedef enum { + OPTION_OK, + OPTION_ERR_ARG, /* invalid args passed into function */ + OPTION_ERR_USE, /* invalid usage, bad data passed into function */ + OPTION_ERR_MEM, /* out of memory */ + OPTION_ERR_VAL /* libval failed */ +} lmtp2nntp_option_rc_t; + +typedef enum { + OPT_FLAG, + OPT_SINGLE, + OPT_MULTI +} optiontype_t; + +typedef lmtp2nntp_option_rc_t (optionloop_cb_t)(optionconfig_t *oc, char *arg, char *cbctx); +lmtp2nntp_option_rc_t option_create (lmtp2nntp_option_t **, val_t *); +lmtp2nntp_option_rc_t option_register(lmtp2nntp_option_t *, char *, char, optiontype_t, optionloop_cb_t *, char *, char *, char *); +lmtp2nntp_option_rc_t option_parse (lmtp2nntp_option_t *, int, char **); +lmtp2nntp_option_rc_t option_destroy (lmtp2nntp_option_t *);