%{ /* ckaliases - verify syntax of sendmail-style alias files 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 . */ #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); 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 (); return LHS; } {IDENT}@{IDENT} { line_begin(); line_add(yytext, yyleng); line_finish(); return EMAIL; } {IDENT} { line_begin(); line_add(yytext, yyleng); line_finish(); return IDENT; } /* Quoted strings */ \"[^\\"\n]*\" { line_begin(); line_add(yytext, yyleng); line_finish(); return STRING; } \"[^\\"\n]*\\. { BEGIN(STR); line_begin(); line_add_unescape(yytext + 1, yyleng - 1); } [^\\"\n]*\\. { line_add_unescape(yytext, yyleng); } [^\\"\n]*\" { BEGIN(INITIAL); if (yyleng > 1) 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]; . { error_at_line(0, 0, file_name, line_num, "Stray character %03o in alias file", yytext[0]); error_count++; } %% int yywrap() { 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; } void line_add(char *text, size_t len) { obstack_grow(&string_stk, text, len); } void line_add_unescape(char *text, size_t len) { char c; obstack_grow(&string_stk, text, len - 2); c = unescape_char(text[len - 1]); obstack_1grow(&string_stk, c); } void line_begin() { } void line_finish () { obstack_1grow(&string_stk, 0); yylval.string = obstack_finish(&string_stk); } void openaliases(char *name) { yyin = fopen (name, "r"); if (!yyin) error(1, errno, "cannot open file `%s'", name); file_name = name; line_num = 0; } void openaliases_prefix(char *prefix, char *name) { char *fullname = NULL; struct stat st; if (stat(prefix, &st)) error(1, errno, "cannot stat `%s'", prefix); if (!S_ISDIR(st.st_mode)) { char *p = strrchr(prefix, '/'); if (p) *p = 0; else prefix = "."; } asprintf(&fullname, "%s/%s", prefix, name); openaliases(fullname); free(fullname); } void init_lex() { obstack_init(&string_stk); yy_flex_debug = 0; } void lex_debug(int debug) { yy_flex_debug = debug; } void read_include(SLIST **plist, char *name) { char *p; char buffer[256]; FILE *fp = fopen(name, "r"); if (!fp) { error_at_line(0, 0, file_name, line_num, "cannot open include file `%s': %s", name, strerror(errno)); error_count++; return; } while (p = fgets(buffer, sizeof buffer, fp)) { char *q; while (*p && isspace(*p)) p++; if (*p == '#') continue; for (q = p + strlen(p) - 1; q > p && isspace(*q); q--) ; q[1] = 0; if (*p) slist_add(plist, strdup(p)); } fclose(fp); }