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

Quelle  config_known_tcp_ports.c

  Sprache: C
 

/*++
/* NAME
/* config_known_tcp_ports 3
/* SUMMARY
/* parse and store known TCP port configuration
/* SYNOPSIS
/* #include <config_known_tcp_ports.h>
/*
/* void config_known_tcp_ports(
/* const char *source,
/* const char *settings);
/* DESCRIPTION
/* config_known_tcp_ports() parses the known TCP port information
/* in the settings argument, and reports any warnings to the standard
/* error stream. The source argument is used to provide warning
/* context. It typically is a configuration parameter name.
/* EXPECTED SYNTAX (ABNF)
/* configuration = empty | name-to-port *("," name-to-port)
/* name-to-port = 1*(name "=") port
/* EXAMPLES
/* In the example below, the whitespace is optional.
/* smtp = 25, smtps = submissions = 465, submission = 587
/* 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 <argv.h>
#include <known_tcp_ports.h>
#include <msg.h>
#include <mymalloc.h>
#include <stringops.h>

 /*
  * Application-specific.
  */

#include <config_known_tcp_ports.h>

/* config_known_tcp_ports - parse configuration and store associations */

void    config_known_tcp_ports(const char *source, const char *settings)
{
    ARGV   *associations;
    ARGV   *association;
    char  **cpp;

    clear_known_tcp_ports();

    /*
     * The settings is in the form of associations separated by comma. Split
     * it into separate associations.
     */

    associations = argv_split(settings, ",");
    if (associations->argc == 0) {
 argv_free(associations);
 return;
    }

    /*
     * Each association is in the form of "1*(name =) port". We use
     * argv_split() to carve this up, then we use mystrtok() to validate the
     * individual fragments. But first we prepend and append space so that we
     * get sensible results when an association starts or ends in "=".
     */

    for (cpp = associations->argv; *cpp != 0; cpp++) {
 char   *temp = concatenate(" ", *cpp, " ", (char *) 0);

 association = argv_split_at(temp, '=');
 myfree(temp);

 if (association->argc == 0) {
      /* empty, ignore */ ;
 } else if (association->argc == 1) {
     msg_warn("%s: in \"%s\" is not in \"name = value\" form",
       source, *cpp);
 } else {
     char   *bp;
     char   *lhs;
     char   *rhs;
     const char *err = 0;
     int     n;

     bp = association->argv[association->argc - 1];
     if ((rhs = mystrtok(&bp, CHARS_SPACE)) == 0) {
  err = "missing port value after \"=\"";
     } else if (mystrtok(&bp, CHARS_SPACE) != 0) {
  err = "whitespace in port number";
     } else {
  for (n = 0; n < association->argc - 1; n++) {
      const char *new_err;

      bp = association->argv[n];
      if ((lhs = mystrtok(&bp, CHARS_SPACE)) == 0) {
   new_err = "missing service name before \"=\"";
      } else if (mystrtok(&bp, CHARS_SPACE) != 0) {
   new_err = "whitespace in service name";
      } else {
   new_err = add_known_tcp_port(lhs, rhs);
      }
      if (new_err != 0 && err == 0)
   err = new_err;
  }
     }
     if (err != 0) {
  msg_warn("%s: in \"%s\": %s", source, *cpp, err);
     }
 }
 argv_free(association);
    }
    argv_free(associations);
}

#ifdef TEST

#include <stdlib.h>
#include <string.h>
#include <msg_vstream.h>

#define STR(x) vstring_str(x)

 /* TODO(wietse) make this a proper VSTREAM interface */

/* vstream_swap - kludge to capture output for testing */

static void vstream_swap(VSTREAM *one, VSTREAM *two)
{
    VSTREAM save;

    save = *one;
    *one = *two;
    *two = save;
}

struct test_case {
    const char *label;   /* identifies test case */
    const char *config;   /* configuration under test */
    const char *exp_warning;  /* expected warning or null */
    const char *exp_export;  /* expected export or null */
};

static struct test_case test_cases[] = {
    {"good",
  /* config */ "smtp = 25, smtps = submissions = 465, lmtp = 24",
  /* warning */ "",
  /* export */ "lmtp=24 smtp=25 smtps=465 submissions=465"
    },
    {"equal-equal",
  /* config */ "smtp = 25, smtps == submissions = 465, lmtp = 24",
  /* warning */ "config_known_tcp_ports: warning: equal-equal: "
 "in \" smtps == submissions = 465\": missing service name before "
 "\"=\"\n",
  /* export */ "lmtp=24 smtp=25 smtps=465 submissions=465"
    },
    {"port test 1",
  /* config */ "smtps = submission =",
  /* warning */ "config_known_tcp_ports: warning: port test 1: "
 "in \"smtps = submission =\": missing port value after \"=\"\n",
  /* export */ ""
    },
    {"port test 2",
  /* config */ "smtps = submission = 4 65",
  /* warning */ "config_known_tcp_ports: warning: port test 2: "
 "in \"smtps = submission = 4 65\": whitespace in port number\n",
  /* export */ ""
    },
    {"port test 3",
  /* config */ "lmtp = 24, smtps = submission = foo",
  /* warning */ "config_known_tcp_ports: warning: port test 3: "
 "in \" smtps = submission = foo\": non-numerical service port\n",
  /* export */ "lmtp=24"
    },
    {"service name test 1",
  /* config */ "smtps = sub mission = 465",
  /* warning */ "config_known_tcp_ports: warning: service name test 1: "
 "in \"smtps = sub mission = 465\": whitespace in service name\n",
  /* export */ "smtps=465"
    },
    {"service name test 2",
  /* config */ "lmtp = 24, smtps = 1234 = submissions = 465",
  /* warning */ "config_known_tcp_ports: warning: service name test 2: "
 "in \" smtps = 1234 = submissions = 465\": numerical service name\n",
  /* export */ "lmtp=24 smtps=465 submissions=465"
    },
    0,
};

int     main(int argc, char **argv)
{
    VSTRING *export_buf;
    struct test_case *tp;
    int     pass = 0;
    int     fail = 0;
    int     test_failed;
    const char *export;
    VSTRING *msg_buf;
    VSTREAM *memory_stream;

#define STRING_OR_NULL(s) ((s) ? (s) : "(null)")

    msg_vstream_init("config_known_tcp_ports", VSTREAM_ERR);

    export_buf = vstring_alloc(100);
    msg_buf = vstring_alloc(100);
    for (tp = test_cases; tp->label != 0; tp++) {
 test_failed = 0;
 if ((memory_stream = vstream_memopen(msg_buf, O_WRONLY)) == 0)
     msg_fatal("open memory stream: %m");
 vstream_swap(VSTREAM_ERR, memory_stream);
 config_known_tcp_ports(tp->label, tp->config);
 vstream_swap(memory_stream, VSTREAM_ERR);
 if (vstream_fclose(memory_stream))
     msg_fatal("close memory stream: %m");
 if (strcmp(STR(msg_buf), tp->exp_warning) != 0) {
     msg_warn("test case %s: got error: \"%s\", want: \"%s\"",
       tp->label, STR(msg_buf),
       STRING_OR_NULL(tp->exp_warning));
     test_failed = 1;
 } else {
     export = export_known_tcp_ports(export_buf);
     if (strcmp(export, tp->exp_export) != 0) {
  msg_warn("test case %s: got export: \"%s\", want: \"%s\"",
    tp->label, export, tp->exp_export);
  test_failed = 1;
     }
     clear_known_tcp_ports();
     VSTRING_RESET(msg_buf);
     VSTRING_TERMINATE(msg_buf);
 }
 if (test_failed) {
     msg_info("%s: FAIL", tp->label);
     fail++;
 } else {
     msg_info("%s: PASS", tp->label);
     pass++;
 }
    }
    msg_info("PASS=%d FAIL=%d", pass, fail);
    vstring_free(msg_buf);
    vstring_free(export_buf);
    exit(fail != 0);
}

#endif

Messung V0.5 in Prozent
C=90 H=99 G=94

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

*© 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.