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 LIMIT
46 %token IS HERE THERE TO MAP WILDCARD
47 %token SET BATCHLIMIT LOGFILE
50 %token <number> NUMBER
51 %token <flag> KEEP FLUSH FETCHALL REWRITE PORT
53 /* these are actually used by the lexer */
63 statement_list : statement
64 | statement_list statement
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);}
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.
77 | define_server serverspecs {prc_register(); prc_reset();}
78 | define_server serverspecs userspecs
81 define_server : POLL STRING {current.servernames = (struct idlist *)NULL;
82 save_str(¤t.servernames, -1, $2);
83 current.skip = FALSE;}
84 | SKIP STRING {current.servernames = (struct idlist *)NULL;
85 save_str(¤t.servernames, -1, $2);
87 | DEFAULTS {current.servernames = (struct idlist *)NULL;
88 save_str(¤t.servernames, -1,"defaults");}
91 serverspecs : /* EMPTY */
92 | serverspecs serv_option
95 alias_list : STRING {save_str(¤t.servernames, -1, $1);}
96 | alias_list STRING {save_str(¤t.servernames, -1, $2);}
99 serv_option : AKA alias_list
100 | PROTOCOL PROTO {current.protocol = $2;}
102 current.protocol = P_POP3;
103 current.authenticate = A_KERBEROS;
104 current.port = KPOP_PORT;
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;}
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
117 userspecs : user1opts {prc_register(); prc_reset();}
118 | user1opts explicits {prc_register(); prc_reset();}
122 explicits : explicitdef {prc_register(); prc_reset();}
123 | explicits explicitdef {prc_register(); prc_reset();}
126 explicitdef : userdef user0opts
129 userdef : USERNAME STRING {strcpy(current.remotename, $2);}
130 | USERNAME mapping_list HERE
131 | USERNAME STRING THERE {strcpy(current.remotename, $2);}
134 user0opts : /* EMPTY */
135 | user0opts user_option
138 user1opts : user_option
139 | user1opts user_option
142 localnames : WILDCARD {current.wildcard = TRUE;}
143 | mapping_list {current.wildcard = FALSE;}
144 | mapping_list WILDCARD {current.wildcard = TRUE;}
147 mapping_list : mapping
148 | mapping_list mapping
152 {save_str_pair(¤t.localnames, $1, NULL);}
154 {save_str_pair(¤t.localnames, $1, $3);}
157 user_option : TO localnames HERE
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);}
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;}
176 /* lexer interface */
178 extern int prc_lineno;
182 static struct query *hosttail; /* where to add new elements */
184 void yyerror (const char *s)
185 /* report a syntax error */
187 fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
191 int prc_filecheck(pathname)
192 /* check that a configuration file is secure */
193 const char *pathname; /* pathname for the configuration file */
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. */
202 if (lstat(pathname, &statbuf) < 0) {
211 if ((statbuf.st_mode & S_IFLNK) == S_IFLNK) {
212 fprintf(stderr, "File %s must not be a symbolic link.\n", pathname);
216 if (statbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
217 fprintf(stderr, "File %s must have no more than -rw------ permissions.\n",
222 if (statbuf.st_uid != getuid()) {
223 fprintf(stderr, "File %s must be owned by you.\n", pathname);
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 */
235 querylist = hosttail = (struct query *)NULL;
238 /* Check that the file is secure */
239 if ((prc_errflag = prc_filecheck(pathname)) != 0)
245 /* Open the configuration and feed it to the lexer. */
246 if ((yyin = fopen(pathname,"r")) == (FILE *)NULL) {
251 yyparse(); /* parse entire file */
261 static void prc_reset(void)
262 /* clear the global current record (server parameters) used by the parser */
264 int saveport, saveproto, saveauth, saveskip;
265 struct idlist *saveservernames;
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
273 saveport = current.port;
274 saveproto = current.protocol;
275 saveauth = current.authenticate;
276 saveskip = current.skip;
277 saveservernames = current.servernames;
279 memset(¤t, '\0', sizeof(current));
281 current.protocol = saveproto;
282 current.authenticate = saveauth;
283 current.skip = saveskip;
284 current.servernames = saveservernames;
287 struct query *hostalloc(init)
288 /* append a host record to the host list */
289 struct query *init; /* pointer to block containing initial values */
293 /* allocate new node */
294 node = (struct query *) xmalloc(sizeof(struct query));
297 memcpy(node, init, sizeof(struct query));
299 /* append to end of list */
300 if (hosttail != (struct query *) 0)
301 hosttail->next = node; /* list contains at least one element */
303 querylist = node; /* list is empty */
308 static void prc_register(void)
309 /* register current parameters and append to the host list */
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);
320 #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld
321 FLAG_FORCE(protocol);
324 FLAG_FORCE(fetchall);
325 FLAG_FORCE(norewrite);
328 FLAG_FORCE(authenticate);
333 (void) hostalloc(¤t);
336 void optmerge(struct query *h2, struct query *h1)
337 /* merge two options records; empty fields in h2 are filled in from h1 */
339 append_str_list(&h2->localnames, &h1->localnames);
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);
349 #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
350 FLAG_MERGE(protocol);
353 FLAG_MERGE(fetchall);
354 FLAG_MERGE(norewrite);
357 FLAG_MERGE(authenticate);
363 /* easier to do this than cope with variations in where the library lives */
364 int yywrap(void) {return 1;}
366 /* rcfile_y.y ends here */