head 1.32; access; symbols LMTP2NNTP_1_4_1:1.32 LMTP2NNTP_1_4_0:1.32 LMTP2NNTP_1_3_0:1.32 LMTP2NNTP_1_3b2:1.32 LMTP2NNTP_1_3b1:1.32 LMTP2NNTP_1_3a3:1.32 LMTP2NNTP_1_3a2:1.32 LMTP2NNTP_1_3a1:1.32 LMTP2NNTP_1_2_0:1.32 LMTP2NNTP_1_2b4:1.32 LMTP2NNTP_1_2b3:1.31 LMTP2NNTP_1_2b2:1.30 LMTP2NNTP_1_2b1:1.23 LMTP2NNTP_1_2a8:1.23 LMTP2NNTP_1_2a7:1.23 LMTP2NNTP_1_2a6:1.21 LMTP2NNTP_1_2a5:1.19 LMTP2NNTP_1_2a4:1.17 LMTP2NNTP_1_2a3:1.15; locks; strict; comment @ * @; 1.32 date 2003.02.12.16.16.29; author rse; state Exp; branches; next 1.31; 1.31 date 2003.02.11.20.24.42; author thl; state Exp; branches; next 1.30; 1.30 date 2003.02.11.12.55.31; author thl; state Exp; branches; next 1.29; 1.29 date 2003.02.11.12.54.58; author thl; state Exp; branches; next 1.28; 1.28 date 2003.02.11.11.40.12; author thl; state Exp; branches; next 1.27; 1.27 date 2003.02.11.10.00.48; author thl; state Exp; branches; next 1.26; 1.26 date 2003.02.11.09.35.22; author thl; state Exp; branches; next 1.25; 1.25 date 2003.02.11.09.02.42; author thl; state Exp; branches; next 1.24; 1.24 date 2003.02.10.14.24.16; author thl; state Exp; branches; next 1.23; 1.23 date 2003.01.30.19.45.20; author rse; state Exp; branches; next 1.22; 1.22 date 2003.01.30.19.42.13; author rse; state Exp; branches; next 1.21; 1.21 date 2002.08.14.12.30.16; author thl; state Exp; branches; next 1.20; 1.20 date 2002.07.02.07.49.01; author rse; state Exp; branches; next 1.19; 1.19 date 2002.05.29.12.24.49; author thl; state Exp; branches; next 1.18; 1.18 date 2002.04.18.13.31.27; author thl; state Exp; branches; next 1.17; 1.17 date 2002.03.07.16.03.56; author thl; state Exp; branches; next 1.16; 1.16 date 2002.03.06.14.25.39; author thl; state Exp; branches; next 1.15; 1.15 date 2002.02.26.15.56.08; author thl; state Exp; branches; next 1.14; 1.14 date 2002.02.13.16.25.38; author thl; state Exp; branches; next 1.13; 1.13 date 2002.02.06.13.51.38; author thl; state Exp; branches; next 1.12; 1.12 date 2002.02.05.14.56.47; author thl; state Exp; branches; next 1.11; 1.11 date 2002.02.05.14.14.54; author thl; state Exp; branches; next 1.10; 1.10 date 2002.02.05.10.42.39; author thl; state Exp; branches; next 1.9; 1.9 date 2002.02.04.13.52.15; author thl; state Exp; branches; next 1.8; 1.8 date 2002.01.31.15.53.43; author thl; state Exp; branches; next 1.7; 1.7 date 2002.01.31.15.42.31; author thl; state Exp; branches; next 1.6; 1.6 date 2002.01.31.15.32.51; author thl; state Exp; branches; next 1.5; 1.5 date 2002.01.31.15.09.25; author thl; state Exp; branches; next 1.4; 1.4 date 2002.01.30.16.41.02; author thl; state Exp; branches; next 1.3; 1.3 date 2002.01.30.14.22.23; author thl; state Exp; branches; next 1.2; 1.2 date 2002.01.24.16.25.54; author thl; state Exp; branches; next 1.1; 1.1 date 2002.01.24.12.04.46; author thl; state Exp; branches; next ; desc @@ 1.32 log @finish DMalloc support @ text @/* ** OSSP lmtp2nntp - Mail to News Gateway ** Copyright (c) 2002-2003 Ralf S. Engelschall ** Copyright (c) 2002-2003 The OSSP Project ** Copyright (c) 2002-2003 Cable & Wireless Germany ** ** 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/tool/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.c: option parsing */ #include #include #include /* third party (included) */ #include "lmtp2nntp_argz.h" /* third party (linked in) */ #include "str.h" #include "val.h" #include "popt.h" /* 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(WITH_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 #if 0 static val_rc_t dumper(void *ctx, const char *name, int type, const char *desc, void *data) { optionval_t *oc; int i; if (type != VAL_TYPE_PTR) return VAL_OK; oc = *(optionval_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++) { { 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(" "); } printf("DEBUG: [%3d] %.8lx \"%s\"\n", i, (long)oc->data.m[i], oc->data.m[i]); } break; default: break; } return VAL_OK; } #endif static lmtp2nntp_option_rc_t option_find(lmtp2nntp_option_t *o, int number, optionval_t **ocp) { if (o == NULL || ocp == NULL) return OPTION_ERR_ARG; *ocp = o->first; while (*ocp != NULL && (*ocp)->number != number) *ocp = (*ocp)->next; if (*ocp == NULL) return OPTION_ERR_NUM; return OPTION_OK; } static void option_register(lmtp2nntp_option_t *o, char *longname, char shortname, optiontype_t type, char *def, char *descrip, char *argdescrip, optionloop_cb_t *cb, char *cbctx) { volatile struct { optionval_t *oc; } v; ex_t ex; v.oc = NULL; try { if (o == NULL || longname == NULL) throw(option_register, o, OPTION_ERR_ARG); /* create a optionval_t structure and initialize exception-uncritical data */ v.oc = (optionval_t *)mallocex(sizeof(optionval_t)); v.oc->next = NULL; v.oc->parent = o; v.oc->longname = NULL; v.oc->shortname = shortname; v.oc->descrip = NULL; v.oc->argdescrip = NULL; v.oc->type = type; v.oc->cb = cb; v.oc->cbctx = cbctx; v.oc->val = o->vo; v.oc->number = o->pi + 1; /* 0 is a reserved val in popt, so offset 1 */ switch (type) { case OPT_FLAG: v.oc->data.f = 0; break; case OPT_SINGLE: v.oc->data.s = NULL; break; case OPT_MULTI: v.oc->data.m = NULL; break; } v.oc->ndata = 0; /* preinitialization complete, now initialize exception-critical data*/ v.oc->longname = strdupex(longname); if (descrip != NULL) v.oc->descrip = strdupex(descrip); if (argdescrip != NULL) v.oc->argdescrip = strdupex(argdescrip); if (type == OPT_SINGLE && def != NULL) { v.oc->data.s = strdupex(def); v.oc->ndata = 1; } /* feed lib_val */ if (val_reg(v.oc->val, v.oc->longname, VAL_TYPE_PTR, v.oc->descrip, NULL) != VAL_OK) throw(option_register, o, OPTION_ERR_USE); if (val_set(v.oc->val, v.oc->longname, v.oc) != VAL_OK) throw(option_register, o, OPTION_ERR_USE); /* feed lib_popt */ if (o->pi >= (o->pn-2)) { /* correction by two here, in mallv.oc and reallv.oc is for AUTOHELP and TABLEEND */ if (o->pt == NULL) { o->pt = (struct popt_option *)mallocex( (1 + 2) * sizeof(struct popt_option)); o->pn = 1; } else { o->pt = (struct popt_option *)reallocex(o->pt, (o->pn * 2 + 2) * sizeof(struct popt_option)); o->pn = o->pn * 2; } } o->pt[o->pi].longName = v.oc->longname; o->pt[o->pi].shortName = v.oc->shortname; o->pt[o->pi].argInfo = v.oc->type == OPT_FLAG ? POPT_ARG_NONE : POPT_ARG_STRING; o->pt[o->pi].arg = NULL; o->pt[o->pi].val = v.oc->number; o->pt[o->pi].descrip = v.oc->descrip; o->pt[o->pi].argDescrip = v.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++; /* link in this new optionval_t structure */ if (o->first == NULL) { o->first = v.oc; o->last = v.oc; } else { o->last->next = v.oc; o->last = v.oc; } } catch(ex) { int i; if (v.oc != NULL) { if (type == OPT_SINGLE && v.oc->data.s != NULL) free(v.oc->data.s); if (type == OPT_MULTI && v.oc->data.m != NULL) { for (i = 0; i < v.oc->ndata; i++) if (v.oc->data.m[i] == NULL) break; else free(v.oc->data.m[i]); free(v.oc->data.m); } if (v.oc->argdescrip != NULL) free(v.oc->argdescrip); if (v.oc->descrip != NULL) free(v.oc->descrip); if (v.oc->longname != NULL) free(v.oc->longname); free(v.oc); } rethrow; } return; } /* this public function catches all underlying exceptions and properly returns a code */ lmtp2nntp_option_rc_t option_create(lmtp2nntp_option_t **op, val_t *parent) { ex_t ex; try { if (op == NULL || parent == NULL) return OPTION_ERR_ARG; (*op = (lmtp2nntp_option_t *)mallocex(sizeof(lmtp2nntp_option_t))); (*op)->first = NULL; (*op)->last = NULL; (*op)->vo = NULL; (*op)->pi = 0; (*op)->pn = 0; (*op)->pt = NULL; if (val_create(&((*op)->vo)) != VAL_OK) return OPTION_ERR_VAL; if (val_reg(parent, "option", VAL_TYPE_VAL, "option", (void *)&((*op)->vo)) != VAL_OK) return OPTION_ERR_VAL; } catch(ex) { if (*op != NULL) { if ((*op)->vo != NULL) val_unreg(parent, "option"); free(*op); } if (ex.ex_class == (void *)option_create) return (lmtp2nntp_option_rc_t)ex.ex_value; return OPTION_ERR_TRY; } return OPTION_OK; } static lmtp2nntp_option_rc_t option_parse_internal(lmtp2nntp_option_t *o, int argc, char **argv) { lmtp2nntp_option_rc_t rc = OPTION_OK; lmtp2nntp_option_rc_t rv; int i; char *cp; optionval_t *ocp; popt_context poptCon; /* internal function trusts args */ /* init lib_popt */ poptCon = popt_getcontext(NULL, argc, (const char **)argv, o->pt, 0); popt_setotheroptionhelp(poptCon, "[OPTIONS]* [newsgroup ...]"); /* print usage if too few argv's */ if (argc < 2) { popt_printusage(poptCon, stderr, 0); return OPTION_ERR_USE; } /* parse every option, continue when optarg missing or bad option found */ while ((i = popt_getnextopt(poptCon)) >= 0 || i == POPT_ERROR_NOARG || i == POPT_ERROR_BADOPT) { if (i == POPT_ERROR_NOARG || i == POPT_ERROR_BADOPT) { fprintf(stderr, "ERROR: %s (%d) \"%s\"\n", popt_strerror(i), i, popt_badoption(poptCon, POPT_BADOPTION_NOALIAS)); rc = OPTION_ERR_USE; continue; } if ((option_find(o, i, &ocp) == OPTION_OK) && (ocp->cb != NULL)) { rv = ocp->cb(ocp, cp = (ocp->type == OPT_FLAG ? NULL : (char *)popt_getoptarg(poptCon)), ocp->cbctx); if (cp != NULL) free(cp); /* TODO this should be the task of popt_freecontext but debugging showed popt does not free(3) */ if (rc == OPTION_OK) rc = rv; } } /* create a "--newsgroup" argc/argv for every leftover argument */ { ex_t ex; volatile struct { char **largv; } v; try { int largc; v.largv = (char **)mallocex((1 + 1) * sizeof(char **)); largc = 0; v.largv[largc] = NULL; v.largv[largc++] = strdupex("leftover"); v.largv[largc] = NULL; while ((cp = (char *)popt_getarg(poptCon)) != NULL) { v.largv = (char **)reallocex(v.largv, (1 + largc + 2) * sizeof(char **)); v.largv[largc++] = strdupex("--newsgroup"); v.largv[largc] = NULL; v.largv[largc++] = strdupex(cp); v.largv[largc] = NULL; } if (largc > 1) { rv = option_parse_internal(o, largc, v.largv); if (rc == OPTION_OK) rc = rv; } } cleanup { if (v.largv != NULL) { for (i = 0; v.largv[i] != NULL; i++) free(v.largv[i]); free(v.largv); } } catch(ex) { rc = OPTION_ERR_TRY; } } popt_freecontext(poptCon); return rc; } static lmtp2nntp_option_rc_t stdsyntax(optionval_t *oc, char *arg, char *cbctx) { switch (oc->type) { case OPT_FLAG: 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: if (arg == NULL) return OPTION_ERR_ARG; /* add this if repeated overwriting definitions of single values is not allowed * however, this will inhibit preinitialization with a default value * if (oc->ndata != 0) * return OPTION_ERR_USE; */ if (oc->ndata == 1 && oc->data.s != NULL) { /* free previous (default) assignment */ free(oc->data.s); oc->data.s = NULL; oc->ndata = 0; } if (cbctx != NULL) if (str_parse(arg, cbctx) <= 0) { fprintf(stderr, "ERROR: argument \"%s\" does NOT match syntax \"%s\"\n", arg, cbctx); return OPTION_ERR_USE; } if ((oc->data.s = strdup(arg)) == NULL) return OPTION_ERR_MEM; oc->ndata = 1; break; case OPT_MULTI: 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) { fprintf(stderr, "ERROR: argument \"%s\" does NOT match syntax \"%s\"\n", arg, cbctx); return OPTION_ERR_USE; } if (oc->data.m == NULL) /* existing + this new + terminating NULL */ oc->data.m = (char **)mallocex( ( 0 + 1 + 1) * sizeof(char **)); else oc->data.m = (char **)reallocex(oc->data.m, (oc->ndata + 1 + 1) * sizeof(char **)); oc->data.m[oc->ndata] = strdupex(arg); oc->ndata++; oc->data.m[oc->ndata] = NULL; break; default: return OPTION_ERR_ARG; break; } return OPTION_OK; } static lmtp2nntp_option_rc_t includeit(optionval_t *oc, char *arg, char *cbctx) { lmtp2nntp_option_rc_t rc = OPTION_OK; lmtp2nntp_option_t *o; volatile char *cpBuf = NULL; int argc = 0; char **argv = NULL; const char *filename = arg; struct stat sb; volatile int fd = -1; ex_t ex; 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 */ if ((o = oc->parent) == NULL) return OPTION_ERR_USE; try { if (stdsyntax(oc, arg, cbctx) != OPTION_OK) throw(0, 0, 0); if (stat(filename, &sb) == -1) throw(includeit, oc, "stat"); if (sb.st_size == 0) throw(includeit, oc, "size"); cpBuf = (char *)mallocex((size_t)sb.st_size + 1); if ((fd = open(filename, O_RDONLY)) == -1) throw(includeit, oc, "open"); if (read(fd, (void *)cpBuf, (size_t)sb.st_size) != (ssize_t)sb.st_size) throw(includeit, oc, "read"); cpBuf[(int)sb.st_size] = '\0'; cpI = (char *)cpBuf; cpO = (char *)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) ;/* no option? comment only! don't care about that. */ else { /* create fake argv[0] */ if (argv == NULL) { argv = (char **)mallocex((1 + 1) * sizeof(char **)); /* argv[0] + NULL */ argv[argc++] = strdupex("include"); argv[argc] = NULL; } /* handle option */ cpNew = (char *)mallocex(2 + strlen(option) + 1); /* dash dash option[] NUL */ cpNew[0]=NUL; strcat(cpNew, "--"); strcat(cpNew, option); argv = (char **)reallocex(argv, (1 + argc + 1) * sizeof(char **)); /* argv[0] + argv[1...argc] + NULL */ argv[argc++] = cpNew; argv[argc] = NULL; if ((value = str_token(&cp, " \t", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL) ;/* no value? optional anyway */ else { while(isspace((int)*value)) value++; /* handle value */ cpNew = strdupex(value); argv = (char **)reallocex(argv, (1 + argc + 1 + 1) * sizeof(char **)); /* argv[0] + argv[1...argc] + NULL */ argv[argc++] = cpNew; argv[argc] = NULL; } } } } cpL = cpO; lline = pline; eline = TRUE; } } p = c; } rc = option_parse_internal(o, argc, argv); } cleanup { int i; if (fd != -1) close(fd); if (argv != NULL) { for (i = 0; argv[i] != NULL; i++) { free(argv[i]); } free(argv); } if (cpBuf != NULL) free((char *)cpBuf); } catch(ex) { if (ex.ex_class == (void *)includeit && ex.ex_value != NULL) { fprintf(stderr, "ERROR: problem with \"%s\" while including \"%s\"\n", (char *)ex.ex_value, filename); } rc = OPTION_ERR_TRY; } return rc; } /* this public function catches all underlying exceptions and properly returns a code */ lmtp2nntp_option_rc_t option_parse(lmtp2nntp_option_t *o, int argc, char **argv) { ex_t ex; if (o == NULL || argc < 0 || argv == NULL) return OPTION_ERR_ARG; try { option_register(o, "childsmax", 'C', OPT_SINGLE, "10", "Childs the daemon spawns at max.", "childsmax", &stdsyntax, "m/\\d+/" ); /*"m/[0-9]+/"*/ option_register(o, "daemonize", 'D', OPT_FLAG, NULL, "Daemonize and detach from terminal", NULL, &stdsyntax, NULL ); option_register(o, "kill", 'K', OPT_FLAG, NULL, "Kill a previously run daemon", NULL, &stdsyntax, NULL ); option_register(o, "pidfile", 'P', OPT_SINGLE, NULL, "Pidfile holding the process ID", "filename", &stdsyntax, "m/.*/" ); option_register(o, "acl", 'a', OPT_MULTI, NULL, "LMTP daemon access control list", "addr[/mask]", &stdsyntax, "m/.*/" ); option_register(o, "bind", 'b', OPT_SINGLE, NULL, "LMTP daemon bind", "addr[:port]|-|path[:perms]", &stdsyntax, "m/.*/" ); option_register(o, "client", 'c', OPT_SINGLE, NULL, "NNTP client bind", "addr[:port]", &stdsyntax, "m/.*/" ); option_register(o, "destination", 'd', OPT_MULTI, NULL, "NNTP client destination", "addr[:port]", &stdsyntax, "m/.*/" ); option_register(o, "groupmode", 'g', OPT_SINGLE, "arg", "Groupmode configures news group(s)", "arg|envelope|header", &stdsyntax, "m/.*/" ); /*"m/(arg|envelope|header)/"*/ option_register(o, "headerrule", 'h', OPT_MULTI, NULL, "Header rewriting rule", "[pri]:[regex]:header:[val]", &stdsyntax, "m/^[0-9]*:.*:.+:.*$/" ); option_register(o, "include", 'i', OPT_MULTI, NULL, "Include a configuration file", "configfile", &includeit, "m/.*/" ); option_register(o, "l2spec", 'l', OPT_SINGLE, NULL, "L2 channel tree specification", "l2spec", &stdsyntax, "m/.*/" ); option_register(o, "mailfrom", 'm', OPT_SINGLE, NULL, "Mail from envelope restriction", "regex", &stdsyntax, "m/.*/" ); option_register(o, "nodename", 'n', OPT_SINGLE, NULL, "System nodename", "name", &stdsyntax, "m/.*/" ); option_register(o, "operationmode", 'o', OPT_SINGLE, "553/5.7.1", "Set fake status or operationmode", "abc/a.d.e|post|feed", &stdsyntax, "m/.*/" ); /*"m/([0-9]{3}\\/[0-9]\\.[0-9]\\.[0-9]|post|feed)/" ); 553 = Requested action not taken: mailbox name not allowed, 5.7.1 = Delivery not authorized, message refused */ option_register(o, "restrictheader", 'r', OPT_SINGLE, NULL, "Restrict messages by header", "regex", &stdsyntax, "m/.*/" ); option_register(o, "size", 's', OPT_SINGLE, "8388608", "Size limitation on message", "bytes", &stdsyntax, "m/.*/" ); /*"m/[0-9]+/"*/ option_register(o, "testfile", 't', OPT_MULTI, NULL, "Testfile for headerrule", "filename", &stdsyntax, "m/.*/" ); option_register(o, "timeoutlmtp", NUL, OPT_SINGLE, NULL, "LMTP server default timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutlmtpaccept", NUL, OPT_SINGLE, "0", "LMTP server accept timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutlmtpread", NUL, OPT_SINGLE, "10", "LMTP server read timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutlmtpwrite", NUL, OPT_SINGLE, "10", "LMTP server write timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntp", NUL, OPT_SINGLE, NULL, "NNTP client default timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE, "360", "NNTP client connect timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntpread", NUL, OPT_SINGLE, "60", "NNTP client read timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntpwrite", NUL, OPT_SINGLE, "60", "NNTP client write timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "user", 'u', OPT_SINGLE, NULL, "User identity", "uid|name", &stdsyntax, "m/.*/" ); option_register(o, "version", 'v', OPT_FLAG, NULL, "Version information", NULL, &stdsyntax, NULL ); option_register(o, "newsgroup", NUL, OPT_MULTI, NULL, "Newsgroup name or match", "newsgroup|wildmat", &stdsyntax, "m/.*/" ); } catch(ex) { if (ex.ex_class == (void *)option_create) return (lmtp2nntp_option_rc_t)ex.ex_value; return OPTION_ERR_TRY; } return option_parse_internal(o, argc, argv); } /* this public function catches all underlying exceptions and properly returns a code */ lmtp2nntp_option_rc_t option_destroy(lmtp2nntp_option_t *o) { optionval_t *oc; optionval_t *ocn; int i; 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); } if (oc->argdescrip != NULL) free(oc->argdescrip); if (oc->descrip != NULL) free(oc->descrip); if (oc->longname != NULL) free(oc->longname); ocn = oc->next; free(oc); oc = ocn; } if (o->vo != NULL) val_destroy(o->vo); if (o->pt != NULL) free(o->pt); free(o); return OPTION_OK; } @ 1.31 log @be more careful with free(3) @ text @d55 1 a55 1 #if defined(HAVE_DMALLOC_H) && defined(DMALLOC) @ 1.30 log @work around memory leak in popt @ text @d319 2 a320 1 free(cp); /* TODO this should be the task of popt_freecontext but debugging showed popt does not free(3) */ @ 1.29 log @fix memory leak when overriding a hardcoded default assignemnt @ text @d319 1 @ 1.28 log @cosmetics @ text @d381 3 a383 2 /* add this if repeated overwriting definitions of single values are not allowed * if (oc->ndata >= 1 || oc->data.s != NULL) d386 5 @ 1.27 log @consolidate two try/clean/catch blocks, fixing a memory leak around cpBuf @ text @d537 2 a538 1 if (fd != -1) close(fd); d540 1 a540 1 for (i = 0; argv[i] != NULL; i++) d542 1 @ 1.26 log @darn memory leak @ text @d430 9 a442 2 stdsyntax(oc, arg, cbctx); d444 2 a455 24 } cleanup { if (fd != -1) close(fd); } catch (ex) { if (ex.ex_class == (void *)includeit && ex.ex_value != NULL) { fprintf(stderr, "ERROR: problem with \"%s\" while including \"%s\"\n", (char *)ex.ex_value, filename); } if (cpBuf != NULL) free((char *)cpBuf); return OPTION_ERR_TRY; } try { 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 */ d537 1 d543 2 d547 3 @ 1.25 log @better use of ex, error reporting and memory handing in includeit() @ text @d646 2 @ 1.24 log @plug memory leak @ text @d360 1 a360 1 rethrow; d421 1 d426 4 d435 19 a453 23 { const char *filename = arg; struct stat sb; volatile int fd = -1; ex_t ex; try { if (stat(filename, &sb) == -1) throw(includeit, oc, "stat"); cpBuf = (char *)mallocex((size_t)sb.st_size + 1); if ((fd = open(filename, O_RDONLY)) == -1) throw(includeit, oc, "open"); if (read(fd, (void *)cpBuf, (size_t)sb.st_size) != (ssize_t)sb.st_size) throw(includeit, oc, "read"); cpBuf[(int)sb.st_size] = '\0'; } cleanup { if (fd != -1) close(fd); } catch (ex) { if (cpBuf != NULL) free((char *)cpBuf); rethrow; d455 3 d460 1 a460 1 { d511 1 a511 2 /*printf("DEBUG: no command - comment only\n")*/ ;/* don't care about comments */ d513 1 a513 1 /*printf("DEBUG: option = ***%s***\n", option);*/ d515 2 a516 4 if ((argv = (char **)malloc( ( 1 + 1) * sizeof(char **))) == NULL) return OPTION_ERR_MEM; argc = 0; argv[argc++] = "include"; d519 2 a520 3 if ((cpNew = (char *)malloc(2 + strlen(option) + 1)) == NULL) return OPTION_ERR_MEM; d524 1 a524 2 if ((argv = (char **)realloc(argv, (argc + 1 + 1) * sizeof(char **))) == NULL) return OPTION_ERR_MEM; d529 1 a529 1 ;/*printf("DEBUG: no value - section\n");*/ d532 3 a534 5 /*printf("DEBUG: value = ***%s***\n", value);*/ if ((cpNew = strdup(value)) == NULL) return OPTION_ERR_MEM; if ((argv = (char **)realloc(argv, (argc + 1 + 1) * sizeof(char **))) == NULL) return OPTION_ERR_MEM; d548 9 d558 4 a561 1 return option_parse_internal(o, argc, argv); @ 1.23 log @remove trailing whitespaces from source tree @ text @d229 1 d233 8 d606 1 d625 9 a633 1 oc = oc->next; @ 1.22 log @Apply the standard OSSP copyright header, document ASCII art and fix URL to lmtp2nntp homepage. @ text @d138 1 a138 1 d224 1 a224 1 o->last->next = v.oc; @ 1.21 log @consequently strdup and properly clean up; fix segfault reallocating too little space @ text @d2 4 a5 2 ** Copyright (c) 2001-2002 The OSSP Project ** Copyright (c) 2001-2002 Cable & Wireless Deutschland d9 1 a9 1 ** It can be found at http://www.ossp.org/pkg/lmtp2nntp/. d26 1 a26 1 ** lmtp2nntp_option.h: option parsing @ 1.20 log @get rid of all warnings under gcc 3.1 @ text @a321 1 char *cpNew; d325 2 a326 1 v.largv[largc++] = "leftover"; d329 2 a330 2 v.largv = (char **)reallocex(v.largv, (largc + 2) * sizeof(char **)); v.largv[largc++] = "--newsgroup"; d332 1 a332 2 cpNew = strdupex(cp); v.largv[largc++] = cpNew; d342 3 a344 1 if (v.largv != NULL) d346 1 @ 1.19 log @we need argc + new + terminating NULL to avoid segfaults @ text @d481 1 a481 1 ;//printf("DEBUG: line[%3d] = ***%s***\n", lline, cpL); d483 1 a483 1 ;//printf("DEBUG: [%3d-%3d] = ***%s***\n", lline, pline-1, cpL); d494 1 a494 1 //printf("DEBUG: no command - comment only\n") d497 1 a497 1 //printf("DEBUG: option = ***%s***\n", option); d517 1 a517 1 ;//printf("DEBUG: no value - section\n"); d520 1 a520 1 //printf("DEBUG: value = ***%s***\n", value); d551 1 a551 1 option_register(o, "childsmax", 'C', OPT_SINGLE, "10", "Childs the daemon spawns at max.", "childsmax", &stdsyntax, "m/\\d+/" ); //"m/[0-9]+/" ); d559 1 a559 1 option_register(o, "groupmode", 'g', OPT_SINGLE, "arg", "Groupmode configures news group(s)", "arg|envelope|header", &stdsyntax, "m/.*/" ); //"m/(arg|envelope|header)/" ); d565 1 a565 1 option_register(o, "operationmode", 'o', OPT_SINGLE, "553/5.7.1", "Set fake status or operationmode", "abc/a.d.e|post|feed", &stdsyntax, "m/.*/" ); //"m/([0-9]{3}\\/[0-9]\\.[0-9]\\.[0-9]|post|feed)/" ); /* 553 = Requested action not taken: mailbox name not allowed, 5.7.1 = Delivery not authorized, message refused */ d567 1 a567 1 option_register(o, "size", 's', OPT_SINGLE, "8388608", "Size limitation on message", "bytes", &stdsyntax, "m/.*/" ); //"m/[0-9]+/" ); d582 1 a582 1 if (ex.ex_class == option_create) @ 1.18 log @updated documentation, aligned and sorted source; @ text @d511 1 a511 1 if ((argv = (char **)realloc(argv, (argc + 1) * sizeof(char **))) == NULL) d523 1 a523 1 if ((argv = (char **)realloc(argv, (argc + 1) * sizeof(char **))) == NULL) @ 1.17 log @cleanup; better use of lib_ex; fight fixmes and resource leakage; cosmetics; flush; @ text @d551 29 a579 29 option_register(o, "childsmax", 'C', OPT_SINGLE, "10", "childs to spawn at max", "childsmax", &stdsyntax, "m/\\d+/" ); //"m/[0-9]+/" ); option_register(o, "daemonize", 'D', OPT_FLAG, NULL, "detach from terminal", NULL, &stdsyntax, NULL ); option_register(o, "kill", 'K', OPT_FLAG, NULL, "kill a previously run daemon", NULL, &stdsyntax, NULL ); option_register(o, "pidfile", 'P', OPT_SINGLE, NULL, "file containing pid", "pidfile", &stdsyntax, "m/.*/" ); option_register(o, "acl", 'a', OPT_MULTI, NULL, "LMTP server access control list", "addr[/mask]", &stdsyntax, "m/.*/" ); option_register(o, "bind", 'b', OPT_SINGLE, NULL, "LMTP server bind", "addr[:port]|-|path[:perms]", &stdsyntax, "m/.*/" ); option_register(o, "client", 'c', OPT_SINGLE, NULL, "NNTP client bind", "addr[:port]", &stdsyntax, "m/.*/" ); option_register(o, "destination", 'd', OPT_MULTI, NULL, "NNTP client destination", "addr[:port]", &stdsyntax, "m/.*/" ); option_register(o, "groupmode", 'g', OPT_SINGLE, "arg", "arg|envelope|header", "groupmode", &stdsyntax, "m/.*/" ); //"m/(arg|envelope|header)/" ); option_register(o, "headerrule", 'h', OPT_MULTI, NULL, "header rewriting rule", "[pri]:[regex]:header:[val]", &stdsyntax, "m/^[0-9]*:.*:.+:.*$/" ); option_register(o, "include", 'i', OPT_MULTI, NULL, "configfile to include", "configfile", &includeit, "m/.*/" ); option_register(o, "timeoutlmtp", NUL, OPT_SINGLE, NULL, "LMTP server default timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutlmtpaccept", NUL, OPT_SINGLE, "0", "LMTP server accept timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutlmtpread", NUL, OPT_SINGLE, "10", "LMTP server read timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutlmtpwrite", NUL, OPT_SINGLE, "10", "LMTP server write timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntp", NUL, OPT_SINGLE, NULL, "NNTP client default timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE, "360", "NNTP client connect timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntpread", NUL, OPT_SINGLE, "60", "NNTP client read timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "timeoutnntpwrite", NUL, OPT_SINGLE, "60", "NNTP client write timeout", "sec", &stdsyntax, "m/.*/" ); option_register(o, "l2spec", 'l', OPT_SINGLE, NULL, "L2 channel tree specification", "l2spec", &stdsyntax, "m/.*/" ); option_register(o, "mailfrom", 'm', OPT_SINGLE, NULL, "mail from envelope restriction", "regex", &stdsyntax, "m/.*/" ); option_register(o, "nodename", 'n', OPT_SINGLE, NULL, "nodename", "name", &stdsyntax, "m/.*/" ); option_register(o, "operationmode", 'o', OPT_SINGLE, "553/5.7.1", "fakestatus or operationmode", "abc/a.d.e|post|feed", &stdsyntax, "m/.*/" ); //"m/([0-9]{3}\\/[0-9]\\.[0-9]\\.[0-9]|post|feed)/" ); /* 553 = Requested action not taken: mailbox name not allowed, 5.7.1 = Delivery not authorized, message refused */ option_register(o, "restrictheader", 'r', OPT_SINGLE, NULL, "header restriction", "regex", &stdsyntax, "m/.*/" ); option_register(o, "size", 's', OPT_SINGLE, "8388608", "maximum message size", "bytes", &stdsyntax, "m/.*/" ); //"m/[0-9]+/" ); option_register(o, "testfile", 't', OPT_MULTI, NULL, "testfile for headerrule", "testfile", &stdsyntax, "m/.*/" ); option_register(o, "user", 'u', OPT_SINGLE, NULL, "user", "uid|name", &stdsyntax, "m/.*/" ); option_register(o, "version", 'v', OPT_FLAG, NULL, "print version", NULL, &stdsyntax, NULL ); option_register(o, "newsgroup", NUL, OPT_MULTI, NULL, "article destination", "newsgroup", &stdsyntax, "m/.*/" ); @ 1.16 log @Syntax and argument checking does no longer ignore errors silently. It properly prints error messages for unknown options or invalid arguments. The message printed includes what it got and what it expected. Processing is continued to check for more errors but finally it aborts before the main program starts. @ text @d130 1 a130 1 lmtp2nntp_option_rc_t option_register(lmtp2nntp_option_t *o, char *longname, char shortname, optiontype_t type, char *def, char *descrip, char *argdescrip, optionloop_cb_t *cb, char *cbctx) d132 4 a135 2 lmtp2nntp_option_rc_t rc = VAL_OK; optionval_t *oc; d137 4 a140 1 //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); d142 78 a219 62 if (o == NULL || longname == NULL) return OPTION_ERR_ARG; /* create a optionval_t structure */ if ((oc = (optionval_t *)malloc(sizeof(optionval_t))) == NULL) return OPTION_ERR_MEM; //printf("DEBUG: optionval_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 */ switch (type) { case OPT_FLAG: oc->data.f = 0; break; case OPT_SINGLE: oc->data.s = def == NULL ? NULL : strdup(def); break; case OPT_MULTI: oc->data.m = NULL; break; } oc->ndata = (type == OPT_SINGLE && def != NULL) ? 1 : 0; if ( ( oc->longname == NULL) || ( descrip != NULL && oc->descrip == NULL) || ( argdescrip != NULL && oc->argdescrip == NULL) || (type == OPT_SINGLE && def != NULL && oc->data.s == NULL) ) CU(OPTION_ERR_MEM); //printf("DEBUG: optionval_t structure created, oc at %.8lx is %.8lx\n", (long)&oc, (long)oc); /* feed lib_val */ if (val_reg(oc->val, oc->longname, VAL_TYPE_PTR, oc->descrip, NULL) != VAL_OK) CU(OPTION_ERR_USE); if (val_set(oc->val, oc->longname, oc) != VAL_OK) CU(OPTION_ERR_USE); //printf("DEBUG: val_reg'ed\n"); #if 0 { optionval_t *ov = 0x12345678; if (val_get(oc->val, oc->longname, &ov) == VAL_OK) printf("DEBUG: oc->val %.8lx %s in %.8lx d = \"s\"\n", (long)oc->val, oc->longname, (long)(oc)); if (val_get(o->vo, oc->longname, &ov) == VAL_OK) printf("DEBUG: o->vo %.8lx %s in %.8lx d = \"s\"\n", (long)o->vo, oc->longname, (long)(ov)); printf("DEBUG: val_get'ed\n"); } #endif /* 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; d222 3 a224 43 //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 optionval_t structure */ if (o->first == NULL) { o->first = oc; o->last = oc; } else { o->last->next = oc; o->last = oc; d226 13 a238 10 //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); d240 1 a240 1 return rc; d243 1 d249 2 a250 2 if (op == NULL) throw(option_create, NULL, OPTION_ERR_ARG); d261 1 a261 1 throw(option_create, NULL, OPTION_ERR_VAL); d264 1 a264 1 throw(option_create, NULL, OPTION_ERR_VAL); d272 3 a274 1 rethrow; d286 1 a286 1 popt_context poptCon; /* context for parsing command-line options */ d288 3 d293 2 d297 1 a297 1 exit(1); //FIXME d299 1 d313 1 d315 30 a344 15 int largc; char **largv; char *cpNew; largv = (char **)mallocex((1 + 1) * sizeof(char **)); largc = 0; largv[largc++] = "leftover"; largv[largc] = NULL; while ((cp = (char *)popt_getarg(poptCon)) != NULL) { largv = (char **)reallocex(largv, (largc + 2) * sizeof(char **)); largv[largc++] = "--newsgroup"; largv[largc] = NULL; cpNew = strdupex(cp); largv[largc++] = cpNew; largv[largc] = NULL; d346 2 a347 4 if (largc > 1) { rv = option_parse_internal(o, largc, largv); if (rc == OPTION_OK) rc = rv; a355 3 //printf("DEBUG: enter stdsyntax %.8lx, \"%s\", \"%s\"\n", (long)oc, arg, cbctx); //printf("DEBUG: oc->type=%d\n", oc->type); a357 1 //printf("DEBUG: flag %20s = %s should match %s\n", oc->longname, arg, cbctx); a365 1 //printf("DEBUG: single %20s = %s should match %s\n", oc->longname, arg, cbctx); d368 4 a371 4 /* use this if repeated overwriting definitions are not allowed * if (oc->ndata >= 1 || oc->data.s != NULL) * return OPTION_ERR_USE; */ a376 1 //printf("DEBUG: \"%s\" does match \"%s\"\n", arg, cbctx); a381 1 //printf("DEBUG: multi %20s = %s should match %s\n", oc->longname, arg, cbctx); d391 5 a395 18 //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; a397 8 #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 a412 2 //printf("DEBUG: enter includeit %.8lx, \"%s\", \"%s\"\n", (long)oc, arg, cbctx); a416 1 //printf("DEBUG: *** 1 *** file going to be read in now\n"); d424 7 a430 4 if (stat(filename, &sb) == -1) throw(0, 0, "stat"); if ((cpBuf = (char *)malloc((size_t)sb.st_size + 1)) == NULL) throw(0, 0, "malloc"); if ((fd = open(filename, O_RDONLY)) == -1) throw(0, 0, "open"); if (read(fd, (void *)cpBuf, (size_t)sb.st_size) != (ssize_t)sb.st_size) throw(0, 0, "read"); d437 2 a438 1 fprintf(stderr, "ERROR: caught %s\n", ex.ex_value == NULL ? "N/A" : (char *)ex.ex_value); a441 1 //printf("DEBUG: *** 2 *** file as it was just read in ***\n%s***\n", cpBuf); d542 1 d545 3 a547 1 if (o == NULL) d550 36 a585 30 (void)option_register(o, "childsmax", 'C', OPT_SINGLE, "10", "childs to spawn at max", "childsmax", &stdsyntax, "m/\\d+/" ); //"m/[0-9]+/" ); (void)option_register(o, "daemonize", 'D', OPT_FLAG, NULL, "detach from terminal", NULL, &stdsyntax, NULL ); (void)option_register(o, "kill", 'K', OPT_FLAG, NULL, "kill a previously run daemon", NULL, &stdsyntax, NULL ); (void)option_register(o, "pidfile", 'P', OPT_SINGLE, NULL, "file containing pid", "pidfile", &stdsyntax, "m/.*/" ); (void)option_register(o, "acl", 'a', OPT_MULTI, NULL, "LMTP server access control list", "addr[/mask]", &stdsyntax, "m/.*/" ); (void)option_register(o, "bind", 'b', OPT_SINGLE, NULL, "LMTP server bind", "addr[:port]|-|path[:perms]", &stdsyntax, "m/.*/" ); (void)option_register(o, "client", 'c', OPT_SINGLE, NULL, "NNTP client bind", "addr[:port]", &stdsyntax, "m/.*/" ); (void)option_register(o, "destination", 'd', OPT_MULTI, NULL, "NNTP client destination", "addr[:port]", &stdsyntax, "m/.*/" ); (void)option_register(o, "groupmode", 'g', OPT_SINGLE, "arg", "arg|envelope|header", "groupmode", &stdsyntax, "m/.*/" ); //"m/(arg|envelope|header)/" ); (void)option_register(o, "headerrule", 'h', OPT_MULTI, NULL, "header rewriting rule", "[pri]:[regex]:header:[val]", &stdsyntax, "m/^[0-9]*:.*:.+:.*$/" ); (void)option_register(o, "include", 'i', OPT_MULTI, NULL, "configfile to include", "configfile", &includeit, "m/.*/" ); (void)option_register(o, "timeoutlmtp", NUL, OPT_SINGLE, NULL, "LMTP server default timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "timeoutlmtpaccept", NUL, OPT_SINGLE, "0", "LMTP server accept timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "timeoutlmtpread", NUL, OPT_SINGLE, "10", "LMTP server read timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "timeoutlmtpwrite", NUL, OPT_SINGLE, "10", "LMTP server write timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "timeoutnntp", NUL, OPT_SINGLE, NULL, "NNTP client default timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE, "360", "NNTP client connect timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "timeoutnntpread", NUL, OPT_SINGLE, "60", "NNTP client read timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "timeoutnntpwrite", NUL, OPT_SINGLE, "60", "NNTP client write timeout", "sec", &stdsyntax, "m/.*/" ); (void)option_register(o, "l2spec", 'l', OPT_SINGLE, NULL, "L2 channel tree specification", "l2spec", &stdsyntax, "m/.*/" ); (void)option_register(o, "mailfrom", 'm', OPT_SINGLE, NULL, "mail from envelope restriction", "regex", &stdsyntax, "m/.*/" ); (void)option_register(o, "nodename", 'n', OPT_SINGLE, NULL, "nodename", "name", &stdsyntax, "m/.*/" ); (void)option_register(o, "operationmode", 'o', OPT_SINGLE, "553/5.7.1", "fakestatus or operationmode", "abc/a.d.e|post|feed", &stdsyntax, "m/.*/" ); //"m/([0-9]{3}\\/[0-9]\\.[0-9]\\.[0-9]|post|feed)/" ); /* 553 = Requested action not taken: mailbox name not allowed, 5.7.1 = Delivery not authorized, message refused */ (void)option_register(o, "restrictheader", 'r', OPT_SINGLE, NULL, "header restriction", "regex", &stdsyntax, "m/.*/" ); (void)option_register(o, "size", 's', OPT_SINGLE, "8388608", "maximum message size", "bytes", &stdsyntax, "m/.*/" ); //"m/[0-9]+/" ); (void)option_register(o, "testfile", 't', OPT_MULTI, NULL, "testfile for headerrule", "testfile", &stdsyntax, "m/.*/" ); (void)option_register(o, "user", 'u', OPT_SINGLE, NULL, "user", "uid|name", &stdsyntax, "m/.*/" ); (void)option_register(o, "version", 'v', OPT_FLAG, NULL, "print version", NULL, &stdsyntax, NULL ); (void)option_register(o, "newsgroup", NUL, OPT_MULTI, NULL, "article destination", "newsgroup", &stdsyntax, "m/.*/" ); d589 1 a593 2 //printf("DEBUG: option_destroy %.8lx\n", (long)o); @ 1.15 log @added --testfile option for header rewrite testing. Transformation from argz to linked list of elements and back implemented for integration into the gateway's "inner loop". Have trouble with lib_ex segfaulting when throwing exception and tried to track down this issue with no luck. @ text @a115 2 lmtp2nntp_option_rc_t rc = VAL_OK; d123 4 a126 1 return rc; d261 1 a261 1 //printf("DEBUG: enter option_create(%.8lx)\n", (long)op); d263 25 a287 51 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; d294 2 a300 9 #if 0 { int i; for (i=0; i= 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); a318 2 //printf("DEBUG: current popt error is \"%s\"(%d)\n", popt_strerror(i), i); //printf("DEBUG: ----\n"); d325 1 a325 2 if ((largv = (char **)malloc((1 + 1) * sizeof(char **))) == NULL) return OPTION_ERR_MEM; d330 1 a330 3 //printf("DEBUG: popt_getarg returned \"%s\"\n", cp); if ((largv = (char **)realloc(largv, (largc + 2) * sizeof(char **))) == NULL) return OPTION_ERR_MEM; d333 1 a333 3 if ((cpNew = strdup(cp)) == NULL) return OPTION_ERR_MEM; //printf("DEBUG: cpNew = \"%s\"\n", cpNew); a335 5 //printf("DEBUG: largc = \"%d\"\n", largc); #if 0 for (i=0; i 1) option_parse_internal(o, largc, largv); a342 1 //printf("DEBUG: current popt error is \"%s\"(%d)\n", popt_strerror(i), i); d344 1 a344 1 return OPTION_OK; d372 1 a372 1 //printf("DEBUG: \"%s\" does NOT match \"%s\"\n", arg, cbctx); d388 1 a388 1 //printf("DEBUG: \"%s\" does NOT match \"%s\"\n", arg, cbctx); a564 3 lmtp2nntp_option_rc_t rc; //printf("DEBUG: enter option_parse(%.8lx, %d, %.8lx)\n", (long)o, argc, (long)argv); d568 1 a568 1 (void)option_register(o, "childsmax", 'C', OPT_SINGLE, "10", "childs to spawn at max", "childsmax", &stdsyntax, "m/.*/" ); //"m/[0-9]+/" ); d598 1 a598 20 #if 0 { int i; for (i=0; i<29; 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, "vorher" ); rc = option_parse_internal(o, argc, argv); //FIXME should fail for syntax errors and unknown options //val_apply(o->vo, "", 9, dumper, "nachher" ); return rc; @ 1.14 log @new -h option and config @ text @d635 1 @ 1.13 log @Fixed bug in --destionation and main() not initializing data correctly causing segfaults. Deactivated leftover code from the static ns array with nsc counter where memcpy segfaults. Fixed bug in option_register() not strdup()ing the default value causing free() to fail on cleanup. Added '-b -' to test.sh cause defaultng to stdio does not currenly work. Deactivated l2_channel_destroy() because it's cleanup fails and it hangs in a infinite loop in user space. @ text @d619 1 a619 1 (void)option_register(o, "headervalue", 'h', OPT_MULTI, NULL, "header/ value added to message", "header: value", &stdsyntax, "m/.*/" ); @ 1.12 log @"make check" works again! --operationmode now correctly sets OPERATIONMODE_FAKE and detects internal error when this mandatory option was neither given nor preset through option_register(). Found missing functionality where option_parse_internal() does not fail on syntax errors or unknown options. Corrected --timeout* options in "test.sh". @ text @d155 6 a160 3 case OPT_FLAG: oc->data.f = 0; break; case OPT_SINGLE: oc->data.s = def; break; case OPT_MULTI: oc->data.m = NULL; break; d163 4 a166 3 if ( ( oc->longname == NULL) || (descrip != NULL && oc->descrip == NULL) || (argdescrip != NULL && oc->argdescrip == NULL) d673 1 a673 1 if (oc->type == OPT_SINGLE && oc->data.s != NULL) d675 1 @ 1.11 log @--version should print then exit the program. It's use is mutually exclusive and it should be checked very soon in the config process. Fixed a bug in --childsmax where sa_addr_u2a expects a colon. Started to work on testsuite which needs major corrections and exhibits lots of bugs in lmtp2nntp. Found a bug where --l2spec does not work when specified on command line. @ text @d652 1 a652 1 rc = option_parse_internal(o, argc, argv); @ 1.10 log @removed obsolete --veryverbose @ text @a616 1 (void)option_register(o, "size", 's', OPT_SINGLE, "8388608", "maximum message size", "bytes", &stdsyntax, "m/.*/" ); //"m/[0-9]+/" ); d625 1 d629 2 a630 1 (void)option_register(o, "l2spec", 'l', OPT_SINGLE, NULL, "L2 channel tree specification", "l2spec", &stdsyntax, "m/.*/" ); a632 1 (void)option_register(o, "restrictheader", 'r', OPT_SINGLE, NULL, "header restriction", "regex", &stdsyntax, "m/.*/" ); @ 1.9 log @application defaults now set through option_register() @ text @a609 1 (void)option_register(o, "veryverbose", 'V', OPT_FLAG, NULL, "FIXME", NULL, &stdsyntax, NULL ); @ 1.8 log @moved --version option @ text @d129 1 a129 1 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) d154 6 a159 4 oc->data.f = 0; oc->data.s = NULL; /* just in case a pointer is larger than int */ oc->data.m = NULL; oc->ndata = 0; d606 29 a634 29 (void)option_register(o, "childsmax", 'C', OPT_SINGLE, &stdsyntax, "m/[0-9]+/", "foo01", "childsmax" ); (void)option_register(o, "daemonize", 'D', OPT_FLAG, &stdsyntax, NULL, "foo02", NULL ); (void)option_register(o, "kill", 'K', OPT_FLAG, &stdsyntax, NULL, "foo03", NULL ); (void)option_register(o, "pidfile", 'P', OPT_SINGLE, &stdsyntax, "m/.*/", "foo04", "pidfile" ); (void)option_register(o, "veryverbose", 'V', OPT_FLAG, &stdsyntax, NULL, "foo05", NULL ); (void)option_register(o, "acl", 'a', OPT_MULTI, &stdsyntax, "m/.*/", "foo06", "addr[/mask]" ); (void)option_register(o, "bind", 'b', OPT_SINGLE, &stdsyntax, "m/.*/", "foo07", "addr[:port]|-|path[:perms]" ); (void)option_register(o, "client", 'c', OPT_SINGLE, &stdsyntax, "m/.*/", "foo08", "addr[:port]" ); (void)option_register(o, "destination", 'd', OPT_MULTI, &stdsyntax, "m/.*/", "foo09", "addr[:port]" ); (void)option_register(o, "groupmode", 'g', OPT_SINGLE, &stdsyntax, "m/.*/", "foo10", "groupmode" ); (void)option_register(o, "headervalue", 'h', OPT_MULTI, &stdsyntax, "m/.*/", "foo11", "header: value" ); (void)option_register(o, "include", 'i', OPT_MULTI, &includeit, "m/.*/", "foo12", "configfile" ); (void)option_register(o, "size", 's', OPT_SINGLE, &stdsyntax, "m/.*/", "foo13", "bytes" ); (void)option_register(o, "timeoutlmtp", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo14", "sec" ); (void)option_register(o, "timeoutlmtpaccept", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "fo14a", "sec" ); (void)option_register(o, "timeoutlmtpread", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo15", "sec" ); (void)option_register(o, "timeoutlmtpwrite", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo16", "sec" ); (void)option_register(o, "timeoutnntp", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo17", "sec" ); (void)option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "fo17a", "sec" ); (void)option_register(o, "timeoutnntpread", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo18", "sec" ); (void)option_register(o, "timeoutnntpwrite", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo19", "sec" ); (void)option_register(o, "mailfrom", 'm', OPT_SINGLE, &stdsyntax, "m/.*/", "foo20", "regex" ); (void)option_register(o, "nodename", 'n', OPT_SINGLE, &stdsyntax, "m/.*/", "foo21", "nodename" ); (void)option_register(o, "operationmode", 'o', OPT_SINGLE, &stdsyntax, "m/.*/", "foo22", "post|feed" ); (void)option_register(o, "l2spec", 'l', OPT_SINGLE, &stdsyntax, "m/.*/", "L2 channel tree textual specification", "l2spec" ); (void)option_register(o, "user", 'u', OPT_SINGLE, &stdsyntax, "m/.*/", "foo24", "uid|name" ); (void)option_register(o, "version", 'v', OPT_FLAG, &stdsyntax, NULL, "fo24a", NULL ); (void)option_register(o, "restrictheader", 'r', OPT_SINGLE, &stdsyntax, "m/.*/", "foo25", "regex" ); (void)option_register(o, "newsgroup", NUL, OPT_MULTI, &stdsyntax, "m/.*/", "foo26", "newsgroup"); d640 1 a640 1 for (i=0; i<26; i++) { @ 1.7 log @moved --user option @ text @d630 1 @ 1.6 log @moved --timeout_XXX options @ text @d629 1 a629 1 (void)option_register(o, "uid", 'u', OPT_SINGLE, &stdsyntax, "m/.*/", "foo24", "number|name" ); @ 1.5 log @moved --restrictheader option @ text @d617 2 a618 1 (void)option_register(o, "timeoutlmtpaccept", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo14", "sec" ); d621 2 a622 1 (void)option_register(o, "timeoutnntpconnect", NUL, OPT_SINGLE, &stdsyntax, "m/.*/", "foo17", "sec" ); @ 1.4 log @flush. first options moved. introduced exception handling. @ text @d628 1 a628 1 (void)option_register(o, "restrictheader", 'r', OPT_MULTI, &stdsyntax, "m/.*/", "foo25", "regex" ); @ 1.3 log @Switch from local copy of POPT to our new linked-in child OSSP popt. @ text @d76 1 a76 6 static void die(char *msg) { printf("ERROR: %s\n", msg); exit(-1); } a95 1 #if 0 a103 1 #endif d112 2 a113 1 //lmtp2nntp_option_rc_t option_find(lmtp2nntp_option_t *o, int number, optionval_t **ocp); d463 1 a463 1 char *cpBuf = NULL; d477 2 a478 1 int fd; d480 14 a493 7 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"); d509 2 a510 2 cpI = cpBuf; cpO = cpBuf; d626 1 a626 1 (void)option_register(o, "l2spec", 'l', OPT_SINGLE, &stdsyntax, "m/.*/", "foo23", "spec" ); @ 1.2 log @option works and data can be read by config @ text @a32 1 #include "lmtp2nntp_popt.h" d35 3 a37 2 #include #include @ 1.1 log @moved config to option, created a new config @ text @a81 24 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; }; d84 1 a84 1 optionconfig_t *oc; d90 1 a90 1 oc = (optionconfig_t *)data; d119 2 a120 2 //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) d138 1 a138 1 optionconfig_t *oc; d145 2 a146 2 /* create a optionconfig_t structure */ if ((oc = (optionconfig_t *)malloc(sizeof(optionconfig_t))) == NULL) d148 1 a148 1 //printf("DEBUG: optionconfig_t structure malloc'ed\n"); d170 1 a170 1 //printf("DEBUG: optionconfig_t structure created\n"); d173 1 a173 1 if (val_reg(oc->val, oc->longname, VAL_TYPE_PTR, oc->descrip, oc) != VAL_OK) d175 3 d179 11 a189 1 //printf("DEBUG: val_reg'ed\n"); d235 1 a235 1 /* link in this new optionconfig_t structure */ d321 1 a321 1 optionconfig_t *ocp; d386 1 a386 1 static lmtp2nntp_option_rc_t stdsyntax(optionconfig_t *oc, char *arg, char *cbctx) d388 1 a388 1 printf("DEBUG: enter stdsyntax %.8lx, \"%s\", \"%s\"\n", (long)oc, arg, cbctx); d466 1 a466 1 static lmtp2nntp_option_rc_t includeit(optionconfig_t *oc, char *arg, char *cbctx) d602 26 a627 26 (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"); d645 1 a645 1 //val_apply(o->vo, "", 9, dumper, "all" ); d647 1 a647 1 val_apply(o->vo, "", 9, dumper, "all" ); d653 1 a653 1 optionconfig_t *oc; @