smtpd.y (7021B)
1 %{ 2 #include "common.h" 3 #include <ctype.h> 4 #include "smtpd.h" 5 6 #define YYSTYPE yystype 7 typedef struct quux yystype; 8 struct quux { 9 String *s; 10 int c; 11 }; 12 Biobuf *yyfp; 13 YYSTYPE *bang; 14 extern Biobuf bin; 15 extern int debug; 16 17 YYSTYPE cat(YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*); 18 int yyparse(void); 19 int yylex(void); 20 YYSTYPE anonymous(void); 21 %} 22 23 %term SPACE 24 %term CNTRL 25 %term CRLF 26 %start conversation 27 %% 28 29 conversation : cmd 30 | conversation cmd 31 ; 32 cmd : error 33 | 'h' 'e' 'l' 'o' spaces sdomain CRLF 34 { hello($6.s, 0); } 35 | 'e' 'h' 'l' 'o' spaces sdomain CRLF 36 { hello($6.s, 1); } 37 | 'm' 'a' 'i' 'l' spaces 'f' 'r' 'o' 'm' ':' spath CRLF 38 { sender($11.s); } 39 | 'm' 'a' 'i' 'l' spaces 'f' 'r' 'o' 'm' ':' spath spaces 'a' 'u' 't' 'h' '=' sauth CRLF 40 { sender($11.s); } 41 | 'r' 'c' 'p' 't' spaces 't' 'o' ':' spath CRLF 42 { receiver($9.s); } 43 | 'd' 'a' 't' 'a' CRLF 44 { data(); } 45 | 'r' 's' 'e' 't' CRLF 46 { reset(); } 47 | 's' 'e' 'n' 'd' spaces 'f' 'r' 'o' 'm' ':' spath CRLF 48 { sender($11.s); } 49 | 's' 'o' 'm' 'l' spaces 'f' 'r' 'o' 'm' ':' spath CRLF 50 { sender($11.s); } 51 | 's' 'a' 'm' 'l' spaces 'f' 'r' 'o' 'm' ':' spath CRLF 52 { sender($11.s); } 53 | 'v' 'r' 'f' 'y' spaces string CRLF 54 { verify($6.s); } 55 | 'e' 'x' 'p' 'n' spaces string CRLF 56 { verify($6.s); } 57 | 'h' 'e' 'l' 'p' CRLF 58 { help(0); } 59 | 'h' 'e' 'l' 'p' spaces string CRLF 60 { help($6.s); } 61 | 'n' 'o' 'o' 'p' CRLF 62 { noop(); } 63 | 'q' 'u' 'i' 't' CRLF 64 { quit(); } 65 | 't' 'u' 'r' 'n' CRLF 66 { turn(); } 67 | 's' 't' 'a' 'r' 't' 't' 'l' 's' CRLF 68 { starttls(); } 69 | 'a' 'u' 't' 'h' spaces name spaces string CRLF 70 { auth($6.s, $8.s); } 71 | 'a' 'u' 't' 'h' spaces name CRLF 72 { auth($6.s, nil); } 73 | CRLF 74 { reply("501 illegal command or bad syntax\r\n"); } 75 ; 76 path : '<' '>' ={ $$ = anonymous(); } 77 | '<' mailbox '>' ={ $$ = $2; } 78 | '<' a_d_l ':' mailbox '>' ={ $$ = cat(&$2, bang, &$4, 0, 0 ,0, 0); } 79 ; 80 spath : path ={ $$ = $1; } 81 | spaces path ={ $$ = $2; } 82 ; 83 auth : path ={ $$ = $1; } 84 | mailbox ={ $$ = $1; } 85 ; 86 sauth : auth ={ $$ = $1; } 87 | spaces auth ={ $$ = $2; } 88 ; 89 ; 90 a_d_l : at_domain ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 91 | at_domain ',' a_d_l ={ $$ = cat(&$1, bang, &$3, 0, 0, 0, 0); } 92 ; 93 at_domain : '@' domain ={ $$ = cat(&$2, 0, 0, 0, 0 ,0, 0); } 94 ; 95 sdomain : domain ={ $$ = $1; } 96 | domain spaces ={ $$ = $1; } 97 ; 98 domain : element ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 99 | element '.' ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 100 | element '.' domain ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); } 101 ; 102 element : name ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 103 | '#' number ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 104 | '[' ']' ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 105 | '[' dotnum ']' ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); } 106 ; 107 mailbox : local_part ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 108 | local_part '@' domain ={ $$ = cat(&$3, bang, &$1, 0, 0 ,0, 0); } 109 ; 110 local_part : dot_string ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 111 | quoted_string ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 112 ; 113 name : let_dig ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 114 | let_dig ld_str ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 115 | let_dig ldh_str ld_str ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); } 116 ; 117 ld_str : let_dig 118 | let_dig ld_str ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 119 ; 120 ldh_str : hunder 121 | ld_str hunder ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 122 | ldh_str ld_str hunder ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); } 123 ; 124 let_dig : a 125 | d 126 ; 127 dot_string : string ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 128 | string '.' dot_string ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); } 129 ; 130 131 string : char ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 132 | string char ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 133 ; 134 135 quoted_string : '"' qtext '"' ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); } 136 ; 137 qtext : '\\' x ={ $$ = cat(&$2, 0, 0, 0, 0 ,0, 0); } 138 | qtext '\\' x ={ $$ = cat(&$1, &$3, 0, 0, 0 ,0, 0); } 139 | q 140 | qtext q ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 141 ; 142 char : c 143 | '\\' x ={ $$ = $2; } 144 ; 145 dotnum : snum '.' snum '.' snum '.' snum ={ $$ = cat(&$1, &$2, &$3, &$4, &$5, &$6, &$7); } 146 ; 147 number : d ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); } 148 | number d ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); } 149 ; 150 snum : number ={ if(atoi(s_to_c($1.s)) > 255) print("bad snum\n"); } 151 ; 152 spaces : SPACE ={ $$ = $1; } 153 | SPACE spaces ={ $$ = $1; } 154 ; 155 hunder : '-' | '_' 156 ; 157 special1 : CNTRL 158 | '(' | ')' | ',' | '.' 159 | ':' | ';' | '<' | '>' | '@' 160 ; 161 special : special1 | '\\' | '"' 162 ; 163 notspecial : '!' | '#' | '$' | '%' | '&' | '\'' 164 | '*' | '+' | '-' | '/' 165 | '=' | '?' 166 | '[' | ']' | '^' | '_' | '`' | '{' | '|' | '}' | '~' 167 ; 168 169 a : 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' 170 | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' 171 | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' 172 ; 173 d : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' 174 ; 175 c : a | d | notspecial 176 ; 177 q : a | d | special1 | notspecial | SPACE 178 ; 179 x : a | d | special | notspecial | SPACE 180 ; 181 %% 182 183 void 184 parseinit(void) 185 { 186 bang = (YYSTYPE*)malloc(sizeof(YYSTYPE)); 187 bang->c = '!'; 188 bang->s = 0; 189 yyfp = &bin; 190 } 191 192 int 193 yylex(void) 194 { 195 int c; 196 197 for(;;){ 198 c = Bgetc(yyfp); 199 if(c == -1) 200 return 0; 201 if(debug) 202 fprint(2, "%c", c); 203 yylval.c = c = c & 0x7F; 204 if(c == '\n'){ 205 return CRLF; 206 } 207 if(c == '\r'){ 208 c = Bgetc(yyfp); 209 if(c != '\n'){ 210 Bungetc(yyfp); 211 c = '\r'; 212 } else { 213 if(debug) 214 fprint(2, "%c", c); 215 return CRLF; 216 } 217 } 218 if(isalpha(c)) 219 return tolower(c); 220 if(isspace(c)) 221 return SPACE; 222 if(iscntrl(c)) 223 return CNTRL; 224 return c; 225 } 226 } 227 228 YYSTYPE 229 cat(YYSTYPE *y1, YYSTYPE *y2, YYSTYPE *y3, YYSTYPE *y4, YYSTYPE *y5, YYSTYPE *y6, YYSTYPE *y7) 230 { 231 YYSTYPE rv; 232 233 memset(&rv, 0, sizeof rv); 234 if(y1->s) 235 rv.s = y1->s; 236 else { 237 rv.s = s_new(); 238 s_putc(rv.s, y1->c); 239 s_terminate(rv.s); 240 } 241 if(y2){ 242 if(y2->s){ 243 s_append(rv.s, s_to_c(y2->s)); 244 s_free(y2->s); 245 } else { 246 s_putc(rv.s, y2->c); 247 s_terminate(rv.s); 248 } 249 } else 250 return rv; 251 if(y3){ 252 if(y3->s){ 253 s_append(rv.s, s_to_c(y3->s)); 254 s_free(y3->s); 255 } else { 256 s_putc(rv.s, y3->c); 257 s_terminate(rv.s); 258 } 259 } else 260 return rv; 261 if(y4){ 262 if(y4->s){ 263 s_append(rv.s, s_to_c(y4->s)); 264 s_free(y4->s); 265 } else { 266 s_putc(rv.s, y4->c); 267 s_terminate(rv.s); 268 } 269 } else 270 return rv; 271 if(y5){ 272 if(y5->s){ 273 s_append(rv.s, s_to_c(y5->s)); 274 s_free(y5->s); 275 } else { 276 s_putc(rv.s, y5->c); 277 s_terminate(rv.s); 278 } 279 } else 280 return rv; 281 if(y6){ 282 if(y6->s){ 283 s_append(rv.s, s_to_c(y6->s)); 284 s_free(y6->s); 285 } else { 286 s_putc(rv.s, y6->c); 287 s_terminate(rv.s); 288 } 289 } else 290 return rv; 291 if(y7){ 292 if(y7->s){ 293 s_append(rv.s, s_to_c(y7->s)); 294 s_free(y7->s); 295 } else { 296 s_putc(rv.s, y7->c); 297 s_terminate(rv.s); 298 } 299 } else 300 return rv; 301 return rv; 302 } 303 304 void 305 yyerror(char *x) 306 { 307 USED(x); 308 } 309 310 /* 311 * an anonymous user 312 */ 313 YYSTYPE 314 anonymous(void) 315 { 316 YYSTYPE rv; 317 318 memset(&rv, 0, sizeof rv); 319 rv.s = s_copy("/dev/null"); 320 return rv; 321 }