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

Quelle  dict_nisplus.c

  Sprache: C
 

/*++
/* NAME
/* dict_nisplus 3
/* SUMMARY
/* dictionary manager interface to NIS+ maps
/* SYNOPSIS
/* #include <dict_nisplus.h>
/*
/* DICT *dict_nisplus_open(map, open_flags, dict_flags)
/* const char *map;
/* int dummy;
/* int dict_flags;
/* DESCRIPTION
/* dict_nisplus_open() makes the specified NIS+ map accessible via
/* the generic dictionary operations described in dict_open(3).
/* The \fIdummy\fR argument is not used.
/* SEE ALSO
/* dict(3) generic dictionary manager
/* DIAGNOSTICS
/* Fatal errors:
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Geoff Gibbs
/* UK-HGMP-RC
/* Hinxton
/* Cambridge
/* CB10 1SB, UK
/*
/* based on the code for dict_nis.c et al by :-
/*
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/


/* System library. */

#include <sys_defs.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#ifdef HAS_NISPLUS
#include <rpcsvc/nis.h>   /* for nis_list */
#endif

/* Utility library. */

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

#ifdef HAS_NISPLUS

/* Application-specific. */

typedef struct {
    DICT    dict;   /* generic members */
    char   *template;   /* parsed query template */
    int     column;   /* NIS+ field number (start at 1) */
} DICT_NISPLUS;

 /*
  * Begin quote from nis+(1):
  * 
  * The following text represents a  context-free  grammar  that defines  the
  * set of legal  NIS+ names. The terminals in this grammar are the
  * characters `.' (dot),  `['  (open  bracket), `]'  (close  bracket),  `,'
  * (comma),  `=' (equals) and whitespace. Angle brackets (`<' and `>'),
  * which delineate  non- terminals,  are  not  part of the grammar. The
  * character `|' (vertical bar) is used to separate alternate productions
  * and should be read as ``this production OR this production''.
  * 
  * name                ::=    . | <simple name> | <indexed name>
  * 
  * simple name         ::=    <string>. | <string>.<simple name>
  * 
  * indexed name        ::=    <search criterion>,<simple name>
  * 
  * search criterion    ::=    [ <attribute list> ]
  * 
  * attribute list      ::=    <attribute> |  <attribute>,<attribute list>
  * 
  * attribute           ::=    <string> = <string>
  * 
  * string              ::=    ISO Latin 1 character set except  the character
  * '/'  (slash).  The initial character may not be a terminal character or
  * the characters '@' (at), '+' (plus), or (`-') hyphen.
  * 
  * Terminals that appear in strings must be  quoted   with  `"' (double quote).
  * The `"' character may be quoted by quoting it with itself `""'.
  * 
  * End quote fron nis+(1).
  * 
  * This NIS client always quotes the entire query string (the value part of
  * [attribute=value],file.domain.) so the issue with initial characters
  * should not be applicable. One wonders what restrictions are applicable
  * when a string is quoted, but the manual doesn't specify what can appear
  * between quotes, and we don't want to get burned.
  */


 /*
  * SLMs.
  */

#define STR(x) vstring_str(x)

/* dict_nisplus_lookup - find table entry */

static const char *dict_nisplus_lookup(DICT *dict, const char *key)
{
    const char *myname = "dict_nisplus_lookup";
    DICT_NISPLUS *dict_nisplus = (DICT_NISPLUS *) dict;
    static VSTRING *quoted_key;
    static VSTRING *query;
    static VSTRING *retval;
    nis_result *reply;
    int     count;
    const char *cp;
    int     last_col;
    int     ch;

    dict->error = 0;

    /*
     * Initialize.
     */

    if (quoted_key == 0) {
 query = vstring_alloc(100);
 retval = vstring_alloc(100);
 quoted_key = vstring_alloc(100);
    }

    /*
     * Optionally fold the key.
     */

    if (dict->flags & DICT_FLAG_FOLD_FIX) {
 if (dict->fold_buf == 0)
     dict->fold_buf = vstring_alloc(10);
 vstring_strcpy(dict->fold_buf, key);
 key = lowercase(vstring_str(dict->fold_buf));
    }

    /*
     * Check that the lookup key does not contain characters disallowed by
     * nis+(1).
     * 
     * XXX Many client implementations don't seem to care about disallowed
     * characters.
     */

    VSTRING_RESET(quoted_key);
    VSTRING_ADDCH(quoted_key, '"');
    for (cp = key; (ch = *(unsigned const char *) cp) != 0; cp++) {
 if ((ISASCII(ch) && !ISPRINT(ch)) || (ch > 126 && ch < 160)) {
     msg_warn("map %s:%s: lookup key with non-printing character 0x%x:"
       " ignoring this request",
       dict->type, dict->name, ch);
     return (0);
 } else if (ch == '"') {
     VSTRING_ADDCH(quoted_key, '"');
 }
 VSTRING_ADDCH(quoted_key, ch);
    }
    VSTRING_ADDCH(quoted_key, '"');
    VSTRING_TERMINATE(quoted_key);

    /*
     * Plug the key into the query template, which typically looks something
     * like the following: [alias=%s],mail_aliases.org_dir.my.nisplus.domain.
     * 
     * XXX The nis+ documentation defines a length limit for simple names like
     * a.b.c., but defines no length limit for (the components of) indexed
     * names such as [x=y],a.b.c. Our query length is limited because Postfix
     * addresses (in envelopes or in headers) have a finite length.
     */

    vstring_sprintf(query, dict_nisplus->template, STR(quoted_key));
    reply = nis_list(STR(query), FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);

    /*
     * When lookup succeeds, the result may be ambiguous, or the requested
     * column may not exist.
     */

    if (reply->status == NIS_SUCCESS) {
 if ((count = NIS_RES_NUMOBJ(reply)) != 1) {
     msg_warn("ambiguous match (%d results) for %s in NIS+ map %s:"
       " ignoring this request",
       count, key, dict_nisplus->dict.name);
     nis_freeresult(reply);
     return (0);
 } else {
     last_col = NIS_RES_OBJECT(reply)->zo_data
  .objdata_u.en_data.en_cols.en_cols_len - 1;
     if (dict_nisplus->column > last_col)
  msg_fatal("requested column %d > max column %d in table %s",
     dict_nisplus->column, last_col,
     dict_nisplus->dict.name);
     vstring_strcpy(retval,
      NIS_RES_OBJECT(reply)->zo_data.objdata_u
      .en_data.en_cols.en_cols_val[dict_nisplus->column]
      .ec_value.ec_value_val);
     if (msg_verbose)
  msg_info("%s: %s, column %d -> %s", myname, STR(query),
    dict_nisplus->column, STR(retval));
     nis_freeresult(reply);
     return (STR(retval));
 }
    }

    /*
     * When the NIS+ lookup fails for reasons other than "key not found",
     * keep logging warnings, and hope that someone will eventually notice
     * the problem and fix it.
     */

    else {
 if (reply->status != NIS_NOTFOUND
     && reply->status != NIS_PARTIAL) {
     msg_warn("lookup %s, NIS+ map %s: %s",
       key, dict_nisplus->dict.name,
       nis_sperrno(reply->status));
     dict->error = DICT_ERR_RETRY;
 } else {
     if (msg_verbose)
  msg_info("%s: not found: query %s", myname, STR(query));
 }
 nis_freeresult(reply);
 return (0);
    }
}

/* dict_nisplus_close - close NISPLUS map */

static void dict_nisplus_close(DICT *dict)
{
    DICT_NISPLUS *dict_nisplus = (DICT_NISPLUS *) dict;

    myfree(dict_nisplus->template);
    if (dict->fold_buf)
 vstring_free(dict->fold_buf);
    dict_free(dict);
}

/* dict_nisplus_open - open NISPLUS map */

DICT   *dict_nisplus_open(const char *map, int open_flags, int dict_flags)
{
    const char *myname = "dict_nisplus_open";
    DICT_NISPLUS *dict_nisplus;
    char   *col_field;

    /*
     * Sanity check.
     */

    if (open_flags != O_RDONLY)
 return (dict_surrogate(DICT_TYPE_NISPLUS, map, open_flags, dict_flags,
          "%s:%s map requires O_RDONLY access mode",
          DICT_TYPE_NISPLUS, map));

    /*
     * Initialize. This is a read-only map with fixed strings, not with
     * regular expressions.
     */

    dict_nisplus = (DICT_NISPLUS *)
 dict_alloc(DICT_TYPE_NISPLUS, map, sizeof(*dict_nisplus));
    dict_nisplus->dict.lookup = dict_nisplus_lookup;
    dict_nisplus->dict.close = dict_nisplus_close;
    dict_nisplus->dict.flags = dict_flags | DICT_FLAG_FIXED;
    if (dict_flags & DICT_FLAG_FOLD_FIX)
 dict_nisplus->dict.fold_buf = vstring_alloc(10);
    dict_nisplus->dict.owner.status = DICT_OWNER_TRUSTED;

    /*
     * Convert the query template into an indexed name and column number. The
     * query template looks like:
     * 
     * [attribute=%s;attribute=value...];simple.name.:column
     * 
     * One instance of %s gets to be replaced by a version of the lookup key;
     * other attributes must specify fixed values. The reason for using ';'
     * is that the comma character is special in main.cf. When no column
     * number is given at the end of the map name, we use a default column.
     */

    dict_nisplus->template = mystrdup(map);
    translit(dict_nisplus->template";"",");
    if ((col_field = strstr(dict_nisplus->template".:")) != 0) {
 col_field[1] = 0;
 col_field += 2;
 if (!alldig(col_field) || (dict_nisplus->column = atoi(col_field)) < 1)
     msg_fatal("bad column field in NIS+ map name: %s", map);
    } else {
 dict_nisplus->column = 1;
    }
    if (msg_verbose)
 msg_info("%s: opened NIS+ table %s for column %d",
   myname, dict_nisplus->template, dict_nisplus->column);
    return (&dict_nisplus->dict);
}

#endif

Messung V0.5 in Prozent
C=72 H=94 G=83

¤ Dauer der Verarbeitung: 0.11 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.