Index: ossp-pkg/lmtp2nntp/lmtp2nntp_option.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.c,v rcsdiff -q -kk '-r1.16' '-r1.17' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.c,v' 2>/dev/null --- lmtp2nntp_option.c 2002/03/06 14:25:39 1.16 +++ lmtp2nntp_option.c 2002/03/07 16:03:56 1.17 @@ -127,142 +127,127 @@ } -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) +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) { - lmtp2nntp_option_rc_t rc = VAL_OK; - optionval_t *oc; + volatile struct { + optionval_t *oc; + } v; + ex_t ex; - //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 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; + v.oc = NULL; + try { + if (o == NULL || longname == NULL) + throw(option_register, o, OPTION_ERR_ARG); - 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; + /* 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 { - //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; + o->last->next = v.oc; + o->last = v.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); + catch(ex) { + if (v.oc != NULL) { + if (type == OPT_SINGLE && v.oc->data.s != NULL) + free(v.oc->data.s); + 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 rc; + 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) - throw(option_create, NULL, OPTION_ERR_ARG); + if (op == NULL || parent == NULL) + return OPTION_ERR_ARG; (*op = (lmtp2nntp_option_t *)mallocex(sizeof(lmtp2nntp_option_t))); (*op)->first = NULL; @@ -273,10 +258,10 @@ (*op)->pt = NULL; if (val_create(&((*op)->vo)) != VAL_OK) - throw(option_create, NULL, OPTION_ERR_VAL); + return OPTION_ERR_VAL; if (val_reg(parent, "option", VAL_TYPE_VAL, "option", (void *)&((*op)->vo)) != VAL_OK) - throw(option_create, NULL, OPTION_ERR_VAL); + return OPTION_ERR_VAL; } catch(ex) { if (*op != NULL) { @@ -284,7 +269,9 @@ val_unreg(parent, "option"); free(*op); } - rethrow; + if (ex.ex_class == (void *)option_create) + return (lmtp2nntp_option_rc_t)ex.ex_value; + return OPTION_ERR_TRY; } return OPTION_OK; } @@ -296,14 +283,20 @@ int i; char *cp; optionval_t *ocp; - popt_context poptCon; /* context for parsing command-line options */ + 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); - exit(1); //FIXME + 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)); @@ -317,27 +310,41 @@ } } + /* create a "--newsgroup" argc/argv for every leftover argument */ { - 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; + ex_t ex; + volatile struct { + char **largv; + } v; + + try { + int largc; + char *cpNew; + + v.largv = (char **)mallocex((1 + 1) * sizeof(char **)); + largc = 0; + v.largv[largc++] = "leftover"; + v.largv[largc] = NULL; + while ((cp = (char *)popt_getarg(poptCon)) != NULL) { + v.largv = (char **)reallocex(v.largv, (largc + 2) * sizeof(char **)); + v.largv[largc++] = "--newsgroup"; + v.largv[largc] = NULL; + cpNew = strdupex(cp); + v.largv[largc++] = cpNew; + v.largv[largc] = NULL; + } + if (largc > 1) { + rv = option_parse_internal(o, largc, v.largv); + if (rc == OPTION_OK) + rc = rv; + } } - if (largc > 1) { - rv = option_parse_internal(o, largc, largv); - if (rc == OPTION_OK) - rc = rv; + cleanup { + if (v.largv != NULL) + free(v.largv); + } + catch(ex) { + rethrow; } } popt_freecontext(poptCon); @@ -346,12 +353,8 @@ static lmtp2nntp_option_rc_t stdsyntax(optionval_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) @@ -360,25 +363,22 @@ 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; - */ + /* add this if repeated overwriting definitions of single values are not allowed + * if (oc->ndata >= 1 || oc->data.s != 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; } - //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) @@ -388,34 +388,13 @@ fprintf(stderr, "ERROR: argument \"%s\" does NOT match syntax \"%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; + 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; -#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; @@ -431,13 +410,10 @@ 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; @@ -445,21 +421,24 @@ ex_t ex; try { - 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"); + 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) { - fprintf(stderr, "ERROR: caught %s\n", ex.ex_value == NULL ? "N/A" : (char *)ex.ex_value); + if (cpBuf != NULL) + free((char *)cpBuf); rethrow; } } - //printf("DEBUG: *** 2 *** file as it was just read in ***\n%s***\n", cpBuf); { char *cpI; /* pointer to next character to be read */ @@ -560,51 +539,59 @@ return option_parse_internal(o, argc, argv); } +/* 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) { - if (o == NULL) - return OPTION_ERR_ARG; + ex_t ex; - (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/.*/" ); + if (o == NULL || argc < 0 || argv == NULL) + return OPTION_ERR_ARG; + try { + 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/.*/" ); + } + catch(ex) { + if (ex.ex_class == 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; int i; - //printf("DEBUG: option_destroy %.8lx\n", (long)o); - if (o == NULL) return OPTION_ERR_ARG; Index: ossp-pkg/lmtp2nntp/lmtp2nntp_option.h RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.h,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_option.h,v' 2>/dev/null --- lmtp2nntp_option.h 2002/03/06 14:25:39 1.6 +++ lmtp2nntp_option.h 2002/03/07 16:03:56 1.7 @@ -52,6 +52,7 @@ typedef enum { OPTION_OK, OPTION_ERR_ARG, /* invalid args passed into function */ + OPTION_ERR_TRY, /* caught an exception from a underlying codeblock */ OPTION_ERR_USE, /* invalid usage, bad data passed into function */ OPTION_ERR_MEM, /* out of memory */ OPTION_ERR_VAL, /* libval failed */ @@ -82,9 +83,9 @@ int ndata; }; -lmtp2nntp_option_rc_t option_create (lmtp2nntp_option_t **, val_t *); -lmtp2nntp_option_rc_t option_register(lmtp2nntp_option_t *, char *, char, optiontype_t, char *, char *, char *, optionloop_cb_t *, char *); -lmtp2nntp_option_rc_t option_parse (lmtp2nntp_option_t *, int, char **); -lmtp2nntp_option_rc_t option_destroy (lmtp2nntp_option_t *); +/* these public functions catch all underlying exceptions and properly return a code */ +lmtp2nntp_option_rc_t option_create (lmtp2nntp_option_t **, val_t *); +lmtp2nntp_option_rc_t option_parse (lmtp2nntp_option_t *, int, char **); +lmtp2nntp_option_rc_t option_destroy(lmtp2nntp_option_t *); #endif /* __LMTP2NNTP_OPTION_H__ */