diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-03-06 18:50:45 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-03-06 18:50:45 +0200 |
commit | 248a97fbf0656d12839ca8986287d216820c9849 (patch) | |
tree | e23c9635b7c752ca1b6ed95ecabc1590a18c548b | |
parent | 8f8a1c98f84669306d1489ddc5d55b6f589df9be (diff) | |
download | alck-248a97fbf0656d12839ca8986287d216820c9849.tar.gz alck-248a97fbf0656d12839ca8986287d216820c9849.tar.bz2 |
Remove site-specific defaults. Improve local-domain options.
* alck.1: Update.
* alck.h (read_include): Remove.
(freadlist, preadlist): New protos.
* gram.y (usage): Update output.
(main): Change -f to -T. Add -W option (read
class w from a command stdout). Change handling
of the -w option.
Remove cwfile - there's no longer a default for -w.
* lex.l (read_include): Rename to freadlist and rewrite.
(preadlist): New function.
-rw-r--r-- | alck.1 | 73 | ||||
-rw-r--r-- | alck.h | 3 | ||||
-rw-r--r-- | gram.y | 44 | ||||
-rw-r--r-- | lex.l | 89 |
4 files changed, 164 insertions, 45 deletions
@@ -14,5 +14,5 @@ .\" You should have received a copy of the GNU General Public License .\" along with Alck. If not, see <http://www.gnu.org/licenses/>. -.TH ALCK 1 "March 5, 2013" "ALCK" +.TH ALCK 1 "March 6, 2013" "ALCK" .SH NAME alck \- check MTA alias files @@ -30,8 +30,12 @@ checks one or several alias files for consistency. The following tests are performed: .TP +.B Multiply defined aliases +.TP .B Transitivity test This test discovers eventual circular dependencies. .TP .B Use of prohibited aliases +This test is optional. When enabled, it detects the use of pipes, +file redirects and includes in the input files. .PP The program returns 0 if all tests pass successfully. Otherwise, @@ -80,4 +84,8 @@ In any case, if several alias files are supplied, treats them as parts of a single alias file. .SH OPTIONS +.SS General +These options affect the behavior of the program in general. They can +be specified anywhere in the command line and affect all options that +follow them. .TP \fB\-d\fR \fISPEC\fR @@ -96,4 +104,53 @@ Upper-case variants are also accepted. Prepending a letter with a dash (\fB\-\fR) reverts its sense. .TP +.B \-v +Verbosely report the results. +.SS Local domain names +The distinction between local and remote email addreses allows +.B alck +to detect circular dependencies between aliases. A local email +is any email that has no domain part, or whose domain part contains +a +.BR "local domain" . +For +.B Sendmail +local domains are those that constitute the +.B w +class. +.PP +The following two options supply local domain names to +.BR alck . +They must appear in the command line before any filenames or +.B \-T +options. +.TP +\fB\-w\fR \fIFILE\fR +Read local domain names from the given +.IR FILE . +The file should list each name on a separate line. Surrounding +whitespace is allowed. Empty lines and +comments (lines starting with the +.B # +character) are ignored. +.TP +\fB\-W\fR \fICOMMAND\fR +Run \fICOMMAND\fR and read local domain names from its standard +output. +.B Alck +will consider for inclusion only those lines that begin with +alphanumeric character and don't contain whitespace. Thus, it is +possible to read the local domain names from the +.B Sendmail +configuration with the following option: +.sp +.nf +.in +2 +-W "echo '$=w' | sendmail -bt" +.in +.fi +.SS Input options +Input options can be interspersed with the input file names. They are +processed in the order of their appearance. +.TP \fB\-T\fR \fIFILE\fR Read names of alias files from \fIFILE\fR. @@ -113,17 +170,7 @@ This options cancels the effect of the previous .B \-r option. -.TP -.B \-v -Verbosely report the results. -.TP -\fB\-w\fR \fIFILE\fR -Read contents of the -.BR Sendmail 's -.B w -class from the given -.IR FILE . -.PP +.SS Informational The following two options instruct the program to display a certain -kind of information and exit: +kind of information and exit. .TP .B \-h @@ -57,5 +57,6 @@ char *slist_member(SLIST *plist, char *name); void slist_destroy(SLIST **plist); -void read_include(SLIST **plist, char *name); +void freadlist(SLIST **plist, char *name); +void preadlist(SLIST **plist, char *progname); void regalias(char *name, SLIST *exp); @@ -21,5 +21,6 @@ char *program_name; SLIST *cw_list; /* List of domain names pertaining to Sendmail 'w' class */ -static int restricted; /* prohibit use of `special' aliases (pipes, + +static int restricted; /* prohibit the use of `special' aliases (pipes, file redirections and includes */ int verbose; /* Verbose mode */ @@ -101,5 +102,5 @@ email : string } $$ = NULL; - read_include(&$$, $2); + freadlist(&$$, $2); } ; @@ -112,5 +113,5 @@ string: IDENT int -yyerror (char *s) +yyerror(char *s) { parserror(file_name, line_num, "%s", s); @@ -175,5 +176,5 @@ usage() printf(" Upper-case variants are also accepted. Prepending\n"); printf(" a letter with '-' reverts its sense\n"); - printf(" -f FILE Read names of alias files from FILE\n"); + printf(" -T FILE Read names of alias files from FILE\n"); printf(" -h Display this help list\n"); printf(" -r Restrict alias file syntax to aliases only (i.e.\n"); @@ -182,6 +183,8 @@ usage() printf(" -v Verbose mode\n"); printf(" -V print program version and exit\n"); - printf(" -w FILE Read contents of Sendmail `w' class from the given\n"); - printf(" file.\n"); + printf(" -w FILE Read local domain names from the FILE\n"); + printf(" -W PROG Run PROG and read local domain names from" + " its stdout\n"); + printf("\n"); printf("Report bugs to <%s>\n", "gray@gnu.org"); @@ -211,5 +214,4 @@ main(int argc, char **argv) int file_count = 0; int true = 1; - char *cwfile = "/etc/mail/sendmail.cw"; SLIST *file_list; /* List of files to be read */ struct string_list *s; @@ -217,9 +219,7 @@ main(int argc, char **argv) init_lex(); program_name = argv[0]; - while ((c = getopt(argc, argv, "-d:f:hp:ruVvw:")) != EOF) { + while ((c = getopt(argc, argv, "-d:hp:rT:uVvW:w:")) != EOF) { switch (c) { case 1: - if (!cw_list) - read_include(&cw_list, cwfile); openaliases(optarg); yyparse(); @@ -253,9 +253,7 @@ main(int argc, char **argv) break; - case 'f': - if (!cw_list) - read_include(&cw_list, cwfile); + case 'T': file_list = NULL; - read_include(&file_list, optarg); + freadlist(&file_list, optarg); if (file_list) { for (s = file_list->head; s; s = s->next) { @@ -286,14 +284,22 @@ main(int argc, char **argv) case 'V': version(); - exit (0); + exit(0); case 'w': if (file_count) - error("-w must be used before first non-option argument"); - cwfile = optarg; + error("-w must be used before the first " + "non-option argument or -T option"); + freadlist(&cw_list, optarg); + break; + + case 'W': + if (file_count) + error("-W must be used before the first " + "non-option argument or -T option"); + preadlist(&cw_list, optarg); break; default: - exit (1); + exit(1); } } @@ -302,6 +308,4 @@ main(int argc, char **argv) argv += optind; - if (!cw_list) - read_include(&cw_list, cwfile); while (argc--) { openaliases(*argv++); @@ -197,10 +197,13 @@ lex_debug(int debug) void -read_include(SLIST **plist, char *name) +freadlist(SLIST **plist, char *name) { char *p; char buffer[256]; - FILE *fp = fopen(name, "r"); - + FILE *fp; + int line = 0; + int skipeol = 0; + + fp = fopen(name, "r"); if (!fp) { parserror(file_name, line_num, @@ -212,17 +215,81 @@ read_include(SLIST **plist, char *name) while (p = fgets(buffer, sizeof buffer, fp)) { - char *q; - + size_t len = strlen(p); + + line++; + + if (len == 0) + continue; + if (p[len-1] != '\n') { + if (!feof(fp)) { + if (!skipeol) + parserror(name, line, + "line too long"); + error_count++; + skipeol = 1; + } + } else if (skipeol) + continue; + else { + p[--len] = 0; + skipeol = 0; + } + while (*p && isspace(*p)) p++; - if (*p == '#') + if (!*p || *p == '#') continue; - for (q = p + strlen(p) - 1; q > p && isspace(*q); q--) - ; - q[1] = 0; - if (*p) - slist_add(plist, p); + + slist_add(plist, p); } fclose(fp); } + +void +preadlist(SLIST **plist, char *progname) +{ + char *p; + char buffer[256]; + FILE *fp; + int line = 0; + int skipeol = 0; + + fp = popen(progname, "r"); + if (!fp) { + parserror(file_name, line_num, + "cannot run `%s': %s", + progname, strerror(errno)); + error_count++; + return; + } + while (p = fgets(buffer, sizeof buffer, fp)) { + size_t len = strlen(p); + char *q; + + line++; + + if (len == 0) + continue; + if (p[len-1] != '\n') { + if (!feof(fp)) { + if (!skipeol) + parserror(progname, line, + "line too long"); + error_count++; + skipeol = 1; + } + } else if (skipeol) + continue; + else { + p[--len] = 0; + skipeol = 0; + } + + if (!*p || !isalnum(*p) || p[strcspn(p, " \t")]) + continue; + + slist_add(plist, p); + } + pclose(fp); +} |