summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2007-08-24 20:38:54 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2007-08-24 20:38:54 (GMT)
commitab736c0b1959c6c605c210d5fd9665bfe002042e (patch) (unidiff)
treee23a335c9a0e81505c9c06ba089e776200e1d443
parented4ec220dcfcba29a7fc8ff161999c32a98e4430 (diff)
downloadalck-ab736c0b1959c6c605c210d5fd9665bfe002042e.tar.gz
alck-ab736c0b1959c6c605c210d5fd9665bfe002042e.tar.bz2
* lib/version.c: New file
* lib/gsc.h (gsc_version): New function * cvs/Makefile.am, ckaliases/Makefile.am, wydawca/Makefile.am, lib/Makefile.am, jabberd/Makefile.am: Fix include dirs * ckaliases/ckaliases.c, ckaliases/lex.l, ckaliases/ckaliases.h, ckaliases/gram.y: Use long options. Implement --version * wydawca/wydawca.c, jabberd/main.c: Use gsc_version to display program version. * doc/gsc.texi: Update * bootstrap: Add vasprintf git-svn-id: file:///svnroot/gsc/trunk@289 d2de0444-eb31-0410-8365-af798a554d48
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile.am3
-rw-r--r--ckaliases.c416
-rw-r--r--ckaliases.h62
-rw-r--r--gram.y336
-rw-r--r--lex.l213
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
@@ -14,9 +14,10 @@
14# You should have received a copy of the GNU General Public License 14# You should have received a copy of the GNU General Public License
15# along with GSC. If not, see <http://www.gnu.org/licenses/>. 15# along with GSC. If not, see <http://www.gnu.org/licenses/>.
16 16
17AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=ckaliases
18AM_YFLAGS=-vtd 17AM_YFLAGS=-vtd
19AM_LFLAGS=-d 18AM_LFLAGS=-d
20sbin_PROGRAMS=ckaliases 19sbin_PROGRAMS=ckaliases
21noinst_HEADERS=gram.h 20noinst_HEADERS=gram.h
22ckaliases_SOURCES=gram.y lex.l ckaliases.c ckaliases.h 21ckaliases_SOURCES=gram.y lex.l ckaliases.c ckaliases.h
22LDADD=../lib/libgsc.a ../gnu/libgnu.a
23INCLUDES = -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,5 +1,5 @@
1/* ckaliases - verify syntax of sendmail-style alias files 1/* ckaliases - verify syntax of sendmail-style alias files
2 Copyright (C) 2005 Sergey Poznyakoff 2 Copyright (C) 2005, 2007 Sergey Poznyakoff
3 3
4 This program is free software; you can redistribute it and/or modify it 4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the 5 under the terms of the GNU General Public License as published by the
@@ -14,28 +14,8 @@
14 You should have received a copy of the GNU General Public License along 14 You should have received a copy of the GNU General Public License along
15 with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 with this program. If not, see <http://www.gnu.org/licenses/>. */
16 16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <stdio.h>
21#include <stdlib.h>
22#define obstack_chunk_alloc malloc
23 #define obstack_chunk_free free
24#include <obstack.h>
25#include "ckaliases.h" 17#include "ckaliases.h"
26 18
27void *
28xmalloc(size_t size)
29{
30 void *p = malloc(size);
31 if (!p) {
32 fprintf(stderr, "not enough memory\n");
33 exit(1);
34 }
35 return p;
36}
37
38
39#ifndef CHAR_BIT 19#ifndef CHAR_BIT
40# define CHAR_BIT 8 20# define CHAR_BIT 8
41#endif 21#endif
@@ -51,131 +31,141 @@ xmalloc(size_t size)
51 to be the transitive closure of what was given. */ 31 to be the transitive closure of what was given. */
52 32
53void 33void
54TC(unsigned *R, int n) 34TC (unsigned *R, int n)
55{ 35{
56 register int rowsize; 36 register int rowsize;
57 register unsigned mask; 37 register unsigned mask;
58 register unsigned *rowj; 38 register unsigned *rowj;
59 register unsigned *rp; 39 register unsigned *rp;
60 register unsigned *rend; 40 register unsigned *rend;
61 register unsigned *ccol; 41 register unsigned *ccol;
62 42
63 unsigned *relend; 43 unsigned *relend;
64 unsigned *cword; 44 unsigned *cword;
65 unsigned *rowi; 45 unsigned *rowi;
66 46
67 rowsize = WORDSIZE(n) * sizeof(unsigned); 47 rowsize = WORDSIZE (n) * sizeof (unsigned);
68 relend = (unsigned *) ((char *) R + (n * rowsize)); 48 relend = (unsigned *) ((char *) R + (n * rowsize));
69 49
70 cword = R; 50 cword = R;
71 mask = 1; 51 mask = 1;
72 rowi = R; 52 rowi = R;
73 while (rowi < relend) { 53 while (rowi < relend)
74 ccol = cword; 54 {
75 rowj = R; 55 ccol = cword;
76 56 rowj = R;
77 while (rowj < relend) { 57
78 if (*ccol & mask) { 58 while (rowj < relend)
79 rp = rowi; 59 {
80 rend = (unsigned *) ((char *) rowj + rowsize); 60 if (*ccol & mask)
81 61 {
82 while (rowj < rend) 62 rp = rowi;
83 *rowj++ |= *rp++; 63 rend = (unsigned *) ((char *) rowj + rowsize);
84 } else { 64
85 rowj = (unsigned *) ((char *) rowj + rowsize); 65 while (rowj < rend)
86 } 66 *rowj++ |= *rp++;
87 67 }
88 ccol = (unsigned *) ((char *) ccol + rowsize); 68 else
89 } 69 {
90 70 rowj = (unsigned *) ((char *) rowj + rowsize);
91 mask <<= 1; 71 }
92 if (mask == 0) { 72
93 mask = 1; 73 ccol = (unsigned *) ((char *) ccol + rowsize);
94 cword++; 74 }
95 }
96 rowi = (unsigned *) ((char *) rowi + rowsize);
97 }
98}
99 75
76 mask <<= 1;
77 if (mask == 0)
78 {
79 mask = 1;
80 cword++;
81 }
82 rowi = (unsigned *) ((char *) rowi + rowsize);
83 }
84}
100 85
101 86
102void 87void
103slist_add(SLIST **plist, char *str) 88slist_add (SLIST **plist, char *str)
104{ 89{
105 struct string_list *p = xmalloc(sizeof(*p)); 90 struct string_list *p = xmalloc (sizeof (*p));
106 p->str = str; 91 p->str = str;
107 p->next = NULL; 92 p->next = NULL;
108 93
109 if (!*plist) { 94 if (!*plist)
110 *plist = xmalloc(sizeof(**plist)); 95 {
111 (*plist)->head = NULL; 96 *plist = xmalloc (sizeof (**plist));
112 } 97 (*plist)->head = NULL;
113 98 }
114 if ((*plist)->head == NULL) { 99
115 (*plist)->head = p; 100 if ((*plist)->head == NULL)
116 (*plist)->count = 0; 101 {
117 } else { 102 (*plist)->head = p;
118 (*plist)->tail->next = p; 103 (*plist)->count = 0;
119 (*plist)->count++; 104 }
120 } 105 else
121 (*plist)->tail = p; 106 {
107 (*plist)->tail->next = p;
108 (*plist)->count++;
109 }
110 (*plist)->tail = p;
122} 111}
123 112
124void 113void
125slist_append(SLIST **pdst, SLIST *src) 114slist_append (SLIST **pdst, SLIST *src)
126{ 115{
127 struct string_list *tail; 116 struct string_list *tail;
128 117
129 if (!*pdst) { 118 if (!*pdst)
130 *pdst = xmalloc(sizeof(**pdst)); 119 {
131 (*pdst)->head = NULL; 120 *pdst = xmalloc (sizeof (**pdst));
132 (*pdst)->count = 0; 121 (*pdst)->head = NULL;
133 } 122 (*pdst)->count = 0;
123 }
124
125 if ((*pdst)->head = NULL)
126 (*pdst)->head = src->head;
127
128 for (tail = src->tail; tail->next; tail = tail->next)
129 ;
134 130
135 if ((*pdst)->head = NULL) 131 (*pdst)->tail = tail;
136 (*pdst)->head = src->head; 132 (*pdst)->count += src->count;
137
138 for (tail = src->tail; tail->next; tail = tail->next)
139 ;
140
141 (*pdst)->tail = tail;
142 (*pdst)->count += src->count;
143} 133}
144 134
145char * 135char *
146slist_member(SLIST *plist, char *name) 136slist_member (SLIST *plist, char *name)
147{ 137{
148 struct string_list *p; 138 struct string_list *p;
149 139
150 if (plist) 140 if (plist)
151 for (p = plist->head; p; p = p->next) 141 for (p = plist->head; p; p = p->next)
152 if (p->str && strcmp(p->str, name) == 0) 142 if (p->str && strcmp (p->str, name) == 0)
153 return p->str; 143 return p->str;
154 return NULL; 144 return NULL;
155} 145}
156 146
157void 147void
158slist_destroy(SLIST **plist) 148slist_destroy (SLIST **plist)
159{ 149{
160 struct string_list *p; 150 struct string_list *p;
161 if (!plist || !*plist) 151 if (!plist || !*plist)
162 return; 152 return;
163 p = (*plist)->head; 153 p = (*plist)->head;
164 while (p) { 154 while (p)
165 struct string_list *next = p->next; 155 {
166 free(p); 156 struct string_list *next = p->next;
167 p = next; 157 free (p);
168 } 158 p = next;
169 free(*plist); 159 }
170 *plist = NULL; 160 free (*plist);
161 *plist = NULL;
171} 162}
172
173
174 163
175 164
176typedef struct { 165typedef struct
177 char *name; 166{
178 SLIST *exp; 167 char *name;
168 SLIST *exp;
179} ALIAS; 169} ALIAS;
180 170
181struct obstack alias_stk; 171struct obstack alias_stk;
@@ -183,139 +173,149 @@ unsigned alias_count;
183ALIAS *aliases; 173ALIAS *aliases;
184 174
185void 175void
186regalias(char *name, SLIST *exp) 176regalias (char *name, SLIST *exp)
187{ 177{
188 ALIAS a; 178 ALIAS a;
189 a.name = name; 179 a.name = name;
190 a.exp = exp; 180 a.exp = exp;
191 obstack_grow(&alias_stk, &a, sizeof a); 181 obstack_grow (&alias_stk, &a, sizeof a);
192 alias_count++; 182 alias_count++;
193} 183}
194 184
195void 185void
196begin_aliases() 186begin_aliases ()
197{ 187{
198 obstack_init(&alias_stk); 188 obstack_init (&alias_stk);
199} 189}
200 190
201static int 191static int
202alias_cmp(const void *a, const void *b) 192alias_cmp (const void *a, const void *b)
203{ 193{
204 return strcmp(((ALIAS*)a)->name, ((ALIAS*)b)->name); 194 return strcmp (((ALIAS *) a)->name, ((ALIAS *) b)->name);
205} 195}
206 196
207static int 197static int
208alias_cmp2(const void *a, const void *b) 198alias_cmp2 (const void *a, const void *b)
209{ 199{
210 char *aname = ((ALIAS*)a)->name; 200 char *aname = ((ALIAS *) a)->name;
211 char *bname = ((ALIAS*)b)->name; 201 char *bname = ((ALIAS *) b)->name;
212 int rc; 202 int rc;
213 int alen; 203 int alen;
214 int blen; 204 int blen;
215 char *p; 205 char *p;
216 206
217 if ((p = strchr(aname, '@')) && slist_member(cw_list, p+1)) 207 if ((p = strchr (aname, '@')) && slist_member (cw_list, p + 1))
218 alen = p - aname; 208 alen = p - aname;
219 else 209 else
220 alen = strlen(aname); 210 alen = strlen (aname);
221 211
222 if ((p = strchr(bname, '@')) && slist_member(cw_list, p+1)) 212 if ((p = strchr (bname, '@')) && slist_member (cw_list, p + 1))
223 blen = p - bname; 213 blen = p - bname;
224 else 214 else
225 blen = strlen(bname); 215 blen = strlen (bname);
226 216
227 if (alen == blen) 217 if (alen == blen)
228 return memcmp(aname, bname, alen); 218 return memcmp (aname, bname, alen);
229 219
230 return strcmp(aname, bname); 220 return strcmp (aname, bname);
231} 221}
232 222
233void 223void
234end_aliases() 224end_aliases ()
235{ 225{
236 int i; 226 int i;
237 aliases = obstack_finish(&alias_stk); 227 aliases = obstack_finish (&alias_stk);
238 qsort(aliases, alias_count, sizeof aliases[0], alias_cmp); 228 qsort (aliases, alias_count, sizeof aliases[0], alias_cmp);
239 for (i = 1; i < alias_count; i++) 229 for (i = 1; i < alias_count; i++)
240 if (alias_cmp(aliases + i - 1, aliases + i) == 0) 230 if (alias_cmp (aliases + i - 1, aliases + i) == 0)
241 error("alias `%s' multiply defined", aliases[i].name); 231 {
232 error (0, 0, "alias `%s' multiply defined", aliases[i].name);
233 error_count++;
234 }
242} 235}
243 236
244 237
245int 238int
246find_alias(char *name) 239find_alias (char *name)
247{ 240{
248 ALIAS a, *p; 241 ALIAS a, *p;
249 242
250 if (!name) 243 if (!name)
251 return -1; 244 return -1;
252 a.name = name; 245 a.name = name;
253 p = bsearch(&a, aliases, alias_count, sizeof aliases[0], alias_cmp2); 246 p = bsearch (&a, aliases, alias_count, sizeof aliases[0], alias_cmp2);
254 return p ? p - aliases : -1; 247 return p ? p - aliases : -1;
255} 248}
256 249
257 250
258static void 251static void
259alias_setbit(unsigned *r, unsigned rowsize, unsigned row, unsigned col) 252alias_setbit (unsigned *r, unsigned rowsize, unsigned row, unsigned col)
260{ 253{
261 SETBIT(r + rowsize * row, col); 254 SETBIT (r + rowsize * row, col);
262} 255}
263 256
264static int 257static int
265alias_bitisset(unsigned *r, unsigned rowsize, unsigned row, unsigned col) 258alias_bitisset (unsigned *r, unsigned rowsize, unsigned row, unsigned col)
266{ 259{
267 return BITISSET(r + rowsize * row, col); 260 return BITISSET (r + rowsize * row, col);
268} 261}
269 262
270 263
271void 264void
272mark_connected(unsigned *r, unsigned size) 265mark_connected (unsigned *r, unsigned size)
273{ 266{
274 int i; 267 int i;
275 268
276 for (i = 0; i < alias_count; i++) { 269 for (i = 0; i < alias_count; i++)
277 if (aliases[i].exp) { 270 {
278 struct string_list *p; 271 if (aliases[i].exp)
279 for (p = aliases[i].exp->head; p; p = p->next) { 272 {
280 int n = find_alias(p->str); 273 struct string_list *p;
281 if (n >= 0) 274 for (p = aliases[i].exp->head; p; p = p->next)
282 alias_setbit(r, size, i, n); 275 {
283 } 276 int n = find_alias (p->str);
284 } 277 if (n >= 0)
278 alias_setbit (r, size, i, n);
279 }
285 } 280 }
281 }
286} 282}
287 283
288void 284void
289check_circular_deps(unsigned *r, unsigned size) 285check_circular_deps (unsigned *r, unsigned size)
290{ 286{
291 int i; 287 int i;
292 288
293 for (i = 0; i < alias_count; i++) { 289 for (i = 0; i < alias_count; i++)
294 if (alias_bitisset(r, size, i, i)) 290 {
295 error("%s: circular dependency", aliases[i].name); 291 if (alias_bitisset (r, size, i, i))
292 {
293 error (0, 0, "%s: circular dependency", aliases[i].name);
294 error_count++;
296 } 295 }
296 }
297} 297}
298 298
299void 299void
300check_aliases() 300check_aliases ()
301{ 301{
302 size_t size; 302 size_t size;
303 unsigned *r; 303 unsigned *r;
304 304
305 /* Allocate matrix */ 305 /* Allocate matrix */
306 size = (alias_count + BITS_PER_WORD - 1) / BITS_PER_WORD; 306 size = (alias_count + BITS_PER_WORD - 1) / BITS_PER_WORD;
307 r = xmalloc(alias_count*size*sizeof(*r)); 307 r = xmalloc (alias_count * size * sizeof (*r));
308 memset(r, 0, alias_count*size*sizeof(*r)); 308 memset (r, 0, alias_count * size * sizeof (*r));
309 309
310 /* First pass: mark directly connected entries */ 310 /* First pass: mark directly connected entries */
311 mark_connected(r, size); 311 mark_connected (r, size);
312 312
313 /* Compute transitive closure of the matrix r */ 313 /* Compute transitive closure of the matrix r */
314 TC(r, alias_count); 314 TC (r, alias_count);
315 315
316 /* Third pass: check for circular deps */ 316 /* Third pass: check for circular deps */
317 check_circular_deps(r, size); 317 check_circular_deps (r, size);
318 318
319 if (verbose) 319 if (verbose)
320 printf("%lu aliases\n", alias_count); 320 printf ("%lu aliases\n", alias_count);
321} 321}
diff --git a/ckaliases.h b/ckaliases.h
index 8d6546d..d3e053c 100644
--- a/ckaliases.h
+++ b/ckaliases.h
@@ -14,36 +14,58 @@
14 You should have received a copy of the GNU General Public License along 14 You should have received a copy of the GNU General Public License along
15 with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 with this program. If not, see <http://www.gnu.org/licenses/>. */
16 16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <stdio.h>
21#include <stdlib.h>
22#define obstack_chunk_alloc malloc
23#define obstack_chunk_free free
24#include <obstack.h>
25#include <stdio.h>
26#include <stdlib.h>
27 #include <stdarg.h>
28#include <unistd.h>
29#include <sys/file.h>
30#include <sys/stat.h>
31#include <errno.h>
32#include <string.h>
33#include "getopt.h"
34#include "progname.h"
35#include "error.h"
36#include "xalloc.h"
37
17extern char *file_name; 38extern char *file_name;
18extern int line_num; 39extern int line_num;
40extern int error_count;
19 41
20void init_lex(); 42void init_lex ();
21void lex_debug(int n); 43void lex_debug (int n);
22void openaliases(char *name); 44void openaliases (char *name);
23void openaliases_prefix(char *prefix, char *name); 45void openaliases_prefix (char *prefix, char *name);
24 46
25struct string_list { 47struct string_list
26 struct string_list *next; 48{
27 char *str; 49 struct string_list *next;
50 char *str;
28}; 51};
29 52
30typedef struct slist { 53typedef struct slist
31 struct string_list *head, *tail; 54{
32 int count; 55 struct string_list *head, *tail;
56 int count;
33} SLIST; 57} SLIST;
34 58
35void slist_add(SLIST **plist, char *str); 59void slist_add (SLIST ** plist, char *str);
36void slist_append(SLIST **pdst, SLIST *src); 60void slist_append (SLIST ** pdst, SLIST * src);
37char *slist_member(SLIST *plist, char *name); 61char *slist_member (SLIST * plist, char *name);
38void slist_destroy(SLIST **plist); 62void slist_destroy (SLIST ** plist);
39
40void read_include(SLIST **plist, char *name);
41 63
42void regalias(char *name, SLIST *exp); 64void read_include (SLIST ** plist, char *name);
43void begin_aliases(void);
44void end_aliases(void);
45 65
46void error(char *fmt, ...); 66void regalias (char *name, SLIST * exp);
67void begin_aliases (void);
68void end_aliases (void);
47 69
48extern SLIST *cw_list; 70extern SLIST *cw_list;
49extern int verbose; 71extern int verbose;
diff --git a/gram.y b/gram.y
index d20f9d8..92346c7 100644
--- a/gram.y
+++ b/gram.y
@@ -1,6 +1,6 @@
1%{ 1%{
2/* ckaliases - verify syntax of sendmail-style alias files 2/* ckaliases - verify syntax of sendmail-style alias files
3 Copyright (C) 2005 Sergey Poznyakoff 3 Copyright (C) 2005, 2007 Sergey Poznyakoff
4 4
5 This program is free software; you can redistribute it and/or modify it 5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the 6 under the terms of the GNU General Public License as published by the
@@ -15,23 +15,18 @@
15 You should have received a copy of the GNU General Public License along 15 You should have received a copy of the GNU General Public License along
16 with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 with this program. If not, see <http://www.gnu.org/licenses/>. */
17 17
18#include <stdio.h>
19#include <stdlib.h>
20 #include <stdarg.h>
21#include <getopt.h>
22 #include <errno.h>
23#include "ckaliases.h" 18#include "ckaliases.h"
24 19
25SLIST *cw_list; /* List of domain names pertaining to Sendmail 'w' class */ 20SLIST *cw_list; /* List of domain names pertaining to Sendmail 'w' class */
26static int restricted; /* prohibit use of `special' aliases (pipes, file redirections 21static int restricted; /* prohibit use of `special' aliases (pipes,
27 and includes */ 22 file redirections and includes */
28int verbose; /* Verbose mode */ 23int verbose; /* Verbose mode */
29static int error_count; /* Number of errors detected so far */ 24int error_count; /* Number of errors detected so far */
30%} 25%}
31 26
32%union { 27%union {
33 char *string; 28 char *string;
34 SLIST *slist; 29 SLIST *slist;
35}; 30};
36 31
37%token <string> IDENT EMAIL STRING LHS 32%token <string> IDENT EMAIL STRING LHS
@@ -51,15 +46,15 @@ list : alias
51 | list EOL alias 46 | list EOL alias
52 | list error EOL 47 | list error EOL
53 { 48 {
54 yyclearin; 49 yyclearin;
55 yyerrok; 50 yyerrok;
56 } 51 }
57 ; 52 ;
58 53
59alias : /* empty */ 54alias : /* empty */
60 | lhs rhs 55 | lhs rhs
61 { 56 {
62 regalias($1, $2); 57 regalias ($1, $2);
63 } 58 }
64 ; 59 ;
65 60
@@ -69,41 +64,43 @@ lhs : LHS ':'
69rhs : emails 64rhs : emails
70 | rhs CONT emails 65 | rhs CONT emails
71 { 66 {
72 slist_append(&$1, $3); 67 slist_append (&$1, $3);
73 $$ = $1; 68 $$ = $1;
74 } 69 }
75 ; 70 ;
76 71
77emails: email 72emails: email
78 | emails ',' email 73 | emails ',' email
79 { 74 {
80 slist_append(&$1, $3); 75 slist_append (&$1, $3);
81 $$ = $1; 76 $$ = $1;
82 } 77 }
83 ; 78 ;
84 79
85email : string 80email : string
86 { 81 {
87 if (restricted && ($1[0] == '|' || $1[0] == '/')) { 82 if (restricted && ($1[0] == '|' || $1[0] == '/'))
88 yyerror("Construct not allowed"); 83 {
89 YYERROR; 84 yyerror ("Construct not allowed");
90 } 85 YYERROR;
91 $$ = NULL; 86 }
92 slist_add(&$$, $1); 87 $$ = NULL;
88 slist_add (&$$, $1);
93 } 89 }
94 | EMAIL 90 | EMAIL
95 { 91 {
96 $$ = NULL; 92 $$ = NULL;
97 slist_add(&$$, $1); 93 slist_add (&$$, $1);
98 } 94 }
99 | INCLUDE string 95 | INCLUDE string
100 { 96 {
101 if (restricted) { 97 if (restricted)
102 yyerror("Include statement is not allowed"); 98 {
103 YYERROR; 99 yyerror ("Include statement is not allowed");
104 } 100 YYERROR;
105 $$ = NULL; 101 }
106 read_include(&$$, $2); 102 $$ = NULL;
103 read_include (&$$, $2);
107 } 104 }
108 ; 105 ;
109 106
@@ -113,156 +110,167 @@ string: IDENT
113 110
114%% 111%%
115 112
116void 113int
117error(char *fmt, ...) 114yyerror (char *s)
118{
119 va_list ap;
120 va_start(ap, fmt);
121 vfprintf(stderr, fmt, ap);
122 va_end(ap);
123 fprintf(stderr, "\n");
124 error_count++;
125}
126
127yyerror(char *s)
128{ 115{
129 error("%s:%d: %s", file_name, line_num, s); 116 error_at_line (0, 0, file_name, line_num, "%s", s);
117 error_count++;
130} 118}
131 119
132
133 120
134void 121void
135usage() 122usage ()
136{ 123{
137 printf("usage: ckaliases [OPTIONS] [FILES...]\n"); 124 printf ("usage: ckaliases [OPTIONS] [FILES...]\n");
138 printf("OPTIONS and FILES may be interspered.\n"); 125 printf ("OPTIONS and FILES may be interspered.\n");
139 printf("Valid options are:\n"); 126 printf ("Valid options are:\n");
140 printf(" -d SPEC Set debug level. SPEC consists of the following\n"); 127 printf (" -d,--debug=SPEC Set debug level. SPEC consists of the following\n");
141 printf(" letters:\n"); 128 printf (" letters:\n");
142 printf(" y enable parser debugging\n"); 129 printf (" y enable parser debugging\n");
143 printf(" l enable lexical analizer debugging\n"); 130 printf (" l enable lexical analizer debugging\n");
144 printf(" Upper-case variants are also accepted. Prepending\n"); 131 printf (" Upper-case variants are also accepted. Prepending\n");
145 printf(" a letter with '-' reverts its sense\n"); 132 printf (" a letter with '-' reverts its sense\n");
146 printf(" -h Display this help list\n"); 133 printf (" -f, --files-from=FILE\n");
147 printf(" -r Restrict alias file syntax to aliases only (i.e.\n"); 134 printf (" Read names of alias files from FILE\n");
148 printf(" prohibit use of pipes and file redirections\n"); 135 printf (" -h, --help Display this help list\n");
149 printf(" -u Revert the effect of the previous -r option\n"); 136 printf (" -r, --restrict Restrict alias file syntax to aliases only (i.e.\n");
150 printf(" -v Verbose mode\n"); 137 printf (" prohibit use of pipes and file redirections\n");
151 printf(" -w FILE Read contents of Sendmail `w' class from the given\n"); 138 printf (" -u, --unrestrict Revert the effect of the previous -r option\n");
152 printf(" file.\n"); 139 printf (" -v, --verbose Verbose mode\n");
140 printf (" -V, --version print program version and exit\n");
141 printf (" -w FILE Read contents of Sendmail `w' class from the given\n");
142 printf (" file.\n");
153} 143}
154 144
145struct option options[] = {
146 { "debug", required_argument, NULL, 'd' },
147 { "help", no_argument, NULL, 'h' },
148 { "version", no_argument, NULL, 'V' },
149 { "restrict", no_argument, NULL, 'r' },
150 { "unrestrict", no_argument, NULL, 'u' },
151 { "verbose", no_argument, NULL, 'v' },
152 { "files-from", required_argument, NULL, 'f' },
153 { NULL }
154};
155 155
156int 156int
157main(int argc, char **argv) 157main (int argc, char **argv)
158{ 158{
159 char *p; 159 char *p;
160 int c; 160 int c;
161 int file_count = 0; 161 int file_count = 0;
162 int true = 1; 162 int true = 1;
163 char *cwfile = "/etc/mail/sendmail.cw"; 163 char *cwfile = "/etc/mail/sendmail.cw";
164 SLIST *file_list; /* List of files to be read */ 164 SLIST *file_list; /* List of files to be read */
165 struct string_list *s; 165 struct string_list *s;
166 166
167 begin_aliases(); 167 begin_aliases ();
168 init_lex(); 168 init_lex ();
169 while ((c = getopt(argc, argv, "-d:f:hp:ruvw:")) != EOF) { 169 program_name = argv[0];
170 switch (c) { 170 while ((c = getopt_long (argc, argv, "-d:f:hp:ruvw:", options, NULL)) != EOF)
171 case 1: 171 {
172 if (!cw_list) 172 switch (c)
173 read_include(&cw_list, cwfile); 173 {
174 openaliases(optarg); 174 case 1:
175 yyparse(); 175 if (!cw_list)
176 file_count++; 176 read_include (&cw_list, cwfile);
177 break; 177 openaliases (optarg);
178 yyparse ();
179 file_count++;
180 break;
178 181
179 case 'd': 182 case 'd':
180 for (p = optarg; *p; p++) { 183 for (p = optarg; *p; p++)
181 switch (*p) { 184 {
182 case '-': 185 switch (*p)
183 true = 0; 186 {
184 break; 187 case '-':
185 case 'y': 188 true = 0;
186 case 'Y': 189 break;
187 yydebug = true; 190
188 true = 1; 191 case 'y':
189 break; 192 case 'Y':
190 case 'l': 193 yydebug = true;
191 case 'L': 194 true = 1;
192 lex_debug(true); 195 break;
193 true = 1; 196
194 break; 197 case 'l':
195 default: 198 case 'L':
196 fprintf(stderr, "%s: unknown debug option %c\n", 199 lex_debug (true);
197 argv[0], *p); 200 true = 1;
198 exit(1); 201 break;
199 }
200 }
201 break;
202
203 case 'f':
204 if (!cw_list)
205 read_include(&cw_list, cwfile);
206 file_list = NULL;
207 read_include(&file_list, optarg);
208 for (s = file_list->head; s; s = s->next) {
209 openaliases_prefix(optarg, s->str);
210 yyparse();
211 file_count++;
212 }
213 slist_destroy(&file_list);
214 break;
215
216 case 'h':
217 usage();
218 exit(0);
219
220 case 'r':
221 restricted = 1;
222 break;
223
224 case 'u':
225 restricted = 0;
226 break;
227 202
228 case 'v':
229 verbose++;
230 break;
231
232 case 'w':
233 if (file_count) {
234 error("-w must be used before first non-option argument");
235 exit(1);
236 }
237 cwfile = optarg;
238 break;
239
240 default: 203 default:
241 exit(1); 204 error (1, 0, "%s: unknown debug option %c", argv[0]);
242 } 205 }
243 } 206 }
207 break;
208
209 case 'f':
210 if (!cw_list)
211 read_include (&cw_list, cwfile);
212 file_list = NULL;
213 read_include (&file_list, optarg);
214 for (s = file_list->head; s; s = s->next)
215 {
216 openaliases_prefix (optarg, s->str);
217 yyparse ();
218 file_count++;
219 }
220 slist_destroy (&file_list);
221 break;
222
223 case 'h':
224 usage ();
225 exit (0);
244 226
245 argc -= optind; 227 case 'r':
246 argv += optind; 228 restricted = 1;
229 break;
230
231 case 'u':
232 restricted = 0;
233 break;
234
235 case 'v':
236 verbose++;
237 break;
247 238
248 if (!cw_list) 239 case 'V':
249 read_include(&cw_list, cwfile); 240 gsc_version ("ckaliases");
250 while (argc--) { 241 exit (0);
251 openaliases(*argv++); 242
252 yyparse(); 243 case 'w':
253 file_count++; 244 if (file_count)
245 error (1, 0, "-w must be used before first non-option argument");
246 cwfile = optarg;
247 break;
248
249 default:
250 exit (1);
254 } 251 }
252 }
253
254 argc -= optind;
255 argv += optind;
256
257 if (!cw_list)
258 read_include (&cw_list, cwfile);
259 while (argc--)
260 {
261 openaliases (*argv++);
262 yyparse ();
263 file_count++;
264 }
255 265
256 if (!file_count) { 266 if (!file_count)
257 error("no files specified"); 267 error (1, 0, "no files specified");
258 exit(1);
259 }
260 268
261 if (verbose) 269 if (verbose)
262 printf("%d files\n", file_count); 270 printf ("%d files\n", file_count);
263 end_aliases(); 271 end_aliases ();
264 check_aliases(); 272 check_aliases ();
265 if (verbose) 273 if (verbose)
266 printf("%lu errors\n", error_count); 274 printf ("%lu errors\n", error_count);
267 exit(error_count!=0); 275 exit (error_count!=0);
268} 276}
diff --git a/lex.l b/lex.l
index 48f943a..ba48a9c 100644
--- a/lex.l
+++ b/lex.l
@@ -1,6 +1,6 @@
1%{ 1%{
2/* ckaliases - verify syntax of sendmail-style alias files 2/* ckaliases - verify syntax of sendmail-style alias files
3 Copyright (C) 2005 Sergey Poznyakoff 3 Copyright (C) 2005, 2007 Sergey Poznyakoff
4 4
5 This program is free software; you can redistribute it and/or modify it 5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the 6 under the terms of the GNU General Public License as published by the
@@ -15,23 +15,13 @@
15 You should have received a copy of the GNU General Public License along 15 You should have received a copy of the GNU General Public License along
16 with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 with this program. If not, see <http://www.gnu.org/licenses/>. */
17 17
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <sys/file.h>
22#include <sys/stat.h>
23#include <errno.h>
24#include <string.h>
25#define obstack_chunk_alloc malloc
26 #define obstack_chunk_free free
27#include <obstack.h>
28#include "ckaliases.h" 18#include "ckaliases.h"
29 #include "gram.h" 19 #include "gram.h"
30 20
31static void line_begin(void); 21static void line_begin (void);
32static void line_add(char *text, size_t len); 22static void line_add (char *text, size_t len);
33static void line_add_unescape(char *text, size_t len); 23static void line_add_unescape (char *text, size_t len);
34static void line_finish(void); 24static void line_finish (void);
35 25
36struct obstack string_stk; 26struct obstack string_stk;
37 27
@@ -54,32 +44,32 @@ SPEC [:@\\]
54 /* Names and emails */ 44 /* Names and emails */
55:include: return INCLUDE; 45:include: return INCLUDE;
56^{IDENT} { 46^{IDENT} {
57 line_begin(); 47 line_begin ();
58 line_add(yytext, yyleng); 48 line_add (yytext, yyleng);
59 line_finish(); 49 line_finish ();
60 return LHS; } 50 return LHS; }
61{IDENT}@{IDENT} { 51{IDENT}@{IDENT} {
62 line_begin(); 52 line_begin ();
63 line_add(yytext, yyleng); 53 line_add (yytext, yyleng);
64 line_finish(); 54 line_finish ();
65 return EMAIL; } 55 return EMAIL; }
66{IDENT} { line_begin(); 56{IDENT} { line_begin ();
67 line_add(yytext, yyleng); 57 line_add (yytext, yyleng);
68 line_finish(); 58 line_finish ();
69 return IDENT; } 59 return IDENT; }
70 /* Quoted strings */ 60 /* Quoted strings */
71\"[^\\"\n]*\" { line_begin(); 61\"[^\\"\n]*\" { line_begin ();
72 line_add(yytext, yyleng); 62 line_add (yytext, yyleng);
73 line_finish(); 63 line_finish ();
74 return STRING; } 64 return STRING; }
75\"[^\\"\n]*\\. { BEGIN(STR); 65\"[^\\"\n]*\\. { BEGIN (STR);
76 line_begin(); 66 line_begin ();
77 line_add_unescape(yytext + 1, yyleng - 1); } 67 line_add_unescape (yytext + 1, yyleng - 1); }
78<STR>[^\\"\n]*\\. { line_add_unescape(yytext, yyleng); } 68<STR>[^\\"\n]*\\. { line_add_unescape (yytext, yyleng); }
79<STR>[^\\"\n]*\" { BEGIN(INITIAL); 69<STR>[^\\"\n]*\" { BEGIN (INITIAL);
80 if (yyleng > 1) 70 if (yyleng > 1)
81 line_add(yytext, yyleng - 1); 71 line_add (yytext, yyleng - 1);
82 line_finish(); 72 line_finish ();
83 return STRING; } 73 return STRING; }
84 /* Other characters */ 74 /* Other characters */
85{SPEC} return yytext[0]; 75{SPEC} return yytext[0];
@@ -87,18 +77,16 @@ SPEC [:@\\]
87\n{WS}+/[^ \t\n] { line_num++; return CONT; } 77\n{WS}+/[^ \t\n] { line_num++; return CONT; }
88\n { line_num++; return EOL; } 78\n { line_num++; return EOL; }
89 ,return yytext[0]; 79 ,return yytext[0];
90. { char *p; 80. { error_at_line (0, 0, file_name, line_num,
91 asprintf(&p, 81 "Stray character %03o in alias file", yytext[0]);
92 "Stray character %03o in alias file", yytext[0]); 82 error_count++; }
93 yyerror(p);
94 free (p); }
95%% 83%%
96 84
97int 85int
98yywrap() 86yywrap ()
99{ 87{
100 fclose(yyin); 88 fclose (yyin);
101 return 1; 89 return 1;
102} 90}
103 91
104static char escape_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t"; 92static char escape_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
@@ -117,112 +105,107 @@ unescape_char (int c)
117} 105}
118 106
119void 107void
120line_add(char *text, size_t len) 108line_add (char *text, size_t len)
121{ 109{
122 obstack_grow(&string_stk, text, len); 110 obstack_grow (&string_stk, text, len);
123} 111}
124 112
125void 113void
126line_add_unescape(char *text, size_t len) 114line_add_unescape (char *text, size_t len)
127{ 115{
128 char c; 116 char c;
129 obstack_grow(&string_stk, text, len - 2); 117 obstack_grow (&string_stk, text, len - 2);
130 c = unescape_char(text[len - 1]); 118 c = unescape_char (text[len - 1]);
131 obstack_1grow(&string_stk, c); 119 obstack_1grow (&string_stk, c);
132} 120}
133 121
134void 122void
135line_begin() 123line_begin ()
136{ 124{
137} 125}
138 126
139void 127void
140line_finish() 128line_finish ()
141{ 129{
142 obstack_1grow(&string_stk, 0); 130 obstack_1grow (&string_stk, 0);
143 yylval.string = obstack_finish(&string_stk); 131 yylval.string = obstack_finish (&string_stk);
144} 132}
145 133
146void 134void
147openaliases(char *name) 135openaliases (char *name)
148{ 136{
149 yyin = fopen(name, "r"); 137 yyin = fopen (name, "r");
150 if (!yyin) { 138 if (!yyin)
151 fprintf(stderr, "cannot open file `%s': %s\n", 139 error (1, errno, "cannot open file `%s'", name);
152 name, strerror(errno)); 140 file_name = name;
153 exit(1); 141 line_num = 0;
154 }
155 file_name = name;
156 line_num = 0;
157} 142}
158 143
159void 144void
160openaliases_prefix(char *prefix, char *name) 145openaliases_prefix (char *prefix, char *name)
161{ 146{
162 char *fullname = NULL; 147 char *fullname = NULL;
163 struct stat st; 148 struct stat st;
164 149
165 if (stat(prefix, &st)) { 150 if (stat (prefix, &st))
166 fprintf(stderr, "cannot stat `%s': %s\n", 151 error (1, errno, "cannot stat `%s'", prefix);
167 prefix, strerror(errno)); 152
168 exit(1); 153 if (!S_ISDIR (st.st_mode))
169 } 154 {
170 155 char *p = strrchr (prefix, '/');
171 if (!S_ISDIR(st.st_mode)) { 156 if (p)
172 char *p = strrchr(prefix, '/'); 157 *p = 0;
173 if (p) 158 else
174 *p = 0; 159 prefix = ".";
175 else 160 }
176 prefix = "."; 161 asprintf (&fullname, "%s/%s", prefix, name);
177 } 162 openaliases (fullname);
178 asprintf(&fullname, "%s/%s", prefix, name); 163 free (fullname);
179 openaliases(fullname);
180 free(fullname);
181} 164}
182 165
183void 166void
184init_lex() 167init_lex ()
185{ 168{
186 obstack_init(&string_stk); 169 obstack_init (&string_stk);
187 yy_flex_debug = 0; 170 yy_flex_debug = 0;
188} 171}
189 172
190void 173void
191lex_debug(int debug) 174lex_debug (int debug)
192{ 175{
193 yy_flex_debug = debug; 176 yy_flex_debug = debug;
194} 177}
195 178
196void 179void
197read_include(SLIST **plist, char *name) 180read_include (SLIST **plist, char *name)
198{ 181{
199 char *p; 182 char *p;
200 char buffer[256]; 183 char buffer[256];
201 FILE *fp = fopen(name, "r"); 184 FILE *fp = fopen (name, "r");
202 185
203 if (!fp) { 186 if (!fp)
204 char *p; 187 {
205 asprintf(&p, 188 error_at_line (0, 0, file_name, line_num,
206 "cannot open include file `%s': %s", 189 "cannot open include file `%s': %s",
207 name, strerror(errno)); 190 name, strerror (errno));
208 yyerror(p); 191 error_count++;
209 free(p); 192 return;
210 return; 193 }
211 } 194
212 195 while (p = fgets (buffer, sizeof buffer, fp))
213 while (p = fgets(buffer, sizeof buffer, fp)) { 196 {
214 char *q; 197 char *q;
215 198
216 while (*p && isspace(*p)) 199 while (*p && isspace (*p))
217 p++; 200 p++;
218 if (*p == '#') 201 if (*p == '#')
219 continue; 202 continue;
220 for (q = p + strlen(p) - 1; q > p && isspace(*q); q--) 203 for (q = p + strlen (p) - 1; q > p && isspace (*q); q--)
221 ; 204 ;
222 q[1] = 0; 205 q[1] = 0;
223 if (*p) 206 if (*p)
224 slist_add(plist, strdup(p)); 207 slist_add (plist, strdup (p));
225 } 208 }
226 fclose(fp); 209 fclose (fp);
227} 210}
228 211

Return to:

Send suggestions and report system problems to the System administrator.