3 * For license terms, see the file COPYING in this directory.
6 /***********************************************************************
9 programmer: Eric S. Raymond <esr@thyrsus.com>
10 description: fetchmail configuration file parser
12 ***********************************************************************/
16 #include <sys/types.h>
21 #include "fetchmail.h"
23 struct hostrec cmd_opts; /* where to put command-line info */
24 struct hostrec *hostlist; /* head of server list (globally visible) */
26 int yydebug; /* in case we didn't generate with -- debug */
28 static struct hostrec current; /* current server record */
29 static int prc_errflag;
38 %token DEFAULTS SERVER PROTOCOL AUTHENTICATE KPOP KERBEROS
39 %token USERNAME PASSWORD FOLDER SMTPHOST MDA IS HERE THERE
42 %token <flag> KEEP FLUSH FETCHALL REWRITE PORT SKIP
44 /* these are actually used by the lexer */
54 statement_list : statement
55 | statement_list statement
58 statement : define_server serverspecs userspecs
61 define_server : SERVER STRING {strcpy(current.servername, $2);}
62 | SKIP SERVER STRING {strcpy(current.servername, $3);
63 current.skip=($1==FLAG_TRUE);}
64 | DEFAULTS {strcpy(current.servername,"defaults");}
67 serverspecs : /* EMPTY */
68 | serverspecs serv_option
71 serv_option : PROTOCOL PROTO {current.protocol = $2;}
73 current.protocol = P_POP3;
74 current.authenticate = A_KERBEROS;
75 current.port = KPOP_PORT;
77 | PORT STRING {current.port = atoi($2);}
78 | SKIP {current.skip = ($1==FLAG_TRUE);}
79 | AUTHENTICATE PASSWORD {current.authenticate = A_PASSWORD;}
80 | AUTHENTICATE KERBEROS {current.authenticate = A_KERBEROS;}
83 /* the first and only the first user spec may omit the USERNAME part */
84 userspecs : user1opts {prc_register(); prc_reset();}
85 | user1opts explicits {prc_register(); prc_reset();}
89 explicits : explicitdef {prc_register(); prc_reset();}
90 | explicits explicitdef {prc_register(); prc_reset();}
93 explicitdef : userdef user0opts
96 userdef : USERNAME STRING {strcpy(current.remotename, $2);}
97 | USERNAME STRING HERE {strcpy(current.localname, $2);}
98 | USERNAME STRING THERE {strcpy(current.remotename, $2);}
101 user0opts : /* EMPTY */
102 | user0opts user_option
105 user1opts : user_option
106 | user1opts user_option
109 user_option : IS STRING {strcpy(current.localname, $2);}
110 | IS STRING HERE {strcpy(current.localname, $2);}
111 | IS STRING THERE {strcpy(current.remotename, $2);}
112 | PASSWORD STRING {strcpy(current.password, $2);}
113 | FOLDER STRING {strcpy(current.mailbox, $2);}
114 | SMTPHOST STRING {strcpy(current.smtphost, $2);}
115 | MDA STRING {strcpy(current.mda, $2);}
117 | KEEP {current.keep = ($1==FLAG_TRUE);}
118 | FLUSH {current.flush = ($1==FLAG_TRUE);}
119 | FETCHALL {current.fetchall = ($1==FLAG_TRUE);}
120 | REWRITE {current.norewrite = ($1==FLAG_TRUE);}
124 /* lexer interface */
126 extern int prc_lineno;
130 static struct hostrec *hosttail; /* where to add new elements */
132 /******************************************************************
134 description: report a syntax error
140 *****************************************************************/
145 fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
149 /******************************************************************
150 function: prc_filecheck
151 description: Check that a configuration file is secure
153 pathname pathname for the configuration file
155 ret. value: error code.
157 *****************************************************************/
159 int prc_filecheck(pathname)
164 /* the run control file must have the same uid as the REAL uid of this
165 process, it must have permissions no greater than 600, and it must not
166 be a symbolic link. We check these conditions here. */
169 if (lstat(pathname, &statbuf) < 0) {
178 if ((statbuf.st_mode & S_IFLNK) == S_IFLNK) {
179 fprintf(stderr, "File %s must not be a symbolic link.\n", pathname);
183 if (statbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
184 fprintf(stderr, "File %s must have no more than -rw------ permissions.\n",
189 if (statbuf.st_uid != getuid()) {
190 fprintf(stderr, "File %s must be owned by you.\n", pathname);
197 /******************************************************************
198 function: prc_parse_file
199 description: Read the contents of the configuration file, storing
200 each parsed record in a linked list.
202 pathname pathname for the configuration file
204 ret. value: error code.
205 globals: writes sp_head, writes hosttail, writes yyin,
206 writes rcfile, writes prc_errflag.
207 calls: prc_reset, yyparse.
208 *****************************************************************/
210 prc_parse_file (pathname)
214 hostlist = hosttail = (struct hostrec *)NULL;
217 /* Check that the file is secure */
218 if ((prc_errflag = prc_filecheck(pathname)) != 0)
224 /* Open the configuration and feed it to the lexer. */
225 if ((yyin = fopen(pathname,"r")) == (FILE *)NULL) {
230 yyparse(); /* parse entire file */
240 /******************************************************************
242 description: clear the global current record (server parameters)
246 globals: writes current.
248 *****************************************************************/
252 char savename[HOSTLEN+1];
253 int saveport, saveproto, saveauth;
256 * Purpose of this code is to initialize the new server block with
257 * the command-line data, but preserve whatever server name was
258 * previously set. Also preserve server options unless the
259 * command-line explicitly overrides them.
261 (void) strcpy(savename, current.servername);
262 saveport = current.port;
263 saveproto = current.protocol;
264 saveauth = current.authenticate;
266 memset(¤t, '\0', sizeof(current));
268 (void) strcpy(current.servername, savename);
269 current.protocol = saveproto;
270 current.authenticate = saveauth;
273 /******************************************************************
275 description: append a host record to the host list
277 init pointer to block containing initial values
278 ret. value: new record.
280 *****************************************************************/
282 struct hostrec *hostalloc(init)
283 struct hostrec *init;
285 struct hostrec *node;
287 /* allocate new node */
288 node = (struct hostrec *) xmalloc(sizeof(struct hostrec));
291 memcpy(node, init, sizeof(struct hostrec));
293 /* append to end of list */
294 if (hosttail != (struct hostrec *) 0)
295 hosttail->next = node; /* list contains at least one element */
297 hostlist = node; /* list is empty */
302 /******************************************************************
304 description: register the parsed server params by appending
305 them to a linked list of server param records.
308 globals: reads current.
310 *****************************************************************/
314 #define STR_FORCE(fld, len) if (cmd_opts.fld[0]) \
315 strcpy(current.fld, cmd_opts.fld)
316 STR_FORCE(localname, USERNAMELEN);
317 STR_FORCE(remotename, USERNAMELEN);
318 STR_FORCE(password, PASSWORDLEN);
319 STR_FORCE(mailbox, FOLDERLEN);
320 STR_FORCE(smtphost, HOSTLEN);
321 STR_FORCE(mda, MDALEN);
324 #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld
325 FLAG_FORCE(protocol);
328 FLAG_FORCE(fetchall);
329 FLAG_FORCE(norewrite);
332 FLAG_FORCE(authenticate);
335 (void) hostalloc(¤t);
338 /******************************************************************
340 description: Merge two options records.
341 Empty fields in h2 are filled in from h1.
346 globals: reads current_head.
349 *****************************************************************/
351 void optmerge(h2, h1)
355 #define STR_MERGE(fld, len) if (*(h2->fld) == '\0') strcpy(h2->fld, h1->fld)
356 STR_MERGE(localname, USERNAMELEN);
357 STR_MERGE(remotename, USERNAMELEN);
358 STR_MERGE(password, PASSWORDLEN);
359 STR_MERGE(mailbox, FOLDERLEN);
360 STR_MERGE(smtphost, HOSTLEN);
361 STR_MERGE(mda, MDALEN);
364 #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
365 FLAG_MERGE(protocol);
368 FLAG_MERGE(fetchall);
369 FLAG_MERGE(norewrite);
372 FLAG_MERGE(authenticate);