main.cf and master.cf parameter names (i.e. parameters that
aren't used anywhere), and it finally displays user-defined
main.cf parameters that *are* used. File: postconf/postconf.c.
+
+20111113
+
+ Cleanup: documented the postconf algorithms and their
+ limitations, and added regression tests to speed up future
+ development. File: postconf/postconf.c
If you upgrade from Postfix 2.7 or earlier, read RELEASE_NOTES-2.8
before proceeding.
+Incompatible changes with snapshot 20111113
+===========================================
+
+The postconf command now logs warnings about unused "name=value"
+entries in main.cf, and about unused "-o name=value" entries in
+master.cf. Such entries are the result of feature creep in Postfix,
+and of mis-typed names. Once the configurations are cleaned up,
+Postfix configuration changes will be more robust.
+
+Major changes with snapshot 20111113
+====================================
+
+postconf support to warn about unused "name=value" entries in
+main.cf, and about unused "-o name=value" entries in master.cf.
+This should help to eliminate common errors with mis-typed names.
+
+The only known limitation is lack of support for per-service parameter
+name spaces in master.cf, meaning that "-o user-defined-name=value"
+always results in an "unused parameter" warning.
+
+This completes an effort that expanded postconf.c by 553 lines of
+code that were designed, written, tested and documented (in 250
+lines) at the cost of 31 person-hours, spread out over 7 days.
+
Major changes with snapshot 20111108
====================================
Things to do after the stable release:
- postconf: legitimize spontaneous_name=value if it is
- referenced as legitimate_name=$spontaneous_name in main.cf
- or master.cf, and warn about spontaneous_name=value that
- have no legitimizing reference. Use mac_expand callback
- to identidy references, and add mac_expand option to always
- expand a conditional macro's right-hand side.
+ postconf: add test cases for unused name=value entries in
+ main.cf and master.cf; add support for per-service parameter
+ name spaces in master.cf.
TLS_README has the priorities reversed. The section about
SMTP client settings begins with an exposition about client
<b>DIAGNOSTICS</b>
Problems are reported to the standard error stream.
+<b>BUGS</b>
+ There currently is no support for per-service parameter
+ name spaces in <a href="master.5.html">master.cf</a>. This means that "-o user-
+ defined-name=value" always results in an "unused parame-
+ ter" warning.
+
<b>ENVIRONMENT</b>
<b>MAIL_CONFIG</b>
Directory with Postfix configuration files.
<b>CONFIGURATION PARAMETERS</b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
to this program.
- The text below provides only a parameter summary. See
+ The text below provides only a parameter summary. See
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
- Pathname of a configuration file with bounce mes-
+ Pathname of a configuration file with bounce mes-
sage templates.
<b>FILES</b>
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
# Do not build with FreeBSD/NetBSD/OpenBSD/MacOSX KQUEUE support.
# By default, KQUEUE support is compiled in on platforms that
# are known to support it.
+# .IP \fB-DNO_NIS\fR
+# Do not build with NIS or NISPLUS support.
# .IP \fB-DNO_PCRE\fR
# Do not build with PCRE support.
# By default, PCRE support is compiled in when the \fBpcre-config\fR
.ad
.fi
Problems are reported to the standard error stream.
+.SH BUGS
+.ad
+.fi
+There currently is no support for per-service parameter
+name spaces in master.cf. This means that "-o
+user-defined-name=value" always results in an "unused
+parameter" warning.
.SH "ENVIRONMENT"
.na
.nf
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20111112"
+#define MAIL_RELEASE_DATE "20111113"
#define MAIL_VERSION_NUMBER "2.9"
#ifdef SNAPSHOT
str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h \
nint_table.h nint_vars.h nbool_table.h nbool_vars.h long_table.h \
long_vars.h
+TEST_TMP= main.cf master.cf
DUMMIES = makes_dummy # for "make -j"
PROG = postconf
SAMPLES = ../../conf/main.cf.default
test: $(TESTPROG)
-tests:
+tests: test1 test2 test3 test4 test5
root_tests:
$(AWK) -f extract.awk ../*/*.c | $(SHELL)
touch makes_dummy
+
+# Define two parameters with smtpd_restriction_classes. One will be ignored.
+
+test1: $(PROG) test1.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ echo smtpd_restriction_classes = foo bar >> main.cf
+ echo foo = yes >> main.cf
+ ./$(PROG) -nc . >test1.tmp 2>&1
+ diff test1.ref test1.tmp
+ rm -f main.cf master.cf test1.tmp
+
+# Define two unused parameters. Expect two warnings.
+
+test2: $(PROG) test2.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ echo restriction_classes = foo bar >> main.cf
+ echo foo = yes >> main.cf
+ ./$(PROG) -nc . >test2.tmp 2>&1
+ diff test2.ref test2.tmp
+ rm -f main.cf master.cf test2.tmp
+
+# Define one parameter in main,cf, validate it with main.cf.
+
+test3: $(PROG) test3.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ ./$(PROG) -nc . >test_base.tmp 2>&1
+ echo foo = yes >> main.cf
+ echo 'bar = $$foo' >> main.cf
+ echo 'always_bcc = $$bar' >> main.cf
+ ./$(PROG) -nc . >test3.tmp 2>&1
+ diff test3.ref test3.tmp
+ rm -f main.cf master.cf test3.tmp
+
+# Define one parameter in main.cf, validate it with master.cf.
+
+test4: $(PROG) test4.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ ./$(PROG) -nc . >test_base.tmp 2>&1
+ echo foo = yes >> main.cf
+ echo 'bar = $$foo' >> main.cf
+ echo smtpd 1 2 3 4 5 6 7 >> master.cf
+ echo ' -o always_bcc=$$bar' >> master.cf
+ ./$(PROG) -nc . >test4.tmp 2>&1
+ diff test4.ref test4.tmp
+ rm -f main.cf master.cf test4.tmp
+
+# Define one user-defined parameter with name=value in master.cf,
+# validate it with known_parameter=$name in master.cf. Currently,
+# user-defined parameter definitions in master.cf are not recognized
+# as definitions, and result in an "unused parameter" warning.
+
+test5: $(PROG) test5.ref
+ rm -f main.cf master.cf
+ touch main.cf master.cf
+ ./$(PROG) -nc . >test_base.tmp 2>&1
+ echo smtpd 1 2 3 4 5 6 7 >> master.cf
+ echo ' -o bar=yes -o always_bcc=$$bar -o' >> master.cf
+ ./$(PROG) -nc . >test5.tmp 2>&1
+ diff test5.ref test5.tmp
+ rm -f main.cf master.cf test5.tmp
+
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
lint $(DEFS) $(SRCS) $(LINTFIX)
clean:
- rm -f *.o *core $(PROG) $(TESTPROG) junk $(MAKES) $(AUTOS) $(DUMMIES)
+ rm -f *.o *core $(PROG) $(TESTPROG) junk $(MAKES) $(AUTOS) $(DUMMIES) \
+ $(TEST_TMP) *.tmp
rm -rf printfck
tidy: clean
/* This feature is available with Postfix 2.6 and later.
/* DIAGNOSTICS
/* Problems are reported to the standard error stream.
+/* BUGS
+/* There currently is no support for per-service parameter
+/* name spaces in master.cf. This means that "-o
+/* user-defined-name=value" always results in an "unused
+/* parameter" warning.
/* ENVIRONMENT
/* .ad
/* .fi
/*
* Lookup table for in-core parameter info.
+ *
+ * XXX Change the value pointers from table indices into pointers to parameter
+ * objects with print methods.
*/
HTABLE *param_table;
/*
* Lookup table for master.cf info.
+ *
+ * XXX Replace by data structures with per-entry hashes for "-o name=value", so
+ * that we can properly handle of definitions and uses in per-service name
+ * spaces.
*/
static ARGV **master_table;
/*
- * Declarations generated by scanning actual C source files.
+ * Support for built-in parameters: declarations generated by scanning
+ * actual C source files.
*/
#include "time_vars.h"
#include "bool_vars.h"
#include "long_vars.h"
/*
- * Manually extracted.
+ * Support for built-in parameters: manually extracted.
*/
#include "install_vars.h"
/*
- * Lookup tables generated by scanning actual C source files.
+ * Support for built-in parameters: lookup tables generated by scanning
+ * actual C source files.
*/
static const CONFIG_TIME_TABLE time_table[] = {
#include "time_table.h"
} STRING_NV;
/*
- * Support for parameters whose postfix-defined names are derived from
- * master.cf service names. These parameters have default values that are
- * defined by built-in parameters.
+ * Service-defined parameter names are created by appending postfix-defined
+ * suffixes to master.cf service names. These parameters have default values
+ * that are defined by built-in parameters.
*/
static STRING_NV *serv_param_table;
static ssize_t serv_param_tablen;
/*
- * Support for parameters whose user-defined names are specified in main.cf
- * with smtpd_restriction_classes, and for user-defined parameters whose
- * "name=value" appears in main.cf and whose $name appears in the value of
- * in master.cf "-o name=value" entries, or in main.cf "name=value" entries
- * for known parameters.
+ * Support for user-defined parameters.
+ *
+ * There are three categories of known parameters: built-in, service-defined
+ * (see previous comment), and valid user-defined. In addition there are
+ * multiple name spaces: the global main.cf name space, and the per-service
+ * name space of each master.cf entry.
+ *
+ * There are two categories of valid user-defined parameters:
+ *
+ * - Parameters whose name appears in the value of smtpd_restriction_classes in
+ * main.cf, and whose name has a "name=value" entry in main.cf (todo:
+ * support for creating names with "-o smtpd_restriction_classes=name"
+ * within a master.cf per-service name space).
+ *
+ * - Parameters whose $name (macro expansion) appears in the value of a
+ * "name=value" entry in main.cf or master.cf of a "known" parameter, and
+ * whose name has a "name=value" entry in main.cf (todo: master.cf).
+ *
+ * All other user-defined parameters are invalid. We currently log a warning
+ * for "name=value" entries in main.cf or master.cf whose $name does not
+ * appear in the value of a main.cf or master.cf "name=value" entry of a
+ * "known" parameter.
*/
static char **user_param_table;
static ssize_t user_param_tablen;
* We can't use the master_ent routines in their current form. They
* convert everything to internal form, and they skip disabled services.
* We need to be able to show default fields as "-", and we need to know
- * about all service names so that we can generate dynamic parameter
- * names (transport-dependent etc.).
+ * about all service names so that we can generate service-dependent
+ * parameter names (transport-dependent etc.).
*/
#define MASTER_BLANKS " \t\r\n" /* XXX */
#define MASTER_FIELD_COUNT 8 /* XXX */
const char *defparam)
{
STRING_NV *sp;
+ char *name = concatenate(service, suffix, (char *) 0);
/*
- * Skip service parameter names that have explicit built-in definitions.
- * This happens with message delivery transports that have a non-default
+ * Skip service parameter names that have built-in definitions. This
+ * happens with message delivery transports that have a non-default
* per-destination concurrency or recipient limit, such as local(8).
- *
- * XXX Skip parameters that are already in the param_table hash.
*/
- serv_param_table = (STRING_NV *)
- myrealloc((char *) serv_param_table,
- (serv_param_tablen + 1) * sizeof(*serv_param_table));
- sp = serv_param_table + serv_param_tablen;
- sp->name = concatenate(service, suffix, (char *) 0);
- sp->value = defparam;
- serv_param_tablen += 1;
+ if (htable_locate(param_table, name) != 0) {
+ myfree(name);
+ } else {
+ serv_param_table = (STRING_NV *)
+ myrealloc((char *) serv_param_table,
+ (serv_param_tablen + 1) * sizeof(*serv_param_table));
+ sp = serv_param_table + serv_param_tablen;
+ sp->name = concatenate(service, suffix, (char *) 0);
+ sp->value = defparam;
+ serv_param_tablen += 1;
+ }
}
/* add_service_parameters - add all service parameters with defaults */
{
/* XXX Merge this with check_parameter_value() */
user_param_table = (char **)
- myrealloc((char *) user_param_table,
- (user_param_tablen + 1) * sizeof(*user_param_table));
+ myrealloc((char *) user_param_table,
+ (user_param_tablen + 1) * sizeof(*user_param_table));
user_param_table[user_param_tablen] = mystrdup(name);
user_param_tablen += 1;
}
+/* scan_user_parameter_value - extract macro names from parameter value */
+
#ifdef MAC_EXP_FLAG_SCAN
#define NO_SCAN_RESULT ((VSTRING *) 0)
#define NO_SCAN_FILTER ((char *) 0)
/*
* Promote only user-defined parameters with an explicit "name=value"
- * main.cf definition. Do not promote parameters whose name appears only
- * as a macro expansion; this is how Postfix implements backwards
- * compatibility after a feature name change.
+ * definition in main.cf (todo: master.cf). Do not promote parameters
+ * whose name appears only as a macro expansion; this is how Postfix
+ * implements backwards compatibility after a feature name change.
*
- * XXX Skip parameters that are already in the param_table hash.
+ * Skip parameters that are already in the param_table hash.
*/
- mac_value = mail_conf_lookup(mac_name);
- if (mac_value != 0) {
- add_user_parameter(mac_name);
- /* Promote parameter names recursively. */
- scan_user_parameter_value(mac_value);
+ if (htable_locate(param_table, mac_name) == 0) {
+ mac_value = mail_conf_lookup(mac_name);
+ if (mac_value != 0) {
+ add_user_parameter(mac_name);
+ /* Promote parameter names recursively. */
+ scan_user_parameter_value(mac_value);
+ }
}
return (0);
}
/*
* Add parameters whose names are defined with smtpd_restriction_classes,
* but only if they have a "name=value" entry in main.cf.
+ *
+ * XXX It is possible that a user-defined parameter is defined in master.cf
+ * with "-o smtpd_restriction_classes=name -o name=value". To handle this
+ * we need to give each master.cf entry its own name space. Until then,
+ * we may log false warnings for unused "-o name=value" entries.
*/
if ((class_list = mail_conf_lookup_eval(VAR_REST_CLASSES)) != 0) {
cp = saved_class_list = mystrdup(class_list);
*
* XXX It is possible that a user-defined parameter is defined in master.cf
* with "-o name1=value1" and then used in a "-o name2=$name1" macro
- * expansion in that same master.cf entry.
+ * expansion in that same master.cf entry. To handle this we need to give
+ * each master.cf entry its own name space. Until then, we may log false
+ * warnings for unused "-o name=value" entries.
*/
for (argvp = master_table; (argv = *argvp) != 0; argvp++) {
for (field = MASTER_FIELD_COUNT; argv->argv[field] != 0; field++) {
* output.
*
* XXX It is possible that a user-defined parameter is defined in master.cf
- * with "-o name1=value1" and then used in a "-o name2=$name1" macro
- * expansion in that same master.cf entry.
+ * with "-o smtpd_restriction_classes=name", or with "-o name1=value1"
+ * and then used in a "-o name2=$name1" macro expansion in that same
+ * master.cf entry. To handle this we need to give each master.cf entry
+ * its own name space. Until then, we may log false warnings for unused
+ * "-o name=value" entries.
*/
for (argvp = master_table; (argv = *argvp) != 0; argvp++) {
for (field = MASTER_FIELD_COUNT; argv->argv[field] != 0; field++) {
/*
* Flag unused parameters. This makes no sense with "postconf -d",
- * because that ignores all the user-specified parameter values that
- * may contain macro expansions with user-defined parameter names.
+ * because that ignores all the user-specified parameters and
+ * user-specified macro expansions in main.cf.
*/
#ifdef MAC_EXP_FLAG_SCAN
if ((cmd_mode & SHOW_DEFS) == 0) {
--- /dev/null
+config_directory = .
+foo = yes
+smtpd_restriction_classes = foo bar
--- /dev/null
+config_directory = .
+./postconf: warning: ./main.cf: unused parameter: restriction_classes=foo bar
+./postconf: warning: ./main.cf: unused parameter: foo=yes
--- /dev/null
+always_bcc = $bar
+bar = $foo
+config_directory = .
+foo = yes
--- /dev/null
+bar = $foo
+config_directory = .
+foo = yes
--- /dev/null
+config_directory = .
+./postconf: warning: ./master.cf: unused parameter: bar=yes
extern int h_errno;
#define MISSING_STRFTIME_E
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/etc:/usr/etc:/usr/ucb"
#define USE_STATFS
extern char *optarg; /* XXX use <getopt.h> */
extern int opterr; /* XXX use <getopt.h> */
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb"
#define USE_STATFS
extern char *optarg;
extern int opterr;
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/etc:/usr/etc:/usr/ucb"
#define USE_STATFS
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
+#ifndef NO_NIS
#define HAS_NIS
#define HAS_NISPLUS
+#endif
#define USE_SYS_SOCKIO_H /* Solaris 2.5, changed sys/ioctl.h */
#define GETTIMEOFDAY(t) gettimeofday(t)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb"
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define USE_SYS_SOCKIO_H
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb"
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
-/* Uncomment the following line if you have NIS package installed
+#ifndef NO_NIS
#define HAS_NIS */
+#endif
#define USE_SYS_SOCKIO_H
#define GETTIMEOFDAY(t) gettimeofday(t,NULL)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb"
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define HAS_SA_LEN
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb"
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define HAS_SA_LEN
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define RESOLVE_H_NEEDS_STDIO_H
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define HAS_SA_LEN
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define RESOLVE_H_NEEDS_STDIO_H
#define HAS_DBM
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define USE_SYS_SOCKIO_H /* XXX check */
#define GETTIMEOFDAY(t) gettimeofday(t)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/bsd"
#define HAS_DB
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
#define FIONREAD_IN_TERMIOS_H
#define HAS_DB
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
#define FIONREAD_IN_TERMIOS_H /* maybe unnecessary */
#define HAS_DB
#define DEF_DB_TYPE "hash"
#define ALIAS_DB_MAP "hash:/etc/aliases"
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
#define FIONREAD_IN_TERMIOS_H
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define ROOT_PATH "/usr/bin:/sbin:/usr/sbin"
#define MISSING_SETENV
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define _PATH_BSHELL "/bin/sh"
#define _PATH_MAILDIR "/var/mail"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define ROOT_PATH "/usr/bin:/sbin:/usr/sbin"
#define MISSING_SETENV
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define _PATH_BSHELL "/bin/sh"
#define _PATH_MAILDIR "/var/mail"
#define INTERNAL_LOCK MYFLOCK_STYLE_FCNTL
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define MISSING_SETENV
#define MISSING_RLIMIT_FSIZE
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define HAVE_SYS_DIR_H
#define STATFS_IN_SYS_VFS_H
#define HAS_FSYNC
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define HAS_NETINFO
#define MISSING_SETENV_PUTENV
#define MISSING_MKFIFO
#define HAVE_SYS_DIR_H
#define STATFS_IN_SYS_VFS_H
#define HAS_FSYNC
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define HAS_NETINFO
#define MISSING_SETENV_PUTENV
#define MISSING_MKFIFO
extern char *optarg; /* XXX use <getopt.h> */
extern int opterr; /* XXX use <getopt.h> */
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb"
#define USE_STATVFS
#define DEF_DB_TYPE "dbm"
#define ALIAS_DB_MAP "dbm:/etc/mail/aliases"
#define DBM_NO_TRAILING_NULL
+#ifndef NO_NIS
#define HAS_NIS
+#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/etc:/usr/bin:/tcb/bin"
#define USE_STATVFS