Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postfix/src/util/   (Postfix Mailserver Version 3.11©)  Datei vom 11.9.2024 mit Größe 7 kB image not shown  

Quelle  dict_stream.c

  Sprache: C
 

/*++
/* NAME
/* dict_stream 3
/* SUMMARY
/*
/* SYNOPSIS
/* #include <dict.h>
/*
/* VSTREAM *dict_stream_open(
/* const char *dict_type,
/* const char *mapname,
/* int open_flags,
/* int dict_flags,
/* struct stat * st,
/* VSTRING **why)
/* DESCRIPTION
/* dict_stream_open() opens a dictionary, which can be specified
/* as a file name, or as inline text enclosed with {}. If successful,
/* dict_stream_open() returns a non-null VSTREAM pointer. Otherwise,
/* it returns an error text through the why argument, allocating
/* storage for the error text if the why argument points to a
/* null pointer.
/*
/* When the dictionary file is specified inline, dict_stream_open()
/* removes the outer {} from the mapname value, and removes leading
/* or trailing comma or whitespace from the result. It then expects
/* to find zero or more rules enclosed in {}, separated by comma
/* and/or whitespace. dict_stream() writes each rule as one text
/* line to an in-memory stream, without its enclosing {} and without
/* leading or trailing whitespace. The result value is a VSTREAM
/* pointer for the in-memory stream that can be read as a regular
/* file.
/* .sp
/* inline-file = "{" 0*(0*wsp-comma rule-spec) 0*wsp-comma "}"
/* .sp
/* rule-spec = "{" 0*wsp rule-text 0*wsp "}"
/* .sp
/* rule-text = any text containing zero or more balanced {}
/* .sp
/* wsp-comma = wsp | ","
/* .sp
/* wsp = whitespace
/*
/* Arguments:
/* .IP dict_type
/* .IP open_flags
/* .IP dict_flags
/* The same as with dict_open(3).
/* .IP mapname
/* Pathname of a file with dictionary content, or inline dictionary
/* content as specified above.
/* .IP st
/* File metadata with the file owner, or fake metadata with the
/* real UID and GID of the dict_stream_open() caller. This is
/* used for "taint" tracking (zero=trusted, non-zero=untrusted).
/* IP why
/* Pointer to pointer to error message storage. dict_stream_open()
/* updates this storage when reporting an error, and allocates
/* memory if why points to a null pointer.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/


 /*
  * System library.
  */

#include <sys_defs.h>

 /*
  * Utility library.
  */

#include <dict.h>
#include <msg.h>
#include <mymalloc.h>
#include <stringops.h>
#include <vstring.h>

#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)

/* dict_inline_to_multiline - convert inline map spec to multiline text */

static char *dict_inline_to_multiline(VSTRING *vp, const char *mapname)
{
    char   *saved_name = mystrdup(mapname);
    char   *bp = saved_name;
    char   *cp;
    char   *err = 0;

    VSTRING_RESET(vp);
    /* Strip the {} from the map "name". */
    err = extpar(&bp, CHARS_BRACE, EXTPAR_FLAG_NONE);
    /* Extract zero or more rules inside {}. */
    while (err == 0 && (cp = mystrtokq(&bp, CHARS_COMMA_SP, CHARS_BRACE)) != 0)
 if ((err = extpar(&cp, CHARS_BRACE, EXTPAR_FLAG_STRIP)) == 0)
     /* Write rule to in-memory file. */
     vstring_sprintf_append(vp, "%s\n", cp);
    VSTRING_TERMINATE(vp);
    myfree(saved_name);
    return (err);
}

/* dict_stream_open - open inline configuration or configuration file */

VSTREAM *dict_stream_open(const char *dict_type, const char *mapname,
             int open_flags, int dict_flags,
             struct stat * st, VSTRING **why)
{
    VSTRING *inline_buf = 0;
    VSTREAM *map_fp;
    char   *err = 0;

#define RETURN_0_WITH_REASON(...) do { \
 if (*why == 0) \
     *why = vstring_alloc(100); \
 vstring_sprintf(*why, __VA_ARGS__); \
 if (inline_buf != 0) \
    vstring_free(inline_buf); \
 if (err != 0) \
     myfree(err); \
 return (0); \
    } while (0)

    if (mapname[0] == CHARS_BRACE[0]) {
 inline_buf = vstring_alloc(100);
 if ((err = dict_inline_to_multiline(inline_buf, mapname)) != 0)
     RETURN_0_WITH_REASON("%s map: %s", dict_type, err);
 map_fp = vstream_memopen(inline_buf, O_RDONLY);
 vstream_control(map_fp, VSTREAM_CTL_OWN_VSTRING, VSTREAM_CTL_END);
 st->st_uid = getuid();   /* geteuid()? */
 st->st_gid = getgid();   /* getegid()? */
 return (map_fp);
    } else {
 if ((map_fp = vstream_fopen(mapname, open_flags, 0)) == 0)
     RETURN_0_WITH_REASON("open %s: %m", mapname);
 if (fstat(vstream_fileno(map_fp), st) < 0)
     msg_fatal("fstat %s: %m", mapname);
 return (map_fp);
    }
}

#ifdef TEST

#include <string.h>

int     main(int argc, char **argv)
{
    struct testcase {
 const char *title;
 const char *mapname;  /* starts with brace */
 const char *expect_err;  /* null or message */
 const char *expect_cont; /* null or content */
    };

#define EXP_NOERR 0
#define EXP_NOCONT 0

#define STRING_OR(s, text_if_null) ((s) ? (s) : (text_if_null))
#define DICT_TYPE_TEST "test"

    const char rule_spec_error[] = DICT_TYPE_TEST " map: "
    "syntax error after '}' in \"{blah blah}x\"";
    const char inline_config_error[] = DICT_TYPE_TEST " map: "
    "syntax error after '}' in \"{{foo bar}, {blah blah}}x\"";
    struct testcase testcases[] = {
 {"normal",
     "{{foo bar}, {blah blah}}", EXP_NOERR, "foo bar\nblah blah\n"
 },
 {"trims leading/trailing wsp around rule-text",
     "{{ foo bar }, { blah blah }}", EXP_NOERR, "foo bar\nblah blah\n"
 },
 {"trims leading/trailing comma-wsp around rule-spec",
     "{, ,{foo bar}, {blah blah}, ,}", EXP_NOERR, "foo bar\nblah blah\n"
 },
 {"empty inline-file",
     "{, }", EXP_NOERR, ""
 },
 {"propagates extpar error for inline-file",
     "{{foo bar}, {blah blah}}x", inline_config_error, EXP_NOCONT
 },
 {"propagates extpar error for rule-spec",
     "{{foo bar}, {blah blah}x}", rule_spec_error, EXP_NOCONT
 },
 0,
    };
    struct testcase *tp;
    VSTRING *act_err = 0;
    VSTRING *act_cont = vstring_alloc(100);
    VSTREAM *fp;
    struct stat st;
    ssize_t exp_len;
    ssize_t act_len;
    int     pass;
    int     fail;

    for (pass = fail = 0, tp = testcases; tp->title; tp++) {
 int     test_passed = 0;

 msg_info("RUN test case %ld %s", (long) (tp - testcases), tp->title);

#if 0
 msg_info("title=%s", tp->title);
 msg_info("mapname=%s", tp->mapname);
 msg_info("expect_err=%s", STRING_OR_NULL(tp->expect_err));
 msg_info("expect_cont=%s", STRINGOR_NULL(tp->expect_cont));
#endif

 if (act_err)
     VSTRING_RESET(act_err);
 fp = dict_stream_open(DICT_TYPE_TEST, tp->mapname, O_RDONLY,
         0, &st, &act_err);
 if (fp) {
     if (tp->expect_err) {
  msg_warn("test case %s: got stream, expected error", tp->title);
     } else if (!tp->expect_err && act_err && LEN(act_err) > 0) {
  msg_warn("test case %s: got error '%s', expected noerror",
    tp->title, STR(act_err));
     } else if (!tp->expect_cont) {
  msg_warn("test case %s: got stream, expected nostream",
    tp->title);
     } else {
  exp_len = strlen(tp->expect_cont);
  if ((act_len = vstream_fread_buf(fp, act_cont, 2 * exp_len)) < 0) {
      msg_warn("test case %s: content read error", tp->title);
  } else {
      VSTRING_TERMINATE(act_cont);
      if (strcmp(tp->expect_cont, STR(act_cont)) != 0) {
   msg_warn("test case %s: got content '%s', expected '%s'",
     tp->title, STR(act_cont), tp->expect_cont);
      } else {
   test_passed = 1;
      }
  }
     }
 } else {
     if (!tp->expect_err) {
  msg_warn("test case %s: got nostream, expected noerror",
    tp->title);
     } else if (tp->expect_cont) {
  msg_warn("test case %s: got nostream, expected stream",
    tp->title);
     } else if (strcmp(STR(act_err), tp->expect_err) != 0) {
  msg_warn("test case %s: got error '%s', expected '%s'",
    tp->title, STR(act_err), tp->expect_err);
     } else {
  test_passed = 1;
     }

 }
 if (test_passed) {
     msg_info("PASS test %ld", (long) (tp - testcases));
     pass++;
 } else {
     msg_info("FAIL test %ld", (long) (tp - testcases));
     fail++;
 }
 if (fp)
     vstream_fclose(fp);
    }
    if (act_err)
 vstring_free(act_err);
    vstring_free(act_cont);
    msg_info("PASS=%d FAIL=%d", pass, fail);
    return (fail > 0);
}

#endif     /* TEST */

Messung V0.5 in Prozent
C=76 H=91 G=83

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-08-09) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.