summaryrefslogtreecommitdiff
path: root/src/readcf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/readcf.c')
-rw-r--r--src/readcf.c238
1 files changed, 212 insertions, 26 deletions
diff --git a/src/readcf.c b/src/readcf.c
index 47c9777cc33b..24b0a6f41bd2 100644
--- a/src/readcf.c
+++ b/src/readcf.c
@@ -16,8 +16,8 @@
#if STARTTLS
# include <tls.h>
#endif
-#if DNSSEC_TEST
-# include <sm_resolve.h>
+#if DNSSEC_TEST || _FFR_NAMESERVER
+# include "sm_resolve.h"
#endif
SM_RCSID("@(#)$Id: readcf.c,v 8.692 2013-11-22 20:51:56 ca Exp $")
@@ -33,12 +33,18 @@ SM_RCSID("@(#)$Id: readcf.c,v 8.692 2013-11-22 20:51:56 ca Exp $")
#define HOURS HOUR
static void fileclass __P((int, char *, char *, bool, bool, bool));
+#if _FFR_DYN_CLASS
+static void dynclass __P((int, char *));
+#endif
static char **makeargv __P((char *));
static void settimeout __P((char *, char *, bool));
static void toomany __P((int, int));
static char *extrquotstr __P((char *, char **, char *, bool *));
static void parse_class_words __P((int, char *));
+#if _FFR_CLASS_RM_ENTRY
+static void classrmentry __P((int, char *));
+#endif
#if _FFR_BOUNCE_QUEUE
static char *bouncequeue = NULL;
@@ -161,6 +167,11 @@ readcf(cfname, safe, e)
char pvpbuf[MAXLINE + MAXATOM];
static char *null_list[1] = { NULL };
extern unsigned char TokTypeNoC[];
+#if _FFR_CLASS_RM_ENTRY
+ int off;
+#else
+# define off 1
+#endif
FileName = cfname;
LineNumber = 0;
@@ -463,7 +474,6 @@ readcf(cfname, safe, e)
endtoken = 0;
break;
-
#if 0
/*
** This doesn't work yet as there are maps defined *after* the cf
@@ -534,12 +544,12 @@ readcf(cfname, safe, e)
if (mid == 0)
break;
#if USE_EAI && 0
- if ('j' == mid && !addr_is_ascii(ep))
- {
- usrerr("hostname %s must be ASCII", ep);
- finis(false, true, EX_CONFIG);
- /* NOTREACHED */
- }
+// if ('j' == mid && !addr_is_ascii(ep))
+// {
+// usrerr("hostname %s must be ASCII", ep);
+// finis(false, true, EX_CONFIG);
+// /* NOTREACHED */
+// }
#endif
p = munchstring(ep, NULL, '\0');
macdefine(&e->e_macro, A_TEMP, mid, p);
@@ -551,9 +561,15 @@ readcf(cfname, safe, e)
case 'C': /* word class */
case 'T': /* trusted user (set class `t') */
+#if _FFR_CLASS_RM_ENTRY
+ if (bp[0] != '\0' && bp[1] == '-')
+ off = 2;
+ else
+ off = 1;
+#endif
if (bp[0] == 'C')
{
- mid = macid_parse(&bp[1], &ep);
+ mid = macid_parse(&bp[off], &ep);
if (mid == 0)
break;
expand(ep, exbuf, sizeof(exbuf), e);
@@ -565,7 +581,7 @@ readcf(cfname, safe, e)
else
{
mid = 't';
- p = &bp[1];
+ p = &bp[off];
}
while (*p != '\0')
{
@@ -580,11 +596,29 @@ readcf(cfname, safe, e)
delim = *p;
*p = '\0';
if (wd[0] != '\0')
- setclass(mid, wd);
+ {
+ if (off < 2)
+ setclass(mid, wd);
+#if _FFR_CLASS_RM_ENTRY
+ else
+ classrmentry(mid, wd);
+#endif /* _FFR_CLASS_RM_ENTRY */
+ }
*p = delim;
}
break;
+#if _FFR_DYN_CLASS
+ case 'A': /* dynamic class */
+ mid = macid_parse(&bp[1], &ep);
+ if (mid == 0)
+ break;
+ for (p = ep; SM_ISSPACE(*p); )
+ p++;
+ dynclass(mid, p);
+ break;
+#endif
+
case 'F': /* word class from file */
mid = macid_parse(&bp[1], &ep);
if (mid == 0)
@@ -940,11 +974,11 @@ toomany(id, maxcnt)
syserr("too many %c lines, %d max", id, maxcnt);
}
/*
-** FILECLASS -- read members of a class from a file
+** FILECLASS -- read members of a class from a file, program, or map
**
** Parameters:
** class -- class to define.
-** filename -- name of file to read.
+** filename -- name of file to read/specification of map and key.
** fmt -- scanf string to use for match.
** ismap -- if set, this is a map lookup.
** safe -- if set, this is a safe read.
@@ -955,8 +989,10 @@ toomany(id, maxcnt)
** none
**
** Side Effects:
-** puts all lines in filename that match a scanf into
-** the named class.
+** puts all entries retrieved from a file, program, or map
+** into the named class:
+** - file or |prg: all words in lines that match a scanf fmt
+** - map: all words in value (rhs) of a map lookup of a key
*/
/*
@@ -1109,7 +1145,6 @@ fileclass(class, filename, fmt, ismap, safe, optional)
sm_dprintf("fileclass: F{%s}: map class %s, key %s, spec %s\n",
mn, cl, key, spec);
-
/* parse map spec */
if (!map.map_class->map_parse(&map, spec))
{
@@ -1229,6 +1264,124 @@ fileclass(class, filename, fmt, ismap, safe, optional)
(void) waitfor(pid);
}
+#if _FFR_DYN_CLASS
+
+/*
+** DYNCLASS -- open a dynamic class
+**
+** Parameters:
+** class -- class to define.
+** arg -- rest of class definition from cf.
+**
+** Returns:
+** none
+*/
+
+static void
+dynclass(class, arg)
+ int class;
+ char *arg;
+{
+ char *p;
+ char *tag;
+ char *mn;
+ char *maptype, *spec;
+ STAB *mapclass, *dynmap;
+
+ mn = newstr(macname(class));
+ if (*arg == '\0')
+ {
+ syserr("dynamic class: A{%s}: missing class definition", mn);
+ return;
+ }
+ tag = arg;
+ dynmap = stab(mn, ST_DYNMAP, ST_FIND);
+ if (NULL != dynmap)
+ {
+ syserr("dynamic class: A{%s}: already defined", mn);
+ goto error;
+ }
+
+ /* skip past tag */
+ if ((p = strchr(arg, '@')) == NULL)
+ {
+ /* should not happen */
+ syserr("dynamic class: A{%s}: bogus map specification", mn);
+ goto error;
+ }
+
+ /* skip past '@' */
+ *p++ = '\0';
+ maptype = p;
+
+ if ((spec = strchr(maptype, ':')) == NULL)
+ {
+ syserr("dynamic class: A{%s}: missing map class", mn);
+ goto error;
+ }
+ *spec++ ='\0';
+
+ /* set up map structure */
+ mapclass = stab(maptype, ST_MAPCLASS, ST_FIND);
+ if (NULL == mapclass)
+ {
+ syserr("dynamic class: A{%s}: map type %s not available",
+ mn, maptype);
+ goto error;
+ }
+
+ if (tTd(37, 5))
+ sm_dprintf("dynamic class: A{%s}: type='%s', tag='%s', spec='%s'\n",
+ mn, maptype, tag, spec);
+
+ /* enter map in stab */
+ dynmap = stab(mn, ST_DYNMAP, ST_ENTER);
+ if (NULL == dynmap)
+ {
+ syserr("dynamic class: A{%s}: cannot enter", mn);
+ goto error2;
+ }
+ dynmap->s_dynclass.map_class = &mapclass->s_mapclass;
+ dynmap->s_dynclass.map_mname = newstr(mn);
+
+ /* parse map spec */
+ if (!dynmap->s_dynclass.map_class->map_parse(&dynmap->s_dynclass, spec))
+ {
+ /* map_parse() showed the error already */
+ goto error;
+ }
+
+ /* open map */
+ if (dynmap->s_dynclass.map_class->map_open(&dynmap->s_dynclass, O_RDONLY))
+ {
+ dynmap->s_dynclass.map_mflags |= MF_OPEN;
+ dynmap->s_dynclass.map_pid = getpid();
+ }
+ else
+ {
+ syserr("dynamic class: A{%s}: map open failed", mn);
+ goto error;
+ }
+ dynmap->s_dynclass.map_mflags |= MF_VALID;
+ dynmap->s_dynclass.map_tag = newstr(tag);
+
+#if 0
+ /* close map: where to do this? */
+ dynmap->s_dynclass.map_mflags |= MF_CLOSING;
+ dynmap->s_dynclass.map_class->map_close(&map);
+ dynmap->s_dynclass.map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
+#endif
+ sm_free(mn);
+ return;
+
+ error:
+ dynmap->s_dynclass.map_mflags |= MF_OPENBOGUS;
+ error2:
+ sm_free(mn);
+ return;
+}
+#endif
+
#if _FFR_RCPTFLAGS
/* first character for dynamically created mailers */
static char dynmailerp = ' ';
@@ -1380,7 +1533,6 @@ newmodmailer(rcpt, fl)
** enters the mailer into the mailer table.
*/
-
void
makemailer(line)
char *line;
@@ -2958,7 +3110,7 @@ static struct optioninfo
#endif
#if _FFR_EIGHT_BIT_ADDR_OK
# if !ALLOW_255
-# ERROR "_FFR_EIGHT_BIT_ADDR_OK requires ALLOW_255"
+# error "_FFR_EIGHT_BIT_ADDR_OK requires ALLOW_255"
# endif
# define O_EIGHT_BIT_ADDR_OK 0xdf
{ "EightBitAddrOK", O_EIGHT_BIT_ADDR_OK, OI_NONE },
@@ -3013,7 +3165,7 @@ static struct optioninfo
# define O_TLSFB2CLEAR 0xef
{ "TLSFallbacktoClear", O_TLSFB2CLEAR, OI_NONE },
#endif
-#if DNSSEC_TEST
+#if DNSSEC_TEST || _FFR_NAMESERVER
# define O_NSPORTIP 0xf0
{ "NameServer", O_NSPORTIP, OI_NONE },
#endif
@@ -3021,7 +3173,7 @@ static struct optioninfo
# define O_DANE 0xf1
{ "DANE", O_DANE, OI_NONE },
#endif
-#if DNSSEC_TEST
+#if DNSSEC_TEST || _FFR_NAMESERVER
# define O_NSSRCHLIST 0xf2
{ "NameSearchList", O_NSSRCHLIST, OI_NONE },
#endif
@@ -3744,7 +3896,6 @@ setoption(opt, val, safe, sticky, e)
WkTimeFact = atoi(val);
break;
-
#if _FFR_QUEUE_GROUP_SORTORDER
/* coordinate this with makequeue() */
#endif
@@ -4737,7 +4888,7 @@ setoption(opt, val, safe, sticky, e)
UseCompressedIPv6Addresses = atobool(val);
break;
-#if DNSSEC_TEST
+#if DNSSEC_TEST || _FFR_NAMESERVER
case O_NSPORTIP:
nsportip(val);
break;
@@ -4776,9 +4927,9 @@ setoption(opt, val, safe, sticky, e)
#if USE_EAI
/* hack for testing */
if (isascii(*val) && isdigit(*val))
- SMTPUTF8 = (int) strtol(val, NULL, 0);
+ SMTP_UTF8 = (int) strtol(val, NULL, 0);
else
- SMTPUTF8 = atobool(val);
+ SMTP_UTF8 = atobool(val);
#else
if (atobool(val))
syserr("readcf: option: %s set but no USE_EAI support",
@@ -4861,6 +5012,42 @@ setclass(class, str)
setbitn(bitidx(class), s->s_class);
}
}
+
+#if _FFR_CLASS_RM_ENTRY
+/*
+** CLASSRMENTRY -- remove a string from a class
+**
+** Parameters:
+** class -- the class from which to remove the string.
+** str -- the string to remove
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** removes the string from the class (if it was in there).
+*/
+
+static void
+classrmentry(class, str)
+ int class;
+ char *str;
+{
+ STAB *s;
+
+ s = stab(str, ST_CLASS, ST_FIND);
+ if (NULL == s /* || ST_CLASS != s->s_symtype */)
+ {
+ if (tTd(37, 8))
+ sm_dprintf("classrmentry: entry=%s not in class %s\n", str, macname(class));
+ return;
+ }
+ clrbitn(bitidx(class), s->s_class);
+ if (tTd(37, 8))
+ sm_dprintf("classrmentry(%s, %s)=%d\n", macname(class), str, bitnset(bitidx(class), s->s_class));
+}
+#endif /* _FFR_CLASS_RM_ENTRY */
+
/*
** MAKEMAPENTRY -- create a map entry
**
@@ -5169,7 +5356,6 @@ static struct timeoutinfo
{ NULL, 0 },
};
-
static void
settimeout(name, val, sticky)
char *name;