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 #include "fetchmail.h"
17 struct hostrec cmd_opts; /* where to put command-line info */
18 struct hostrec *hostlist; /* head of server list (globally visible) */
20 int yydebug; /* in case we didn't generate with -- debug */
22 static struct hostrec current; /* current server record */
23 static int prc_errflag;
33 %token DEFAULTS SERVER PROTOCOL AUTHENTICATE TIMEOUT KPOP KERBEROS
34 %token USERNAME PASSWORD FOLDER SMTPHOST MDA IS HERE THERE TO MAP
37 %token <number> NUMBER
38 %token <flag> KEEP FLUSH FETCHALL REWRITE PORT SKIP
40 /* these are actually used by the lexer */
50 statement_list : statement
51 | statement_list statement
54 statement : define_server serverspecs userspecs
57 define_server : SERVER STRING {strcpy(current.servername, $2);}
58 | SKIP SERVER STRING {strcpy(current.servername, $3);
59 current.skip=($1==FLAG_TRUE);}
60 | DEFAULTS {strcpy(current.servername,"defaults");}
63 serverspecs : /* EMPTY */
64 | serverspecs serv_option
67 serv_option : PROTOCOL PROTO {current.protocol = $2;}
69 current.protocol = P_POP3;
70 current.authenticate = A_KERBEROS;
71 current.port = KPOP_PORT;
73 | PORT NUMBER {current.port = $2;}
74 | SKIP {current.skip = ($1==FLAG_TRUE);}
75 | AUTHENTICATE PASSWORD {current.authenticate = A_PASSWORD;}
76 | AUTHENTICATE KERBEROS {current.authenticate = A_KERBEROS;}
77 | TIMEOUT NUMBER {current.timeout = $2;}
80 /* the first and only the first user spec may omit the USERNAME part */
81 userspecs : user1opts {prc_register(); prc_reset();}
82 | user1opts explicits {prc_register(); prc_reset();}
86 explicits : explicitdef {prc_register(); prc_reset();}
87 | explicits explicitdef {prc_register(); prc_reset();}
90 explicitdef : userdef user0opts
93 userdef : USERNAME STRING {strcpy(current.remotename, $2);}
94 | USERNAME mapping_list HERE
95 | USERNAME STRING THERE {strcpy(current.remotename, $2);}
98 user0opts : /* EMPTY */
99 | user0opts user_option
102 user1opts : user_option
103 | user1opts user_option
106 mapping_list : mapping
107 | mapping_list mapping
111 {save_id_pair(¤t.localnames, $1, NULL);}
113 {save_id_pair(¤t.localnames, $1, $3);}
116 user_option : TO mapping_list HERE
118 | IS mapping_list HERE
120 | IS STRING THERE {strcpy(current.remotename, $2);}
121 | PASSWORD STRING {strcpy(current.password, $2);}
122 | FOLDER STRING {strcpy(current.mailbox, $2);}
123 | SMTPHOST STRING {strcpy(current.smtphost, $2);}
124 | MDA STRING {strcpy(current.mda, $2);}
126 | KEEP {current.keep = ($1==FLAG_TRUE);}
127 | FLUSH {current.flush = ($1==FLAG_TRUE);}
128 | FETCHALL {current.fetchall = ($1==FLAG_TRUE);}
129 | REWRITE {current.norewrite = ($1==FLAG_TRUE);}
133 /* lexer interface */
135 extern int prc_lineno;
139 static struct hostrec *hosttail; /* where to add new elements */
142 /* report a syntax error */
143 char *s; /* error string */
145 fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
149 int prc_filecheck(pathname)
150 /* check that a configuration file is secure */
151 char *pathname; /* pathname for the configuration file */
155 /* the run control file must have the same uid as the REAL uid of this
156 process, it must have permissions no greater than 600, and it must not
157 be a symbolic link. We check these conditions here. */
160 if (lstat(pathname, &statbuf) < 0) {
169 if ((statbuf.st_mode & S_IFLNK) == S_IFLNK) {
170 fprintf(stderr, "File %s must not be a symbolic link.\n", pathname);
174 if (statbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
175 fprintf(stderr, "File %s must have no more than -rw------ permissions.\n",
180 if (statbuf.st_uid != getuid()) {
181 fprintf(stderr, "File %s must be owned by you.\n", pathname);
188 prc_parse_file (pathname)
189 /* digest the configuration into a linked list of host records */
190 char *pathname; /* pathname for the configuration file */
193 hostlist = hosttail = (struct hostrec *)NULL;
196 /* Check that the file is secure */
197 if ((prc_errflag = prc_filecheck(pathname)) != 0)
203 /* Open the configuration and feed it to the lexer. */
204 if ((yyin = fopen(pathname,"r")) == (FILE *)NULL) {
209 yyparse(); /* parse entire file */
220 /* clear the global current record (server parameters) used by the parser */
222 char savename[HOSTLEN+1];
223 int saveport, saveproto, saveauth;
226 * Purpose of this code is to initialize the new server block with
227 * the command-line data, but preserve whatever server name was
228 * previously set. Also preserve server options unless the
229 * command-line explicitly overrides them.
231 (void) strcpy(savename, current.servername);
232 saveport = current.port;
233 saveproto = current.protocol;
234 saveauth = current.authenticate;
236 memset(¤t, '\0', sizeof(current));
238 (void) strcpy(current.servername, savename);
239 current.protocol = saveproto;
240 current.authenticate = saveauth;
243 struct hostrec *hostalloc(init)
244 /* append a host record to the host list */
245 struct hostrec *init; /* pointer to block containing initial values */
247 struct hostrec *node;
249 /* allocate new node */
250 node = (struct hostrec *) xmalloc(sizeof(struct hostrec));
253 memcpy(node, init, sizeof(struct hostrec));
255 /* append to end of list */
256 if (hosttail != (struct hostrec *) 0)
257 hosttail->next = node; /* list contains at least one element */
259 hostlist = node; /* list is empty */
265 /* register current parameters and append to the host list */
267 #define STR_FORCE(fld, len) if (cmd_opts.fld[0]) \
268 strcpy(current.fld, cmd_opts.fld)
269 STR_FORCE(remotename, USERNAMELEN);
270 STR_FORCE(password, PASSWORDLEN);
271 STR_FORCE(mailbox, FOLDERLEN);
272 STR_FORCE(smtphost, HOSTLEN);
273 STR_FORCE(mda, MDALEN);
276 #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld
277 FLAG_FORCE(protocol);
280 FLAG_FORCE(fetchall);
281 FLAG_FORCE(norewrite);
284 FLAG_FORCE(authenticate);
288 (void) hostalloc(¤t);
291 void optmerge(h2, h1)
292 /* merge two options records; empty fields in h2 are filled in from h1 */
298 append_uid_list(&h2->localnames, &h1->localnames);
300 #define STR_MERGE(fld, len) if (*(h2->fld) == '\0') strcpy(h2->fld, h1->fld)
301 STR_MERGE(remotename, USERNAMELEN);
302 STR_MERGE(password, PASSWORDLEN);
303 STR_MERGE(mailbox, FOLDERLEN);
304 STR_MERGE(smtphost, HOSTLEN);
305 STR_MERGE(mda, MDALEN);
308 #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
309 FLAG_MERGE(protocol);
312 FLAG_MERGE(fetchall);
313 FLAG_MERGE(norewrite);
316 FLAG_MERGE(authenticate);
322 /* easier to do this than cope with variations in where the library lives */
323 int yywrap() {return 1;}
325 /* rcfile_y.y ends here */