SCCSID(@
(#)readcf.c 3.21 %G%);
** READCF -- read control file.
** This routine reads the control file and builds the internal
** The file is formatted as a sequence of lines, each taken
** atomically. The first character of each line describes how
** the line is to be interpreted. The lines are:
** Dxval Define macro x to have value val.
** Cxword Put word into class x.
** Fxfile [fmt] Read file for lines to put into
** class x. Use scanf string 'fmt'
** or "%s" if not present. Fmt should
** only produce one string-valued result.
** Hname: value Define header with field-name 'name'
** and value as specified; this will be
** macro expanded immediately before
** Sn Use rewriting set n.
** Rlhs rhs Rewrite addresses that match lhs to
** Mn p f r a Define mailer. n - internal name,
** p - pathname, f - flags, r - rewriting
** rule for sender, a - argument vector.
** cfname -- control file name.
** safe -- set if this is a system configuration file.
** Non-system configuration files can not do
** certain things (e.g., leave the SUID bit on
** when executing mailers).
** Builds several internal tables.
struct rewrite
*RewriteRules
[10];
struct rewrite
*rwp
= NULL
;
extern char **copyplist();
syserr("cannot open %s", cfname
);
while (fgets(buf
, sizeof buf
, cf
) != NULL
)
case 'R': /* rewriting rule */
for (p
= &buf
[1]; *p
!= '\0' && *p
!= '\t'; p
++)
syserr("invalid rewrite line \"%s\"", buf
);
/* allocate space for the rule header */
RewriteRules
[ruleset
] = rwp
=
(struct rewrite
*) xalloc(sizeof *rwp
);
rwp
->r_next
= (struct rewrite
*) xalloc(sizeof *rwp
);
/* expand and save the LHS */
(void) expand(&buf
[1], exbuf
, &exbuf
[sizeof exbuf
]);
rwp
->r_lhs
= prescan(exbuf
, '\t');
rwp
->r_lhs
= copyplist(rwp
->r_lhs
, TRUE
);
/* expand and save the RHS */
(void) expand(p
, exbuf
, &exbuf
[sizeof exbuf
]);
rwp
->r_rhs
= prescan(exbuf
, '\t');
rwp
->r_rhs
= copyplist(rwp
->r_rhs
, TRUE
);
case 'S': /* select rewriting set */
case 'D': /* macro definition */
define(buf
[1], newstr(&buf
[2]));
case 'H': /* required header line */
(void) chompheader(&buf
[1], TRUE
);
case 'C': /* word class */
case 'F': /* word class from file */
/* read list of words from argument or file */
for (p
= &buf
[2]; *p
!= '\0' && !isspace(*p
); p
++)
fileclass(class, &buf
[2], p
);
/* scan the list of words and set class for all */
for (p
= &buf
[2]; *p
!= '\0'; )
while (*p
!= '\0' && isspace(*p
))
while (*p
!= '\0' && !isspace(*p
))
s
= stab(wd
, ST_CLASS
, ST_ENTER
);
s
->s_class
|= 1 << class;
case 'M': /* define mailer */
makemailer(&buf
[1], safe
);
syserr("unknown control line \"%s\"", buf
);
** FILECLASS -- read members of a class from a file
** class -- class to define.
** filename -- name of file to read.
** fmt -- scanf string to use for match.
** puts all lines in filename that match a scanf into
fileclass(class, filename
, fmt
)
f
= fopen(filename
, "r");
syserr("cannot open %s", filename
);
while (fgets(buf
, sizeof buf
, f
) != NULL
)
if (sscanf(buf
, fmt
, wordbuf
) != 1)
s
= stab(wordbuf
, ST_CLASS
, ST_ENTER
);
s
->s_class
|= 1 << class;
** MAKEMAILER -- define a new mailer.
** line -- description of mailer. This is in tokens
** separated by white space. The fields are:
** * the name of the mailer, as refered to
** in the rewriting rules.
** * the pathname of the program to fork to
** * the options needed by this program.
** * the macro string needed to translate
** a local "from" name to one that can be
** returned to this machine.
** * the argument vector (a series of parameters).
** safe -- set if this is a safe configuration file.
** enters the mailer into the mailer table.
while (*p != '\0' && isspace(*p)) \
while (*p != '\0' && !isspace(*p)) \
extern u_long
mfencode();
register struct mailer
*m
;
if (NextMailer
>= MAXMAILERS
)
syserr("Too many mailers defined");
/* collect initial information */
syserr("invalid M line in configuration file");
m
= (struct mailer
*) xalloc(sizeof *m
);
m
->m_name
= newstr(mname
);
m
->m_mailer
= newstr(mpath
);
m
->m_from
= newstr(mfrom
);
m
->m_badstat
= EX_UNAVAILABLE
;
Mailer
[NextMailer
++] = m
;
/* collect the argument vector */
for (i
= 0; i
< MAXPV
- 1 && *p
!= '\0'; i
++)
m
->m_argv
= (char **) xalloc((unsigned) (sizeof margv
[0] * i
));
bmove((char *) margv
, (char *) m
->m_argv
, sizeof margv
[0] * i
);
s
= stab(m
->m_name
, ST_MAILER
, ST_ENTER
);
** PRINTRULES -- print rewrite rules (for debugging)
register struct rewrite
*rwp
;
for (ruleset
= 0; ruleset
< 10; ruleset
++)
if (RewriteRules
[ruleset
] == NULL
)
printf("\n----Rule Set %d:\n", ruleset
);
for (rwp
= RewriteRules
[ruleset
]; rwp
!= NULL
; rwp
= rwp
->r_next
)
for (av
= rwp
->r_lhs
; *av
!= NULL
; av
++)
for (av
= rwp
->r_rhs
; *av
!= NULL
; av
++)
** MFENCODE -- crack mailer options
** These options modify the functioning of the mailer
** from the configuration table.
** p -- pointer to vector of options.
** option list in binary.
char opt_name
; /* external name of option */
int opt_value
; /* internal name of option */
struct optlist OptList
[] =
register struct optlist
*o
;
register u_long opts
= 0;
for (o
= OptList
; o
->opt_name
!= '\0' && o
->opt_name
!= *p
; o
++)
syserr("bad mailer option %c", *p
);
** MFDECODE -- decode mailer flags into external form.
** flags -- value of flags to decode.
** f -- file to write them onto.
register struct optlist
*o
;
for (o
= OptList
; o
->opt_name
!= '\0'; o
++)
if ((o
->opt_value
& flags
) == o
->opt_value
)