diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | ckaliases.c | 416 | ||||
-rw-r--r-- | ckaliases.h | 62 | ||||
-rw-r--r-- | gram.y | 336 | ||||
-rw-r--r-- | lex.l | 213 |
5 files changed, 522 insertions, 508 deletions
diff --git a/Makefile.am b/Makefile.am index c43b7a3..12f531c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,18 +5,19 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # # GSC is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GSC. If not, see <http://www.gnu.org/licenses/>. -AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=ckaliases AM_YFLAGS=-vtd AM_LFLAGS=-d sbin_PROGRAMS=ckaliases noinst_HEADERS=gram.h ckaliases_SOURCES=gram.y lex.l ckaliases.c ckaliases.h +LDADD=../lib/libgsc.a ../gnu/libgnu.a +INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/gnu -I../gnu diff --git a/ckaliases.c b/ckaliases.c index 343a52f..d77e62d 100644 --- a/ckaliases.c +++ b/ckaliases.c @@ -1,321 +1,321 @@ /* ckaliases - verify syntax of sendmail-style alias files - Copyright (C) 2005 Sergey Poznyakoff + Copyright (C) 2005, 2007 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#define obstack_chunk_alloc malloc -#define obstack_chunk_free free -#include <obstack.h> #include "ckaliases.h" -void * -xmalloc(size_t size) -{ - void *p = malloc(size); - if (!p) { - fprintf(stderr, "not enough memory\n"); - exit(1); - } - return p; -} - - #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #define BITS_PER_WORD (sizeof(unsigned)*CHAR_BIT) #define MAXTABLE 32767 #define WORDSIZE(n) (((n) + BITS_PER_WORD - 1) / BITS_PER_WORD) #define SETBIT(x, i) ((x)[(i)/BITS_PER_WORD] |= (1<<((i) % BITS_PER_WORD))) #define RESETBIT(x, i) ((x)[(i)/BITS_PER_WORD] &= ~(1<<((i) % BITS_PER_WORD))) #define BITISSET(x, i) (((x)[(i)/BITS_PER_WORD] & (1<<((i) % BITS_PER_WORD))) != 0) /* given n by n matrix of bits R, modify its contents to be the transitive closure of what was given. */ void -TC(unsigned *R, int n) +TC (unsigned *R, int n) { - register int rowsize; - register unsigned mask; - register unsigned *rowj; - register unsigned *rp; - register unsigned *rend; - register unsigned *ccol; - - unsigned *relend; - unsigned *cword; - unsigned *rowi; - - rowsize = WORDSIZE(n) * sizeof(unsigned); - relend = (unsigned *) ((char *) R + (n * rowsize)); - - cword = R; - mask = 1; - rowi = R; - while (rowi < relend) { - ccol = cword; - rowj = R; - - while (rowj < relend) { - if (*ccol & mask) { - rp = rowi; - rend = (unsigned *) ((char *) rowj + rowsize); - - while (rowj < rend) - *rowj++ |= *rp++; - } else { - rowj = (unsigned *) ((char *) rowj + rowsize); - } - - ccol = (unsigned *) ((char *) ccol + rowsize); - } - - mask <<= 1; - if (mask == 0) { - mask = 1; - cword++; - } - rowi = (unsigned *) ((char *) rowi + rowsize); - } -} + register int rowsize; + register unsigned mask; + register unsigned *rowj; + register unsigned *rp; + register unsigned *rend; + register unsigned *ccol; + + unsigned *relend; + unsigned *cword; + unsigned *rowi; + + rowsize = WORDSIZE (n) * sizeof (unsigned); + relend = (unsigned *) ((char *) R + (n * rowsize)); + + cword = R; + mask = 1; + rowi = R; + while (rowi < relend) + { + ccol = cword; + rowj = R; + + while (rowj < relend) + { + if (*ccol & mask) + { + rp = rowi; + rend = (unsigned *) ((char *) rowj + rowsize); + + while (rowj < rend) + *rowj++ |= *rp++; + } + else + { + rowj = (unsigned *) ((char *) rowj + rowsize); + } + + ccol = (unsigned *) ((char *) ccol + rowsize); + } + mask <<= 1; + if (mask == 0) + { + mask = 1; + cword++; + } + rowi = (unsigned *) ((char *) rowi + rowsize); + } +} void -slist_add(SLIST **plist, char *str) +slist_add (SLIST **plist, char *str) { - struct string_list *p = xmalloc(sizeof(*p)); - p->str = str; - p->next = NULL; - - if (!*plist) { - *plist = xmalloc(sizeof(**plist)); - (*plist)->head = NULL; - } - - if ((*plist)->head == NULL) { - (*plist)->head = p; - (*plist)->count = 0; - } else { - (*plist)->tail->next = p; - (*plist)->count++; - } - (*plist)->tail = p; + struct string_list *p = xmalloc (sizeof (*p)); + p->str = str; + p->next = NULL; + + if (!*plist) + { + *plist = xmalloc (sizeof (**plist)); + (*plist)->head = NULL; + } + + if ((*plist)->head == NULL) + { + (*plist)->head = p; + (*plist)->count = 0; + } + else + { + (*plist)->tail->next = p; + (*plist)->count++; + } + (*plist)->tail = p; } void -slist_append(SLIST **pdst, SLIST *src) +slist_append (SLIST **pdst, SLIST *src) { - struct string_list *tail; - - if (!*pdst) { - *pdst = xmalloc(sizeof(**pdst)); - (*pdst)->head = NULL; - (*pdst)->count = 0; - } + struct string_list *tail; + + if (!*pdst) + { + *pdst = xmalloc (sizeof (**pdst)); + (*pdst)->head = NULL; + (*pdst)->count = 0; + } + + if ((*pdst)->head = NULL) + (*pdst)->head = src->head; + + for (tail = src->tail; tail->next; tail = tail->next) + ; - if ((*pdst)->head = NULL) - (*pdst)->head = src->head; - - for (tail = src->tail; tail->next; tail = tail->next) - ; - - (*pdst)->tail = tail; - (*pdst)->count += src->count; + (*pdst)->tail = tail; + (*pdst)->count += src->count; } char * -slist_member(SLIST *plist, char *name) +slist_member (SLIST *plist, char *name) { - struct string_list *p; - - if (plist) - for (p = plist->head; p; p = p->next) - if (p->str && strcmp(p->str, name) == 0) - return p->str; - return NULL; + struct string_list *p; + + if (plist) + for (p = plist->head; p; p = p->next) + if (p->str && strcmp (p->str, name) == 0) + return p->str; + return NULL; } void -slist_destroy(SLIST **plist) +slist_destroy (SLIST **plist) { - struct string_list *p; - if (!plist || !*plist) - return; - p = (*plist)->head; - while (p) { - struct string_list *next = p->next; - free(p); - p = next; - } - free(*plist); - *plist = NULL; + struct string_list *p; + if (!plist || !*plist) + return; + p = (*plist)->head; + while (p) + { + struct string_list *next = p->next; + free (p); + p = next; + } + free (*plist); + *plist = NULL; } - - -typedef struct { - char *name; - SLIST *exp; +typedef struct +{ + char *name; + SLIST *exp; } ALIAS; struct obstack alias_stk; unsigned alias_count; ALIAS *aliases; void -regalias(char *name, SLIST *exp) +regalias (char *name, SLIST *exp) { - ALIAS a; - a.name = name; - a.exp = exp; - obstack_grow(&alias_stk, &a, sizeof a); - alias_count++; + ALIAS a; + a.name = name; + a.exp = exp; + obstack_grow (&alias_stk, &a, sizeof a); + alias_count++; } void -begin_aliases() +begin_aliases () { - obstack_init(&alias_stk); + obstack_init (&alias_stk); } static int -alias_cmp(const void *a, const void *b) +alias_cmp (const void *a, const void *b) { - return strcmp(((ALIAS*)a)->name, ((ALIAS*)b)->name); + return strcmp (((ALIAS *) a)->name, ((ALIAS *) b)->name); } static int -alias_cmp2(const void *a, const void *b) +alias_cmp2 (const void *a, const void *b) { - char *aname = ((ALIAS*)a)->name; - char *bname = ((ALIAS*)b)->name; - int rc; - int alen; - int blen; - char *p; - - if ((p = strchr(aname, '@')) && slist_member(cw_list, p+1)) - alen = p - aname; - else - alen = strlen(aname); - - if ((p = strchr(bname, '@')) && slist_member(cw_list, p+1)) - blen = p - bname; - else - blen = strlen(bname); - - if (alen == blen) - return memcmp(aname, bname, alen); - - return strcmp(aname, bname); + char *aname = ((ALIAS *) a)->name; + char *bname = ((ALIAS *) b)->name; + int rc; + int alen; + int blen; + char *p; + + if ((p = strchr (aname, '@')) && slist_member (cw_list, p + 1)) + alen = p - aname; + else + alen = strlen (aname); + + if ((p = strchr (bname, '@')) && slist_member (cw_list, p + 1)) + blen = p - bname; + else + blen = strlen (bname); + + if (alen == blen) + return memcmp (aname, bname, alen); + + return strcmp (aname, bname); } void -end_aliases() +end_aliases () { - int i; - aliases = obstack_finish(&alias_stk); - qsort(aliases, alias_count, sizeof aliases[0], alias_cmp); - for (i = 1; i < alias_count; i++) - if (alias_cmp(aliases + i - 1, aliases + i) == 0) - error("alias `%s' multiply defined", aliases[i].name); + int i; + aliases = obstack_finish (&alias_stk); + qsort (aliases, alias_count, sizeof aliases[0], alias_cmp); + for (i = 1; i < alias_count; i++) + if (alias_cmp (aliases + i - 1, aliases + i) == 0) + { + error (0, 0, "alias `%s' multiply defined", aliases[i].name); + error_count++; + } } int -find_alias(char *name) +find_alias (char *name) { - ALIAS a, *p; + ALIAS a, *p; - if (!name) - return -1; - a.name = name; - p = bsearch(&a, aliases, alias_count, sizeof aliases[0], alias_cmp2); - return p ? p - aliases : -1; + if (!name) + return -1; + a.name = name; + p = bsearch (&a, aliases, alias_count, sizeof aliases[0], alias_cmp2); + return p ? p - aliases : -1; } static void -alias_setbit(unsigned *r, unsigned rowsize, unsigned row, unsigned col) +alias_setbit (unsigned *r, unsigned rowsize, unsigned row, unsigned col) { - SETBIT(r + rowsize * row, col); + SETBIT (r + rowsize * row, col); } static int -alias_bitisset(unsigned *r, unsigned rowsize, unsigned row, unsigned col) +alias_bitisset (unsigned *r, unsigned rowsize, unsigned row, unsigned col) { - return BITISSET(r + rowsize * row, col); + return BITISSET (r + rowsize * row, col); } void -mark_connected(unsigned *r, unsigned size) +mark_connected (unsigned *r, unsigned size) { - int i; - - for (i = 0; i < alias_count; i++) { - if (aliases[i].exp) { - struct string_list *p; - for (p = aliases[i].exp->head; p; p = p->next) { - int n = find_alias(p->str); - if (n >= 0) - alias_setbit(r, size, i, n); - } - } + int i; + + for (i = 0; i < alias_count; i++) + { + if (aliases[i].exp) + { + struct string_list *p; + for (p = aliases[i].exp->head; p; p = p->next) + { + int n = find_alias (p->str); + if (n >= 0) + alias_setbit (r, size, i, n); + } } + } } void -check_circular_deps(unsigned *r, unsigned size) +check_circular_deps (unsigned *r, unsigned size) { - int i; - - for (i = 0; i < alias_count; i++) { - if (alias_bitisset(r, size, i, i)) - error("%s: circular dependency", aliases[i].name); + int i; + + for (i = 0; i < alias_count; i++) + { + if (alias_bitisset (r, size, i, i)) + { + error (0, 0, "%s: circular dependency", aliases[i].name); + error_count++; } + } } void -check_aliases() +check_aliases () { - size_t size; - unsigned *r; - - /* Allocate matrix */ - size = (alias_count + BITS_PER_WORD - 1) / BITS_PER_WORD; - r = xmalloc(alias_count*size*sizeof(*r)); - memset(r, 0, alias_count*size*sizeof(*r)); + size_t size; + unsigned *r; + + /* Allocate matrix */ + size = (alias_count + BITS_PER_WORD - 1) / BITS_PER_WORD; + r = xmalloc (alias_count * size * sizeof (*r)); + memset (r, 0, alias_count * size * sizeof (*r)); - /* First pass: mark directly connected entries */ - mark_connected(r, size); + /* First pass: mark directly connected entries */ + mark_connected (r, size); - /* Compute transitive closure of the matrix r */ - TC(r, alias_count); + /* Compute transitive closure of the matrix r */ + TC (r, alias_count); - /* Third pass: check for circular deps */ - check_circular_deps(r, size); + /* Third pass: check for circular deps */ + check_circular_deps (r, size); - if (verbose) - printf("%lu aliases\n", alias_count); + if (verbose) + printf ("%lu aliases\n", alias_count); } diff --git a/ckaliases.h b/ckaliases.h index 8d6546d..d3e053c 100644 --- a/ckaliases.h +++ b/ckaliases.h @@ -5,45 +5,67 @@ under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#define obstack_chunk_alloc malloc +#define obstack_chunk_free free +#include <obstack.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include "getopt.h" +#include "progname.h" +#include "error.h" +#include "xalloc.h" + extern char *file_name; extern int line_num; +extern int error_count; -void init_lex(); -void lex_debug(int n); -void openaliases(char *name); -void openaliases_prefix(char *prefix, char *name); +void init_lex (); +void lex_debug (int n); +void openaliases (char *name); +void openaliases_prefix (char *prefix, char *name); -struct string_list { - struct string_list *next; - char *str; +struct string_list +{ + struct string_list *next; + char *str; }; -typedef struct slist { - struct string_list *head, *tail; - int count; +typedef struct slist +{ + struct string_list *head, *tail; + int count; } SLIST; -void slist_add(SLIST **plist, char *str); -void slist_append(SLIST **pdst, SLIST *src); -char *slist_member(SLIST *plist, char *name); -void slist_destroy(SLIST **plist); - -void read_include(SLIST **plist, char *name); +void slist_add (SLIST ** plist, char *str); +void slist_append (SLIST ** pdst, SLIST * src); +char *slist_member (SLIST * plist, char *name); +void slist_destroy (SLIST ** plist); -void regalias(char *name, SLIST *exp); -void begin_aliases(void); -void end_aliases(void); +void read_include (SLIST ** plist, char *name); -void error(char *fmt, ...); +void regalias (char *name, SLIST * exp); +void begin_aliases (void); +void end_aliases (void); extern SLIST *cw_list; extern int verbose; @@ -1,268 +1,276 @@ %{ /* ckaliases - verify syntax of sendmail-style alias files - Copyright (C) 2005 Sergey Poznyakoff + Copyright (C) 2005, 2007 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <getopt.h> -#include <errno.h> #include "ckaliases.h" SLIST *cw_list; /* List of domain names pertaining to Sendmail 'w' class */ -static int restricted; /* prohibit use of `special' aliases (pipes, file redirections - and includes */ -int verbose; /* Verbose mode */ -static int error_count; /* Number of errors detected so far */ +static int restricted; /* prohibit use of `special' aliases (pipes, + file redirections and includes */ +int verbose; /* Verbose mode */ +int error_count; /* Number of errors detected so far */ %} %union { - char *string; - SLIST *slist; + char *string; + SLIST *slist; }; %token <string> IDENT EMAIL STRING LHS %token CONT %token EOL %token INCLUDE %type <string> string lhs %type <slist> rhs emails email %% input : list ; list : alias | list EOL alias | list error EOL { - yyclearin; - yyerrok; + yyclearin; + yyerrok; } ; alias : /* empty */ | lhs rhs { - regalias($1, $2); + regalias ($1, $2); } ; lhs : LHS ':' ; rhs : emails | rhs CONT emails { - slist_append(&$1, $3); - $$ = $1; + slist_append (&$1, $3); + $$ = $1; } ; emails: email | emails ',' email { - slist_append(&$1, $3); - $$ = $1; + slist_append (&$1, $3); + $$ = $1; } ; email : string { - if (restricted && ($1[0] == '|' || $1[0] == '/')) { - yyerror("Construct not allowed"); - YYERROR; - } - $$ = NULL; - slist_add(&$$, $1); + if (restricted && ($1[0] == '|' || $1[0] == '/')) + { + yyerror ("Construct not allowed"); + YYERROR; + } + $$ = NULL; + slist_add (&$$, $1); } | EMAIL { - $$ = NULL; - slist_add(&$$, $1); + $$ = NULL; + slist_add (&$$, $1); } | INCLUDE string { - if (restricted) { - yyerror("Include statement is not allowed"); - YYERROR; - } - $$ = NULL; - read_include(&$$, $2); + if (restricted) + { + yyerror ("Include statement is not allowed"); + YYERROR; + } + $$ = NULL; + read_include (&$$, $2); } ; string: IDENT | STRING ; %% -void -error(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); - error_count++; -} - -yyerror(char *s) +int +yyerror (char *s) { - error("%s:%d: %s", file_name, line_num, s); + error_at_line (0, 0, file_name, line_num, "%s", s); + error_count++; } - void -usage() +usage () { - printf("usage: ckaliases [OPTIONS] [FILES...]\n"); - printf("OPTIONS and FILES may be interspered.\n"); - printf("Valid options are:\n"); - printf(" -d SPEC Set debug level. SPEC consists of the following\n"); - printf(" letters:\n"); - printf(" y enable parser debugging\n"); - printf(" l enable lexical analizer debugging\n"); - printf(" Upper-case variants are also accepted. Prepending\n"); - printf(" a letter with '-' reverts its sense\n"); - printf(" -h Display this help list\n"); - printf(" -r Restrict alias file syntax to aliases only (i.e.\n"); - printf(" prohibit use of pipes and file redirections\n"); - printf(" -u Revert the effect of the previous -r option\n"); - printf(" -v Verbose mode\n"); - printf(" -w FILE Read contents of Sendmail `w' class from the given\n"); - printf(" file.\n"); + printf ("usage: ckaliases [OPTIONS] [FILES...]\n"); + printf ("OPTIONS and FILES may be interspered.\n"); + printf ("Valid options are:\n"); + printf (" -d,--debug=SPEC Set debug level. SPEC consists of the following\n"); + printf (" letters:\n"); + printf (" y enable parser debugging\n"); + printf (" l enable lexical analizer debugging\n"); + printf (" Upper-case variants are also accepted. Prepending\n"); + printf (" a letter with '-' reverts its sense\n"); + printf (" -f, --files-from=FILE\n"); + printf (" Read names of alias files from FILE\n"); + printf (" -h, --help Display this help list\n"); + printf (" -r, --restrict Restrict alias file syntax to aliases only (i.e.\n"); + printf (" prohibit use of pipes and file redirections\n"); + printf (" -u, --unrestrict Revert the effect of the previous -r option\n"); + printf (" -v, --verbose Verbose mode\n"); + printf (" -V, --version print program version and exit\n"); + printf (" -w FILE Read contents of Sendmail `w' class from the given\n"); + printf (" file.\n"); } +struct option options[] = { + { "debug", required_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "restrict", no_argument, NULL, 'r' }, + { "unrestrict", no_argument, NULL, 'u' }, + { "verbose", no_argument, NULL, 'v' }, + { "files-from", required_argument, NULL, 'f' }, + { NULL } +}; int -main(int argc, char **argv) +main (int argc, char **argv) { - char *p; - int c; - 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; + char *p; + int c; + 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; - begin_aliases(); - init_lex(); - while ((c = getopt(argc, argv, "-d:f:hp:ruvw:")) != EOF) { - switch (c) { - case 1: - if (!cw_list) - read_include(&cw_list, cwfile); - openaliases(optarg); - yyparse(); - file_count++; - break; + begin_aliases (); + init_lex (); + program_name = argv[0]; + while ((c = getopt_long (argc, argv, "-d:f:hp:ruvw:", options, NULL)) != EOF) + { + switch (c) + { + case 1: + if (!cw_list) + read_include (&cw_list, cwfile); + openaliases (optarg); + yyparse (); + file_count++; + break; - case 'd': - for (p = optarg; *p; p++) { - switch (*p) { - case '-': - true = 0; - break; - case 'y': - case 'Y': - yydebug = true; - true = 1; - break; - case 'l': - case 'L': - lex_debug(true); - true = 1; - break; - default: - fprintf(stderr, "%s: unknown debug option %c\n", - argv[0], *p); - exit(1); - } - } - break; - - case 'f': - if (!cw_list) - read_include(&cw_list, cwfile); - file_list = NULL; - read_include(&file_list, optarg); - for (s = file_list->head; s; s = s->next) { - openaliases_prefix(optarg, s->str); - yyparse(); - file_count++; - } - slist_destroy(&file_list); - break; - - case 'h': - usage(); - exit(0); - - case 'r': - restricted = 1; - break; - - case 'u': - restricted = 0; - break; + case 'd': + for (p = optarg; *p; p++) + { + switch (*p) + { + case '-': + true = 0; + break; + + case 'y': + case 'Y': + yydebug = true; + true = 1; + break; + + case 'l': + case 'L': + lex_debug (true); + true = 1; + break; - case 'v': - verbose++; - break; - - case 'w': - if (file_count) { - error("-w must be used before first non-option argument"); - exit(1); - } - cwfile = optarg; - break; - default: - exit(1); + error (1, 0, "%s: unknown debug option %c", argv[0]); } - } + } + break; + + case 'f': + if (!cw_list) + read_include (&cw_list, cwfile); + file_list = NULL; + read_include (&file_list, optarg); + for (s = file_list->head; s; s = s->next) + { + openaliases_prefix (optarg, s->str); + yyparse (); + file_count++; + } + slist_destroy (&file_list); + break; + + case 'h': + usage (); + exit (0); - argc -= optind; - argv += optind; + case 'r': + restricted = 1; + break; + + case 'u': + restricted = 0; + break; + + case 'v': + verbose++; + break; - if (!cw_list) - read_include(&cw_list, cwfile); - while (argc--) { - openaliases(*argv++); - yyparse(); - file_count++; + case 'V': + gsc_version ("ckaliases"); + exit (0); + + case 'w': + if (file_count) + error (1, 0, "-w must be used before first non-option argument"); + cwfile = optarg; + break; + + default: + exit (1); } + } + + argc -= optind; + argv += optind; + + if (!cw_list) + read_include (&cw_list, cwfile); + while (argc--) + { + openaliases (*argv++); + yyparse (); + file_count++; + } - if (!file_count) { - error("no files specified"); - exit(1); - } + if (!file_count) + error (1, 0, "no files specified"); - if (verbose) - printf("%d files\n", file_count); - end_aliases(); - check_aliases(); - if (verbose) - printf("%lu errors\n", error_count); - exit(error_count!=0); + if (verbose) + printf ("%d files\n", file_count); + end_aliases (); + check_aliases (); + if (verbose) + printf ("%lu errors\n", error_count); + exit (error_count!=0); } @@ -1,228 +1,211 @@ %{ /* ckaliases - verify syntax of sendmail-style alias files - Copyright (C) 2005 Sergey Poznyakoff + Copyright (C) 2005, 2007 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#define obstack_chunk_alloc malloc -#define obstack_chunk_free free -#include <obstack.h> #include "ckaliases.h" #include "gram.h" -static void line_begin(void); -static void line_add(char *text, size_t len); -static void line_add_unescape(char *text, size_t len); -static void line_finish(void); +static void line_begin (void); +static void line_add (char *text, size_t len); +static void line_add_unescape (char *text, size_t len); +static void line_finish (void); struct obstack string_stk; char *file_name; int line_num; %} %x STR IDENT [a-zA-Z0-9_\-+\./]+ WS [ \t] SPEC [:@\\] %% /* Comments */ #.*\n { line_num++; return EOL; } /* White space */ ^{WS}+\n { line_num++; return EOL; } {WS}+ ; /* Names and emails */ :include: return INCLUDE; ^{IDENT} { - line_begin(); - line_add(yytext, yyleng); - line_finish(); + line_begin (); + line_add (yytext, yyleng); + line_finish (); return LHS; } {IDENT}@{IDENT} { - line_begin(); - line_add(yytext, yyleng); - line_finish(); + line_begin (); + line_add (yytext, yyleng); + line_finish (); return EMAIL; } -{IDENT} { line_begin(); - line_add(yytext, yyleng); - line_finish(); +{IDENT} { line_begin (); + line_add (yytext, yyleng); + line_finish (); return IDENT; } /* Quoted strings */ -\"[^\\"\n]*\" { line_begin(); - line_add(yytext, yyleng); - line_finish(); +\"[^\\"\n]*\" { line_begin (); + line_add (yytext, yyleng); + line_finish (); return STRING; } -\"[^\\"\n]*\\. { BEGIN(STR); - line_begin(); - line_add_unescape(yytext + 1, yyleng - 1); } -<STR>[^\\"\n]*\\. { line_add_unescape(yytext, yyleng); } -<STR>[^\\"\n]*\" { BEGIN(INITIAL); +\"[^\\"\n]*\\. { BEGIN (STR); + line_begin (); + line_add_unescape (yytext + 1, yyleng - 1); } +<STR>[^\\"\n]*\\. { line_add_unescape (yytext, yyleng); } +<STR>[^\\"\n]*\" { BEGIN (INITIAL); if (yyleng > 1) - line_add(yytext, yyleng - 1); - line_finish(); + line_add (yytext, yyleng - 1); + line_finish (); return STRING; } /* Other characters */ {SPEC} return yytext[0]; \\\n { line_num++; } \n{WS}+/[^ \t\n] { line_num++; return CONT; } \n { line_num++; return EOL; } , return yytext[0]; -. { char *p; - asprintf(&p, - "Stray character %03o in alias file", yytext[0]); - yyerror(p); - free (p); } +. { error_at_line (0, 0, file_name, line_num, + "Stray character %03o in alias file", yytext[0]); + error_count++; } %% int -yywrap() +yywrap () { - fclose(yyin); - return 1; + fclose (yyin); + return 1; } static char escape_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t"; int unescape_char (int c) { char *p; for (p = escape_transtab; *p; p += 2) { if (*p == c) return p[1]; } return c; } |