%{ /* 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); }