3 * rcfile_y.y -- Run control file parser for fetchmail
5 * For license terms, see the file COPYING in this directory.
10 #include <sys/types.h>
15 #if defined(STDC_HEADERS)
18 #if defined(HAVE_UNISTD_H)
23 #include "fetchmail.h"
25 struct query cmd_opts; /* where to put command-line info */
26 struct query *querylist; /* head of server list (globally visible) */
28 int yydebug; /* in case we didn't generate with -- debug */
30 static struct query current; /* current server record */
31 static int prc_errflag;
33 static void prc_register();
34 static void prc_reset();
44 %token DEFAULTS POLL SKIP AKA PROTOCOL AUTHENTICATE TIMEOUT KPOP KERBEROS
45 %token USERNAME PASSWORD FOLDER SMTPHOST MDA IS HERE THERE TO MAP LIMIT
46 %token SET BATCHLIMIT LOGFILE
49 %token <number> NUMBER
50 %token <flag> KEEP FLUSH FETCHALL REWRITE PORT
52 /* these are actually used by the lexer */
62 statement_list : statement
63 | statement_list statement
66 /* future global options should also have the form SET <name> <value> */
67 statement : SET BATCHLIMIT MAP NUMBER {batchlimit = $4;}
68 | SET LOGFILE STRING {logfile = xstrdup($3);}
71 * The way the next two productions are written depends on the fact that
72 * userspecs cannot be empty. It's a kluge to deal with files that sset
73 * up a load of defaults and then have poll statements following with no
74 * user options at all.
76 | define_server serverspecs {prc_register(); prc_reset();}
77 | define_server serverspecs userspecs
80 define_server : POLL STRING {strcpy(current.servername, $2);}
81 | SKIP STRING {strcpy(current.servername, $2);
83 | DEFAULTS {strcpy(current.servername,"defaults");}
86 serverspecs : /* EMPTY */
87 | serverspecs serv_option
90 alias_list : STRING {save_uid(¤t.aka, -1, $1);}
91 | alias_list STRING {save_uid(¤t.aka, -1, $2);}
94 serv_option : AKA alias_list
95 | PROTOCOL PROTO {current.protocol = $2;}
97 current.protocol = P_POP3;
98 current.authenticate = A_KERBEROS;
99 current.port = KPOP_PORT;
101 | PORT NUMBER {current.port = $2;}
102 | AUTHENTICATE PASSWORD {current.authenticate = A_PASSWORD;}
103 | AUTHENTICATE KERBEROS {current.authenticate = A_KERBEROS;}
104 | TIMEOUT NUMBER {current.timeout = $2;}
108 * The first and only the first user spec may omit the USERNAME part.
109 * This is a backward-compatibility kluge to allow old popclient files
112 userspecs : user1opts {prc_register(); prc_reset();}
113 | user1opts explicits {prc_register(); prc_reset();}
117 explicits : explicitdef {prc_register(); prc_reset();}
118 | explicits explicitdef {prc_register(); prc_reset();}
121 explicitdef : userdef user0opts
124 userdef : USERNAME STRING {strcpy(current.remotename, $2);}
125 | USERNAME mapping_list HERE
126 | USERNAME STRING THERE {strcpy(current.remotename, $2);}
129 user0opts : /* EMPTY */
130 | user0opts user_option
133 user1opts : user_option
134 | user1opts user_option
137 mapping_list : mapping
138 | mapping_list mapping
142 {save_id_pair(¤t.localnames, $1, NULL);}
144 {save_id_pair(¤t.localnames, $1, $3);}
147 user_option : TO mapping_list HERE
149 | IS mapping_list HERE
152 | IS STRING THERE {strcpy(current.remotename, $2);}
153 | PASSWORD STRING {strcpy(current.password, $2);}
154 | FOLDER STRING {strcpy(current.mailbox, $2);}
155 | SMTPHOST STRING {strcpy(current.smtphost, $2);}
156 | MDA STRING {strcpy(current.mda, $2);}
158 | KEEP {current.keep = ($1==FLAG_TRUE);}
159 | FLUSH {current.flush = ($1==FLAG_TRUE);}
160 | FETCHALL {current.fetchall = ($1==FLAG_TRUE);}
161 | REWRITE {current.norewrite = ($1==FLAG_TRUE);}
162 | LIMIT NUMBER {current.limit = $2;}
166 /* lexer interface */
168 extern int prc_lineno;
172 static struct query *hosttail; /* where to add new elements */
174 void yyerror (const char *s)
175 /* report a syntax error */
177 fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
181 int prc_filecheck(pathname)
182 /* check that a configuration file is secure */
183 const char *pathname; /* pathname for the configuration file */
187 /* the run control file must have the same uid as the REAL uid of this
188 process, it must have permissions no greater than 600, and it must not
189 be a symbolic link. We check these conditions here. */
192 if (lstat(pathname, &statbuf) < 0) {
201 if ((statbuf.st_mode & S_IFLNK) == S_IFLNK) {
202 fprintf(stderr, "File %s must not be a symbolic link.\n", pathname);
206 if (statbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
207 fprintf(stderr, "File %s must have no more than -rw------ permissions.\n",
212 if (statbuf.st_uid != getuid()) {
213 fprintf(stderr, "File %s must be owned by you.\n", pathname);
220 int prc_parse_file (pathname)
221 /* digest the configuration into a linked list of host records */
222 const char *pathname; /* pathname for the configuration file */
225 querylist = hosttail = (struct query *)NULL;
228 /* Check that the file is secure */
229 if ((prc_errflag = prc_filecheck(pathname)) != 0)
235 /* Open the configuration and feed it to the lexer. */
236 if ((yyin = fopen(pathname,"r")) == (FILE *)NULL) {
241 yyparse(); /* parse entire file */
251 static void prc_reset(void)
252 /* clear the global current record (server parameters) used by the parser */
254 char savename[HOSTLEN+1];
255 int saveport, saveproto, saveauth, saveskip;
256 struct idlist *saveaka;
259 * Purpose of this code is to initialize the new server block, but
260 * preserve whatever server name was previously set. Also
261 * preserve server options unless the command-line explicitly
264 (void) strcpy(savename, current.servername);
265 saveport = current.port;
266 saveproto = current.protocol;
267 saveauth = current.authenticate;
268 saveskip = current.skip;
269 saveaka = current.aka;
271 memset(¤t, '\0', sizeof(current));
273 (void) strcpy(current.servername, savename);
274 current.protocol = saveproto;
275 current.authenticate = saveauth;
276 current.skip = saveskip;
277 current.aka = saveaka;
280 struct query *hostalloc(init)
281 /* append a host record to the host list */
282 struct query *init; /* pointer to block containing initial values */
286 /* allocate new node */
287 node = (struct query *) xmalloc(sizeof(struct query));
290 memcpy(node, init, sizeof(struct query));
292 /* append to end of list */
293 if (hosttail != (struct query *) 0)
294 hosttail->next = node; /* list contains at least one element */
296 querylist = node; /* list is empty */
301 static void prc_register(void)
302 /* register current parameters and append to the host list */
304 #define STR_FORCE(fld, len) if (cmd_opts.fld[0]) \
305 strcpy(current.fld, cmd_opts.fld)
306 STR_FORCE(remotename, USERNAMELEN);
307 STR_FORCE(password, PASSWORDLEN);
308 STR_FORCE(mailbox, FOLDERLEN);
309 STR_FORCE(smtphost, HOSTLEN);
310 STR_FORCE(mda, MDALEN);
313 #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld
314 FLAG_FORCE(protocol);
317 FLAG_FORCE(fetchall);
318 FLAG_FORCE(norewrite);
321 FLAG_FORCE(authenticate);
326 (void) hostalloc(¤t);
329 void optmerge(struct query *h2, struct query *h1)
330 /* merge two options records; empty fields in h2 are filled in from h1 */
332 append_uid_list(&h2->localnames, &h1->localnames);
333 append_uid_list(&h2->aka, &h1->aka);
335 #define STR_MERGE(fld, len) if (*(h2->fld) == '\0') strcpy(h2->fld, h1->fld)
336 STR_MERGE(remotename, USERNAMELEN);
337 STR_MERGE(password, PASSWORDLEN);
338 STR_MERGE(mailbox, FOLDERLEN);
339 STR_MERGE(smtphost, HOSTLEN);
340 STR_MERGE(mda, MDALEN);
343 #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
344 FLAG_MERGE(protocol);
347 FLAG_MERGE(fetchall);
348 FLAG_MERGE(norewrite);
351 FLAG_MERGE(authenticate);
357 /* easier to do this than cope with variations in where the library lives */
358 int yywrap(void) {return 1;}
360 /* rcfile_y.y ends here */