OSSP CVS Repository

ossp - ossp-pkg/lmtp2nntp/lmtp2nntp_config.c 1.8
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/lmtp2nntp/lmtp2nntp_config.c 1.8
/*
**  Copyright (c) 2001-2002 The OSSP Project <http://www.ossp.org/>
**  Copyright (c) 2001-2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
**
**  This file is part of OSSP lmtp2nntp, an LMTP speaking local
**  mailer which forwards mails as Usenet news articles via NNTP.
**  It can be found at http://www.ossp.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 <ossp@ossp.org>.
**
**  lmtp2nntp.c: LMTP to NNTP configuration parsing
*/

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
// #include <unistd.h>
// #include <errno.h>
// #include <string.h>
// #include <fcntl.h>
// #include <sys/utsname.h>
// #include <sys/time.h>
// #include <sys/types.h>
// #include <sys/wait.h>
// #include <sys/stat.h>
// #include <signal.h>
// #include <pwd.h>

/* third party (included) */
// #include "lmtp2nntp_argz.h"
// #include "lmtp2nntp_shpat.h"
// #include "lmtp2nntp_daemon.h"
#include "lmtp2nntp_popt.h"
#include "val.h"

/* third party (linked in) */
#include "str.h"
// #include "l2.h"
// #include "var.h"

/* library version check (compile-time) */
#define  L2_VERSION_HEX_REQ 0x001200
#define  L2_VERSION_STR_REQ "0.1.0"
#define STR_VERSION_HEX_REQ 0x009206
#define STR_VERSION_STR_REQ "0.9.6"
#ifdef L2_VERSION_HEX
#if L2_VERSION_HEX < L2_VERSION_HEX_REQ
#error "require a newer version of OSSP L2"
#endif
#endif
#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_config.h"
#include "lmtp2nntp_lmtp.h"
#include "lmtp2nntp_nntp.h"
#include "lmtp2nntp_msg.h"
#include "sa.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

void die(char *); //FIXME
void die(char *msg)
{
        printf("ERROR: %s\n", msg);
            exit(-1);
}

static val_rc_t dumper(void *ctx, const char *name, int type, const char *desc, void *data)
{
    switch (type) {
        case VAL_TYPE_VAL:
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_VAL,    desc=<%20s>, data@%.8lx INTERNAL\n",
                    (char *)ctx, name,      desc, (long)data);
            break;
        case VAL_TYPE_PTR:
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_PTR,    desc=<%20s>, data@%.8lx=%.8lx\n",
                    (char *)ctx, name,      desc, (long)data, *(long *)data);
            break;
        case VAL_TYPE_CHAR:                                                                              
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_CHAR,   desc=<%20s>, data@%.8lx='%c'\n",
                    (char *)ctx, name,      desc, (long)data, *(char *)data);
            break;
        case VAL_TYPE_SHORT:                                                                             
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_SHORT,  desc=<%20s>, data@%.8lx=%8d\n",
                    (char *)ctx, name,      desc, (long)data, *(short *)data);
            break;
        case VAL_TYPE_INT:                                                                               
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_INT,    desc=<%20s>, data@%.8lx=%8d\n",
                    (char *)ctx, name,      desc, (long)data, *(int *)data);
            break;
        case VAL_TYPE_LONG:                                                                              
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_LONG,   desc=<%20s>, data@%.8lx=%8ld\n",
                    (char *)ctx, name,      desc, (long)data, *(long *)data);
            break;
        case VAL_TYPE_FLOAT:                                                                             
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_FLOAT,  desc=<%20s>, data@%.8lx=%8f\n",
                    (char *)ctx, name,      desc, (long)data, *(float *)data);
            break;
        case VAL_TYPE_DOUBLE:                                                                            
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, VAL_TYPE_DOUBLE, desc=<%20s>, data@%.8lx=%8f\n",
                    (char *)ctx, name,      desc, (long)data, *(double *)data);
            break;
        default: 
            fprintf(stderr, "DEBUG: <%10s>, name=<%10s>, type = %.8lx,    desc=<%20s>, data@%.8lx\n",
                    (char *)ctx, name, (long)type, desc, (long)data);
    }

    return VAL_OK;
}

void dotconftest(int argc, char **argv) /*FIXME*/
{
    popt_context poptCon;   /* context for parsing command-line options */
    lmtp2nntp_config_t *ctx;
    char *cpBuf;
    struct popt_option poptTable[] = {
        { "childsmax",      'C', POPT_ARG_STRING, NULL, 'C', "foo", "childsmax" },
        { "daemonize",      'D', POPT_ARG_NONE,   NULL, 'D', "foo", NULL },
        { "kill",           'K', POPT_ARG_NONE,   NULL, 'K', "foo", NULL },
        { "pidfile",        'P', POPT_ARG_STRING, NULL, 'P', "foo", "pidfile" },
        { "veryverbose",    'V', POPT_ARG_NONE,   NULL, 'V', "foo", NULL },
        { "acl",            'a', POPT_ARG_STRING, NULL, 'a', "foo", "addr[/mask]" },
        { "bind",           'b', POPT_ARG_STRING, NULL, 'b', "foo", "addr[:port]|-|path[:perms]" },
        { "client",         'c', POPT_ARG_STRING, NULL, 'c', "foo", "addr[:port]" },
        { "destination",    'd', POPT_ARG_STRING, NULL, 'd', "foo", "addr[:port]" },
        { "groupmode",      'g', POPT_ARG_STRING, NULL, 'g', "foo", "groupmode" },
        { "headervalue",    'h', POPT_ARG_STRING, NULL, 'h', "foo", "header: value" },
        { "include",        'i', POPT_ARG_STRING, NULL, 'i', "foo", "configfile" },
        { "size",           's', POPT_ARG_STRING, NULL, 's', "foo", "bytes" },
        { "timeout",        't', POPT_ARG_STRING, NULL, 't', "foo", "name=sec" },
        { "mailfrom",       'm', POPT_ARG_STRING, NULL, 'm', "foo", "regex" },
        { "nodename",       'n', POPT_ARG_STRING, NULL, 'n', "foo", "nodename" },
        { "operationmode",  'o', POPT_ARG_STRING, NULL, 'o', "foo", "post|feed" },
        { "l2spec",         'l', POPT_ARG_STRING, NULL, 'l', "foo", "spec" },
        { "uid",            'u', POPT_ARG_STRING, NULL, 'u', "foo", "number|name" },
        { "restrictheader", 'r', POPT_ARG_STRING, NULL, 'r', "foo", "regex" },
        { "newsgroup",      NUL, POPT_ARG_STRING
                        |POPT_ARGFLAG_DOC_HIDDEN, NULL, 1,   NULL,  NULL },
        POPT_AUTOHELP
        { NULL,               0, 0,               NULL, 0 }
    };
 
    ctx = malloc(sizeof(lmtp2nntp_config_t));
    ctx->option_childsmax = 10;

    {
        int testint = 10;
        int testintout = 100;
        int testint2 = 20;
        int testintout2 = 200;
        val_rc_t rc;
        val_t *v, *v2, *v3;

        if ((rc = val_create(&v)) != VAL_OK)
            die("val_create");

        printf("DEBUG: testint = %d, testintout = %d\n", testint, testintout);

        if ((rc = val_reg(v, "foo", VAL_TYPE_INT, "foo variable", (void *)&testint)) != VAL_OK)
            die("val_reg");

        testint++;
        if ((rc = val_get(v, "foo", &testintout)) != VAL_OK)
            die("val_get");
        printf("DEBUG: testint = %d, testintout = %d\n", testint, testintout);

        if ((rc = val_set(v, "foo", 2)) != VAL_OK)
            die("val_set");
        if ((rc = val_get(v, "foo", &testintout)) != VAL_OK)
            die("val_get");
        printf("DEBUG: testint = %d, testintout = %d\n", testint, testintout);

        if ((rc = val_create(&v2)) != VAL_OK)
            die("val_create 2");

#if 0
        if ((rc = val_reg(v, "bar", VAL_TYPE_VAL, "bar variable", (void *)&v2)) != VAL_OK)
            die("val_reg 2");
#endif
        val_reg(v, "bar", VAL_TYPE_VAL, "bar variable", NULL);
        val_set(v, "bar", v2);
        if ((rc = val_get(v, "bar", &v3)) != VAL_OK)
            die("val_get v3");

        if ((rc = val_reg(v2, "quux", VAL_TYPE_INT, "quux variable", (void *)&testint2)) != VAL_OK)
            die("val_reg 2b");

        testint2++;
        if ((rc = val_get(v2, "quux", &testintout2)) != VAL_OK)
            die("val_get 2c");
        printf("DEBUG: testint2 = %d, testintout2 = %d\n", testint2, testintout2);
        if ((rc = val_get(v, "bar.quux", &testintout2)) != VAL_OK) {
            fprintf(stderr, "rc=%d\n", rc);
            die("val_get 2d");
        }
        printf("DEBUG: testint2 = %d, testintout2 = %d\n", testint2, testintout2);

        printf("DEBUG: testint     at address %lx\n", (long)&testint);
        printf("DEBUG: testintout  at address %lx\n", (long)&testintout);
        printf("DEBUG: testint2    at address %lx\n", (long)&testint2);
        printf("DEBUG: testint2out at address %lx\n", (long)&testintout2);

        if ((rc = val_reg(v, "bar.ptr", VAL_TYPE_PTR, "bar ptr (&testint)", NULL)) != VAL_OK)
            die("val_ret  for bar.ptr using inline data");
        if ((rc = val_set(v, "bar.ptr", &testint)) != VAL_OK)
            die("val_set  for bar.ptr using inline data");
        if ((rc = val_reg(v, "bar.char", VAL_TYPE_CHAR, "bar character (!)", NULL)) != VAL_OK)
            die("val_ret  for bar.char using inline data");
        if ((rc = val_set(v, "bar.char", '!')) != VAL_OK)
            die("val_set  for bar.char using inline data");
        if ((rc = val_reg(v, "bar.short", VAL_TYPE_SHORT, "bar short (555)", NULL)) != VAL_OK)
            die("val_ret  for bar.short using inline data");
        if ((rc = val_set(v, "bar.short", 555)) != VAL_OK)
            die("val_set  for bar.short using inline data");
        if ((rc = val_reg(v, "bar.int", VAL_TYPE_INT, "bar integer (76543)", NULL)) != VAL_OK)
            die("val_ret  for bar.int using inline data");
        if ((rc = val_set(v, "bar.int", 76543)) != VAL_OK)
            die("val_set  for bar.int using inline data");
        if ((rc = val_reg(v, "bar.long", VAL_TYPE_LONG, "bar long (2097152)", NULL)) != VAL_OK)
            die("val_ret  for bar.long using inline data");
        if ((rc = val_set(v, "bar.long", 2097152)) != VAL_OK)
            die("val_set  for bar.long using inline data");
        if ((rc = val_reg(v, "bar.float", VAL_TYPE_FLOAT, "bar float (1.955830)", NULL)) != VAL_OK)
            die("val_ret  for bar.float using inline data");
        if ((rc = val_set(v, "bar.float", 1.95583)) != VAL_OK)
            die("val_set  for bar.float using inline data");
        if ((rc = val_reg(v, "bar.double", VAL_TYPE_DOUBLE, "bar double (3.1415+)", NULL)) != VAL_OK)
            die("val_ret  for bar.double using inline data");
        if ((rc = val_set(v, "bar.double", 3.14159265358979)) != VAL_OK)
            die("val_set  for bar.double using inline data");

        // OK val_apply(v,  "", 9, dumper, "v" );
        // OK val_apply(v2, "", 9, dumper, "v2");
        // OK val_apply(v,  "", 0, dumper, "v" );
        // OK val_apply(v,  "bar", 1, dumper, "v" );
        // OK val_apply(v2,  "", 0, dumper, "v" );
        // OK val_apply(v,  "", 1, dumper, "v" );
        // OK val_apply(v,  "foo", 0, dumper, "v" );
        // OK val_apply(v2,  "char", 2, dumper, "v" );
        // OK val_apply(v,  "bar.char", 2, dumper, "v" );

        if ((rc = val_destroy(v2)) != VAL_OK)
            die("val_destroy 2");

        if ((rc = val_destroy(v)) != VAL_OK)
            die("val_destroy");

        return;
    }

    {
        char c;
        char *cp;

        poptCon = popt_getcontext(NULL, argc, (const char **)argv, poptTable, 0);
        popt_setotheroptionhelp(poptCon, "[OPTIONS]* [newsgroup ...]");
        printf("DEBUG: argc=%d\n", argc);
        if (argc < 2) {
            popt_printusage(poptCon, stderr, 0);
            exit(1);
        }
        while ((c = popt_getnextopt(poptCon)) >= 0) {
            printf("DEBUG: popt_getnextopt returned %d='%c'\n", (int)c, c);
        }
        while ((cp = popt_getarg(poptCon)) != NULL) {
            printf("DEBUG: popt_getarg returned \"%s\"\n", cp);
        }

        printf("DEBUG: popt_getnextopt ended with \"%s\"(%d)\n", popt_strerror((int)c), (int)c);
        popt_freecontext(poptCon);
        return;
    }

/* Braindump

    fuer configure

ich brauche eine Tabelle, die alle optionen in langer und kurzer Form
enthaelt, Angabe ob flag, single- oder multivalue, callbacks fuer die
syntaxpruefung des human-readable inputs, die conversion ins interne binaryformat sowie rueckwandlung in
human-readable format. Dazu informationen fuer help.
 */

/* Braindump

    fuer var

ich brauche eine struktur, aus der man ersehen kann, welche variablen es gibt. 
    {
        struct "system.uname.sysname",  varstring, 
        struct "system.uname.nodename", 
        struct "system.uname.release", 
        struct "system.uname.version", 
        struct "system.uname.machine", 
        
        <<< ctx->progname = strdup(argv[0]);
        <<< foo = ctx->progname;

        >>> rc = varreg("main.progname", &ctx->progname);
        >>> rc = varset("main.progname", strdup(argv[0])); //equivalent to ctx->progname = strdup(argv[0]);
        >>> rc = varget("main.progname", &foo);            //equivalent to foo = ctx->progname
    }
 */

    {
        const char *filename = "example.conf";
        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");
    }
    //FIXME printf("DEBUG: *** 1 *** 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 *command;
                            char *value;

                            if ((command = str_token(&cp, " \t", "\"'", "#", STR_STRIPQUOTES|STR_BACKSLASHESC)) == NULL)
                                ;//printf("DEBUG: no command - comment only\n");
                            else {
                                printf("DEBUG:   command = ***%s***\n", command);
                                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);
                                }
                            }
                        }
                    }
                    cpL = cpO;
                    lline = pline;
                    eline = TRUE;
                }
            }
            p = c;
        }
    }
}


CVSTrac 2.0.1