]> Pileus Git - ~andy/fetchmail/blob - rcfile_y.y
Increase %a for Solaris.
[~andy/fetchmail] / rcfile_y.y
1 %{
2 /*
3  * rcfile_y.y -- Run control file parser for fetchmail
4  *
5  * For license terms, see the file COPYING in this directory.
6  */
7
8 #include <config.h>
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <sys/file.h>
12 #include <sys/wait.h>
13 #include <sys/stat.h>
14 #include <errno.h>
15 #if defined(STDC_HEADERS)
16 #include <stdlib.h>
17 #endif
18 #if defined(HAVE_UNISTD_H)
19 #include <unistd.h>
20 #endif
21 #include <string.h>
22
23 #include "fetchmail.h"
24
25 struct query cmd_opts;  /* where to put command-line info */
26 struct query *querylist;        /* head of server list (globally visible) */
27
28 int yydebug;    /* in case we didn't generate with -- debug */
29
30 static struct query current;            /* current server record */
31 static int prc_errflag;
32
33 static void prc_register();
34 static void prc_reset();
35 %}
36
37 %union {
38   int proto;
39   int flag;
40   int number;
41   char *sval;
42 }
43
44 %token DEFAULTS POLL SKIP AKA PROTOCOL AUTHENTICATE TIMEOUT KPOP KERBEROS
45 %token USERNAME PASSWORD FOLDER SMTPHOST MDA LIMIT
46 %token IS HERE THERE TO MAP WILDCARD
47 %token SET BATCHLIMIT LOGFILE
48 %token <proto> PROTO
49 %token <sval>  STRING
50 %token <number> NUMBER
51 %token <flag>  KEEP FLUSH FETCHALL REWRITE PORT
52
53 /* these are actually used by the lexer */
54 %token FLAG_TRUE        2
55 %token FLAG_FALSE       1
56
57 %%
58
59 rcfile          : /* empty */
60                 | statement_list
61                 ;
62
63 statement_list  : statement
64                 | statement_list statement
65                 ;
66
67 /* future global options should also have the form SET <name> <value> */
68 statement       : SET BATCHLIMIT MAP NUMBER     {batchlimit = $4;}
69                 | SET LOGFILE MAP STRING        {logfile = xstrdup($4);}
70
71 /* 
72  * The way the next two productions are written depends on the fact that
73  * userspecs cannot be empty.  It's a kluge to deal with files that set
74  * up a load of defaults and then have poll statements following with no
75  * user options at all. 
76  */
77                 | define_server serverspecs     {prc_register(); prc_reset();}
78                 | define_server serverspecs userspecs
79                 ;
80
81 define_server   : POLL STRING   {current.servernames = (struct idlist *)NULL;
82                                         save_str(&current.servernames, -1, $2);
83                                         current.skip = FALSE;}
84                 | SKIP STRING   {current.servernames = (struct idlist *)NULL;
85                                         save_str(&current.servernames, -1, $2);
86                                         current.skip = TRUE;}
87                 | DEFAULTS      {current.servernames = (struct idlist *)NULL;
88                                         save_str(&current.servernames, -1,"defaults");}
89                 ;
90
91 serverspecs     : /* EMPTY */
92                 | serverspecs serv_option
93                 ;
94
95 alias_list      : STRING                {save_str(&current.servernames, -1, $1);}
96                 | alias_list STRING     {save_str(&current.servernames, -1, $2);}
97                 ;
98
99 serv_option     : AKA alias_list
100                 | PROTOCOL PROTO        {current.protocol = $2;}
101                 | PROTOCOL KPOP         {
102                                             current.protocol = P_POP3;
103                                             current.authenticate = A_KERBEROS;
104                                             current.port = KPOP_PORT;
105                                         }
106                 | PORT NUMBER           {current.port = $2;}
107                 | AUTHENTICATE PASSWORD {current.authenticate = A_PASSWORD;}
108                 | AUTHENTICATE KERBEROS {current.authenticate = A_KERBEROS;}
109                 | TIMEOUT NUMBER        {current.timeout = $2;}
110                 ;
111
112 /*
113  * The first and only the first user spec may omit the USERNAME part.
114  * This is a backward-compatibility kluge to allow old popclient files
115  * to keep working.
116  */
117 userspecs       : user1opts             {prc_register(); prc_reset();}
118                 | user1opts explicits   {prc_register(); prc_reset();}
119                 | explicits
120                 ;
121
122 explicits       : explicitdef           {prc_register(); prc_reset();}
123                 | explicits explicitdef {prc_register(); prc_reset();}
124                 ;
125
126 explicitdef     : userdef user0opts
127                 ;
128
129 userdef         : USERNAME STRING       {strcpy(current.remotename, $2);}
130                 | USERNAME mapping_list HERE
131                 | USERNAME STRING THERE {strcpy(current.remotename, $2);}
132                 ;
133
134 user0opts       : /* EMPTY */
135                 | user0opts user_option
136                 ;
137
138 user1opts       : user_option
139                 | user1opts user_option
140                 ;
141
142 localnames      : WILDCARD              {current.wildcard =  TRUE;}
143                 | mapping_list          {current.wildcard =  FALSE;}
144                 | mapping_list WILDCARD {current.wildcard =  TRUE;}
145                 ;
146
147 mapping_list    : mapping               
148                 | mapping_list mapping
149                 ;
150
151 mapping         : STRING        
152                                 {save_str_pair(&current.localnames, $1, NULL);}
153                 | STRING MAP STRING
154                                 {save_str_pair(&current.localnames, $1, $3);}
155                 ;
156
157 user_option     : TO localnames HERE
158                 | TO localnames
159                 | IS localnames HERE
160                 | IS localnames
161
162                 | IS STRING THERE       {strcpy(current.remotename, $2);}
163                 | PASSWORD STRING       {strcpy(current.password, $2);}
164                 | FOLDER STRING         {strcpy(current.mailbox, $2);}
165                 | SMTPHOST STRING       {strcpy(current.smtphost, $2);}
166                 | MDA STRING            {strcpy(current.mda, $2);}
167
168                 | KEEP                  {current.keep = ($1==FLAG_TRUE);}
169                 | FLUSH                 {current.flush = ($1==FLAG_TRUE);}
170                 | FETCHALL              {current.fetchall = ($1==FLAG_TRUE);}
171                 | REWRITE               {current.norewrite = ($1==FLAG_TRUE);}
172                 | LIMIT NUMBER          {current.limit = $2;}
173                 ;
174 %%
175
176 /* lexer interface */
177 extern char *rcfile;
178 extern int prc_lineno;
179 extern char *yytext;
180 extern FILE *yyin;
181
182 static struct query *hosttail;  /* where to add new elements */
183
184 void yyerror (const char *s)
185 /* report a syntax error */
186 {
187     fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
188     prc_errflag++;
189 }
190
191 int prc_filecheck(pathname)
192 /* check that a configuration file is secure */
193 const char *pathname;           /* pathname for the configuration file */
194 {
195     struct stat statbuf;
196
197     /* the run control file must have the same uid as the REAL uid of this 
198        process, it must have permissions no greater than 600, and it must not 
199        be a symbolic link.  We check these conditions here. */
200
201     errno = 0;
202     if (lstat(pathname, &statbuf) < 0) {
203         if (errno == ENOENT) 
204             return(0);
205         else {
206             perror(pathname);
207             return(PS_IOERR);
208         }
209     }
210
211     if ((statbuf.st_mode & S_IFLNK) == S_IFLNK) {
212         fprintf(stderr, "File %s must not be a symbolic link.\n", pathname);
213         return(PS_AUTHFAIL);
214     }
215
216     if (statbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
217         fprintf(stderr, "File %s must have no more than -rw------ permissions.\n", 
218                 pathname);
219         return(PS_AUTHFAIL);
220     }
221
222     if (statbuf.st_uid != getuid()) {
223         fprintf(stderr, "File %s must be owned by you.\n", pathname);
224         return(PS_AUTHFAIL);
225     }
226
227     return(0);
228 }
229
230 int prc_parse_file (pathname)
231 /* digest the configuration into a linked list of host records */
232 const char *pathname;           /* pathname for the configuration file */
233 {
234     prc_errflag = 0;
235     querylist = hosttail = (struct query *)NULL;
236     prc_reset();
237
238     /* Check that the file is secure */
239     if ((prc_errflag = prc_filecheck(pathname)) != 0)
240         return(prc_errflag);
241
242     if (errno == ENOENT)
243         return(0);
244
245     /* Open the configuration and feed it to the lexer. */
246     if ((yyin = fopen(pathname,"r")) == (FILE *)NULL) {
247         perror(pathname);
248         return(PS_IOERR);
249     }
250
251     yyparse();          /* parse entire file */
252
253     fclose(yyin);
254
255     if (prc_errflag) 
256         return(PS_SYNTAX);
257     else
258         return(0);
259 }
260
261 static void prc_reset(void)
262 /* clear the global current record (server parameters) used by the parser */
263 {
264     int         saveport, saveproto, saveauth, saveskip;
265     struct idlist *saveservernames;
266
267     /*
268      * Purpose of this code is to initialize the new server block, but
269      * preserve whatever server name was previously set.  Also
270      * preserve server options unless the command-line explicitly
271      * overrides them.
272      */
273     saveport = current.port;
274     saveproto = current.protocol;
275     saveauth = current.authenticate;
276     saveskip = current.skip;
277     saveservernames = current.servernames;
278
279     memset(&current, '\0', sizeof(current));
280
281     current.protocol = saveproto;
282     current.authenticate = saveauth;
283     current.skip = saveskip;
284     current.servernames = saveservernames;
285 }
286
287 struct query *hostalloc(init)
288 /* append a host record to the host list */
289 struct query *init;     /* pointer to block containing initial values */
290 {
291     struct query *node;
292
293     /* allocate new node */
294     node = (struct query *) xmalloc(sizeof(struct query));
295
296     /* initialize it */
297     memcpy(node, init, sizeof(struct query));
298
299     /* append to end of list */
300     if (hosttail != (struct query *) 0)
301         hosttail->next = node;  /* list contains at least one element */
302     else
303         querylist = node;       /* list is empty */
304     hosttail = node;
305     return(node);
306 }
307
308 static void prc_register(void)
309 /* register current parameters and append to the host list */
310 {
311 #define STR_FORCE(fld, len) if (cmd_opts.fld[0]) \
312                                         strcpy(current.fld, cmd_opts.fld)
313     STR_FORCE(remotename, USERNAMELEN);
314     STR_FORCE(password, PASSWORDLEN);
315     STR_FORCE(mailbox, FOLDERLEN);
316     STR_FORCE(smtphost, HOSTLEN);
317     STR_FORCE(mda, MDALEN);
318 #undef STR_FORCE
319     
320 #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld
321     FLAG_FORCE(protocol);
322     FLAG_FORCE(keep);
323     FLAG_FORCE(flush);
324     FLAG_FORCE(fetchall);
325     FLAG_FORCE(norewrite);
326     FLAG_FORCE(skip);
327     FLAG_FORCE(port);
328     FLAG_FORCE(authenticate);
329     FLAG_FORCE(timeout);
330     FLAG_FORCE(limit);
331 #undef FLAG_FORCE
332
333     (void) hostalloc(&current);
334 }
335
336 void optmerge(struct query *h2, struct query *h1)
337 /* merge two options records; empty fields in h2 are filled in from h1 */
338 {
339     append_str_list(&h2->localnames, &h1->localnames);
340
341 #define STR_MERGE(fld, len) if (*(h2->fld) == '\0') strcpy(h2->fld, h1->fld)
342     STR_MERGE(remotename, USERNAMELEN);
343     STR_MERGE(password, PASSWORDLEN);
344     STR_MERGE(mailbox, FOLDERLEN);
345     STR_MERGE(smtphost, HOSTLEN);
346     STR_MERGE(mda, MDALEN);
347 #undef STR_MERGE
348
349 #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
350     FLAG_MERGE(protocol);
351     FLAG_MERGE(keep);
352     FLAG_MERGE(flush);
353     FLAG_MERGE(fetchall);
354     FLAG_MERGE(norewrite);
355     FLAG_MERGE(skip);
356     FLAG_MERGE(port);
357     FLAG_MERGE(authenticate);
358     FLAG_MERGE(timeout);
359     FLAG_MERGE(limit);
360 #undef FLAG_MERGE
361 }
362
363 /* easier to do this than cope with variations in where the library lives */
364 int yywrap(void) {return 1;}
365
366 /* rcfile_y.y ends here */