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 SERVER PROTOCOL AUTHENTICATE TIMEOUT KPOP KERBEROS
45 %token USERNAME PASSWORD FOLDER SMTPHOST MDA IS HERE THERE TO MAP LIMIT
48 %token <number> NUMBER
49 %token <flag> KEEP FLUSH FETCHALL REWRITE PORT SKIP
51 /* these are actually used by the lexer */
61 statement_list : statement
62 | statement_list statement
65 statement : define_server serverspecs userspecs
68 define_server : SERVER STRING {strcpy(current.servername, $2);}
69 | SKIP SERVER STRING {strcpy(current.servername, $3);
70 current.skip=($1==FLAG_TRUE);}
71 | DEFAULTS {strcpy(current.servername,"defaults");}
74 serverspecs : /* EMPTY */
75 | serverspecs serv_option
78 serv_option : PROTOCOL PROTO {current.protocol = $2;}
80 current.protocol = P_POP3;
81 current.authenticate = A_KERBEROS;
82 current.port = KPOP_PORT;
84 | PORT NUMBER {current.port = $2;}
85 | SKIP {current.skip = ($1==FLAG_TRUE);}
86 | AUTHENTICATE PASSWORD {current.authenticate = A_PASSWORD;}
87 | AUTHENTICATE KERBEROS {current.authenticate = A_KERBEROS;}
88 | TIMEOUT NUMBER {current.timeout = $2;}
91 /* the first and only the first user spec may omit the USERNAME part */
92 userspecs : user1opts {prc_register(); prc_reset();}
93 | user1opts explicits {prc_register(); prc_reset();}
97 explicits : explicitdef {prc_register(); prc_reset();}
98 | explicits explicitdef {prc_register(); prc_reset();}
101 explicitdef : userdef user0opts
104 userdef : USERNAME STRING {strcpy(current.remotename, $2);}
105 | USERNAME mapping_list HERE
106 | USERNAME STRING THERE {strcpy(current.remotename, $2);}
109 user0opts : /* EMPTY */
110 | user0opts user_option
113 user1opts : user_option
114 | user1opts user_option
117 mapping_list : mapping
118 | mapping_list mapping
122 {save_id_pair(¤t.localnames, $1, NULL);}
124 {save_id_pair(¤t.localnames, $1, $3);}
127 user_option : TO mapping_list HERE
129 | IS mapping_list HERE
131 | IS STRING THERE {strcpy(current.remotename, $2);}
132 | PASSWORD STRING {strcpy(current.password, $2);}
133 | FOLDER STRING {strcpy(current.mailbox, $2);}
134 | SMTPHOST STRING {strcpy(current.smtphost, $2);}
135 | MDA STRING {strcpy(current.mda, $2);}
137 | KEEP {current.keep = ($1==FLAG_TRUE);}
138 | FLUSH {current.flush = ($1==FLAG_TRUE);}
139 | FETCHALL {current.fetchall = ($1==FLAG_TRUE);}
140 | REWRITE {current.norewrite = ($1==FLAG_TRUE);}
141 | LIMIT NUMBER {current.limit = $2;}
145 /* lexer interface */
147 extern int prc_lineno;
151 static struct query *hosttail; /* where to add new elements */
154 /* report a syntax error */
155 const char *s; /* error string */
157 fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
161 int prc_filecheck(pathname)
162 /* check that a configuration file is secure */
163 const char *pathname; /* pathname for the configuration file */
167 /* the run control file must have the same uid as the REAL uid of this
168 process, it must have permissions no greater than 600, and it must not
169 be a symbolic link. We check these conditions here. */
172 if (lstat(pathname, &statbuf) < 0) {
181 if ((statbuf.st_mode & S_IFLNK) == S_IFLNK) {
182 fprintf(stderr, "File %s must not be a symbolic link.\n", pathname);
186 if (statbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
187 fprintf(stderr, "File %s must have no more than -rw------ permissions.\n",
192 if (statbuf.st_uid != getuid()) {
193 fprintf(stderr, "File %s must be owned by you.\n", pathname);
200 int prc_parse_file (pathname)
201 /* digest the configuration into a linked list of host records */
202 const char *pathname; /* pathname for the configuration file */
205 querylist = hosttail = (struct query *)NULL;
208 /* Check that the file is secure */
209 if ((prc_errflag = prc_filecheck(pathname)) != 0)
215 /* Open the configuration and feed it to the lexer. */
216 if ((yyin = fopen(pathname,"r")) == (FILE *)NULL) {
221 yyparse(); /* parse entire file */
231 static void prc_reset()
232 /* clear the global current record (server parameters) used by the parser */
234 char savename[HOSTLEN+1];
235 int saveport, saveproto, saveauth;
238 * Purpose of this code is to initialize the new server block with
239 * the command-line data, but preserve whatever server name was
240 * previously set. Also preserve server options unless the
241 * command-line explicitly overrides them.
243 (void) strcpy(savename, current.servername);
244 saveport = current.port;
245 saveproto = current.protocol;
246 saveauth = current.authenticate;
248 memset(¤t, '\0', sizeof(current));
250 (void) strcpy(current.servername, savename);
251 current.protocol = saveproto;
252 current.authenticate = saveauth;
255 struct query *hostalloc(init)
256 /* append a host record to the host list */
257 struct query *init; /* pointer to block containing initial values */
261 /* allocate new node */
262 node = (struct query *) xmalloc(sizeof(struct query));
265 memcpy(node, init, sizeof(struct query));
267 /* append to end of list */
268 if (hosttail != (struct query *) 0)
269 hosttail->next = node; /* list contains at least one element */
271 querylist = node; /* list is empty */
276 static void prc_register()
277 /* register current parameters and append to the host list */
279 #define STR_FORCE(fld, len) if (cmd_opts.fld[0]) \
280 strcpy(current.fld, cmd_opts.fld)
281 STR_FORCE(remotename, USERNAMELEN);
282 STR_FORCE(password, PASSWORDLEN);
283 STR_FORCE(mailbox, FOLDERLEN);
284 STR_FORCE(smtphost, HOSTLEN);
285 STR_FORCE(mda, MDALEN);
288 #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld
289 FLAG_FORCE(protocol);
292 FLAG_FORCE(fetchall);
293 FLAG_FORCE(norewrite);
296 FLAG_FORCE(authenticate);
301 (void) hostalloc(¤t);
304 void optmerge(h2, h1)
305 /* merge two options records; empty fields in h2 are filled in from h1 */
309 append_uid_list(&h2->localnames, &h1->localnames);
311 #define STR_MERGE(fld, len) if (*(h2->fld) == '\0') strcpy(h2->fld, h1->fld)
312 STR_MERGE(remotename, USERNAMELEN);
313 STR_MERGE(password, PASSWORDLEN);
314 STR_MERGE(mailbox, FOLDERLEN);
315 STR_MERGE(smtphost, HOSTLEN);
316 STR_MERGE(mda, MDALEN);
319 #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
320 FLAG_MERGE(protocol);
323 FLAG_MERGE(fetchall);
324 FLAG_MERGE(norewrite);
327 FLAG_MERGE(authenticate);
334 /* easier to do this than cope with variations in where the library lives */
335 int yywrap() {return 1;}
337 /* rcfile_y.y ends here */