]> Pileus Git - ~andy/fetchmail/blobdiff - rcfile_y.y
Dave Bodenstab's fixes.
[~andy/fetchmail] / rcfile_y.y
index 62ca5ef02003c114903a7e148dea867a6ce2ed65..693bcb9edd45b4ce3a8ef7f71b11b2078580d43b 100644 (file)
@@ -29,6 +29,9 @@ int yydebug;  /* in case we didn't generate with -- debug */
 
 static struct query current;           /* current server record */
 static int prc_errflag;
+
+static void prc_register();
+static void prc_reset();
 %}
 
 %union {
@@ -38,12 +41,15 @@ static int prc_errflag;
   char *sval;
 }
 
-%token DEFAULTS SERVER PROTOCOL AUTHENTICATE TIMEOUT KPOP KERBEROS
-%token USERNAME PASSWORD FOLDER SMTPHOST MDA IS HERE THERE TO MAP LIMIT
+%token DEFAULTS POLL SKIP AKA LOCALDOMAINS PROTOCOL
+%token AUTHENTICATE TIMEOUT KPOP KERBEROS
+%token ENVELOPE USERNAME PASSWORD FOLDER SMTPHOST MDA PRECONNECT LIMIT
+%token IS HERE THERE TO MAP WILDCARD
+%token SET BATCHLIMIT FETCHLIMIT LOGFILE INTERFACE MONITOR
 %token <proto> PROTO
 %token <sval>  STRING
 %token <number> NUMBER
-%token <flag>  KEEP FLUSH FETCHALL REWRITE PORT SKIP
+%token <flag>  KEEP FLUSH FETCHALL REWRITE STRIPCR DNS PORT
 
 /* these are actually used by the lexer */
 %token FLAG_TRUE       2
@@ -59,33 +65,80 @@ statement_list      : statement
                | statement_list statement
                ;
 
-statement      : define_server serverspecs userspecs      
+/* future global options should also have the form SET <name> <value> */
+statement      : SET LOGFILE MAP STRING        {logfile = xstrdup($4);}
+
+/* 
+ * The way the next two productions are written depends on the fact that
+ * userspecs cannot be empty.  It's a kluge to deal with files that set
+ * up a load of defaults and then have poll statements following with no
+ * user options at all. 
+ */
+               | define_server serverspecs     {prc_register(); prc_reset();}
+               | define_server serverspecs userspecs
+                               {
+                                       memset(&current,'\0',sizeof(current));
+                                       current.stripcr = -1;
+                               }
                ;
 
-define_server  : SERVER STRING         {strcpy(current.servername, $2);}
-               | SKIP SERVER STRING    {strcpy(current.servername, $3);
-                                               current.skip=($1==FLAG_TRUE);}
-               | DEFAULTS      {strcpy(current.servername,"defaults");}
+define_server  : POLL STRING   {current.server.names = (struct idlist *)NULL;
+                                       save_str(&current.server.names, -1,$2);
+                                       current.server.skip = FALSE;}
+               | SKIP STRING   {current.server.names = (struct idlist *)NULL;
+                                       save_str(&current.server.names, -1,$2);
+                                       current.server.skip = TRUE;}
+               | DEFAULTS      {current.server.names = (struct idlist *)NULL;
+                                       save_str(&current.server.names, -1,"defaults");}
                ;
 
 serverspecs    : /* EMPTY */
                | serverspecs serv_option
                ;
 
-serv_option    : PROTOCOL PROTO        {current.protocol = $2;}
+alias_list     : STRING                {save_str(&current.server.names,-1,$1);}
+               | alias_list STRING     {save_str(&current.server.names,-1,$2);}
+               ;
+
+domain_list    : STRING                {save_str(&current.server.localdomains,-1,$1);}
+               | domain_list STRING    {save_str(&current.server.localdomains,-1,$2);}
+               ;
+
+serv_option    : AKA alias_list
+               | LOCALDOMAINS domain_list
+               | PROTOCOL PROTO        {current.server.protocol = $2;}
                | PROTOCOL KPOP         {
-                                           current.protocol = P_POP3;
-                                           current.authenticate = A_KERBEROS;
-                                           current.port = KPOP_PORT;
+                                           current.server.protocol = P_POP3;
+                                           current.server.authenticate = A_KERBEROS;
+                                           current.server.port = KPOP_PORT;
+                                       }
+               | PORT NUMBER           {current.server.port = $2;}
+               | AUTHENTICATE PASSWORD {current.server.authenticate = A_PASSWORD;}
+               | AUTHENTICATE KERBEROS {current.server.authenticate = A_KERBEROS;}
+               | TIMEOUT NUMBER        {current.server.timeout = $2;}
+               | ENVELOPE STRING       {current.server.envelope = xstrdup($2);}
+               | INTERFACE STRING      {
+#ifdef linux
+                                       interface_parse($2, &current.server);
+#else
+                                       fprintf(stderr, "fetchmail: interface option is only supported under Linux\n");
+#endif /* linux */
                                        }
-               | PORT NUMBER           {current.port = $2;}
-               | SKIP                  {current.skip = ($1==FLAG_TRUE);}
-               | AUTHENTICATE PASSWORD {current.authenticate = A_PASSWORD;}
-               | AUTHENTICATE KERBEROS {current.authenticate = A_KERBEROS;}
-               | TIMEOUT NUMBER        {current.timeout = $2;}
+               | MONITOR STRING        {
+#ifdef linux
+                                       current.server.monitor = xstrdup($2);
+#else
+                                       fprintf(stderr, "fetchmail: monitor option is only supported under Linux\n");
+#endif /* linux */
+                                       }
+               | DNS                   {current.server.no_dns = ($1==FLAG_FALSE);}
                ;
 
-/* the first and only the first user spec may omit the USERNAME part */
+/*
+ * The first and only the first user spec may omit the USERNAME part.
+ * This is a backward-compatibility kluge to allow old popclient files
+ * to keep working.
+ */
 userspecs      : user1opts             {prc_register(); prc_reset();}
                | user1opts explicits   {prc_register(); prc_reset();}
                | explicits
@@ -98,9 +151,9 @@ explicits    : explicitdef           {prc_register(); prc_reset();}
 explicitdef    : userdef user0opts
                ;
 
-userdef                : USERNAME STRING       {strcpy(current.remotename, $2);}
+userdef                : USERNAME STRING       {current.remotename = xstrdup($2);}
                | USERNAME mapping_list HERE
-               | USERNAME STRING THERE {strcpy(current.remotename, $2);}
+               | USERNAME STRING THERE {current.remotename = xstrdup($2);}
                ;
 
 user0opts      : /* EMPTY */
@@ -111,31 +164,41 @@ user1opts : user_option
                | user1opts user_option
                ;
 
+localnames     : WILDCARD              {current.wildcard =  TRUE;}
+               | mapping_list          {current.wildcard =  FALSE;}
+               | mapping_list WILDCARD {current.wildcard =  TRUE;}
+               ;
+
 mapping_list   : mapping               
                | mapping_list mapping
                ;
 
 mapping                : STRING        
-                               {save_id_pair(&current.localnames, $1, NULL);}
+                               {save_str_pair(&current.localnames, $1, NULL);}
                | STRING MAP STRING
-                               {save_id_pair(&current.localnames, $1, $3);}
+                               {save_str_pair(&current.localnames, $1, $3);}
                ;
 
-user_option    : TO mapping_list HERE
-               | TO mapping_list
-               | IS mapping_list HERE
-               | IS mapping_list
-               | IS STRING THERE       {strcpy(current.remotename, $2);}
-               | PASSWORD STRING       {strcpy(current.password, $2);}
-               | FOLDER STRING         {strcpy(current.mailbox, $2);}
-               | SMTPHOST STRING       {strcpy(current.smtphost, $2);}
-               | MDA STRING            {strcpy(current.mda, $2);}
+user_option    : TO localnames HERE
+               | TO localnames
+               | IS localnames HERE
+               | IS localnames
+
+               | IS STRING THERE       {current.remotename = xstrdup($2);}
+               | PASSWORD STRING       {current.password = xstrdup($2);}
+               | FOLDER STRING         {current.mailbox = xstrdup($2);}
+               | SMTPHOST STRING       {current.smtphost = xstrdup($2);}
+               | MDA STRING            {current.mda = xstrdup($2);}
+               | PRECONNECT STRING     {current.preconnect = xstrdup($2);}
 
                | KEEP                  {current.keep = ($1==FLAG_TRUE);}
                | FLUSH                 {current.flush = ($1==FLAG_TRUE);}
                | FETCHALL              {current.fetchall = ($1==FLAG_TRUE);}
-               | REWRITE               {current.norewrite = ($1==FLAG_TRUE);}
+               | REWRITE               {current.no_rewrite =($1==FLAG_FALSE);}
+               | STRIPCR               {current.stripcr = ($1==FLAG_TRUE);}
                | LIMIT NUMBER          {current.limit = $2;}
+               | FETCHLIMIT NUMBER     {current.fetchlimit = $2;}
+               | BATCHLIMIT NUMBER     {current.batchlimit = $2;}
                ;
 %%
 
@@ -147,12 +210,11 @@ extern FILE *yyin;
 
 static struct query *hosttail; /* where to add new elements */
 
-void yyerror (s)
+void yyerror (const char *s)
 /* report a syntax error */
-const char *s; /* error string */
 {
-  fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
-  prc_errflag++;
+    fprintf(stderr,"%s line %d: %s at %s\n", rcfile, prc_lineno, s, yytext);
+    prc_errflag++;
 }
 
 int prc_filecheck(pathname)
@@ -170,7 +232,7 @@ const char *pathname;               /* pathname for the configuration file */
        if (errno == ENOENT) 
            return(0);
        else {
-           perror(pathname);
+           error(0, errno, "lstat: %s", pathname);
            return(PS_IOERR);
        }
     }
@@ -211,7 +273,7 @@ const char *pathname;               /* pathname for the configuration file */
 
     /* Open the configuration and feed it to the lexer. */
     if ((yyin = fopen(pathname,"r")) == (FILE *)NULL) {
-       perror(pathname);
+       error(0, errno, "open: %s", pathname);
        return(PS_IOERR);
     }
 
@@ -225,28 +287,22 @@ const char *pathname;             /* pathname for the configuration file */
        return(0);
 }
 
-void prc_reset()
+static void prc_reset(void)
 /* clear the global current record (server parameters) used by the parser */
 {
-    char       savename[HOSTLEN+1];
-    int                saveport, saveproto, saveauth;
+    struct hostdata save;
 
     /*
-     * Purpose of this code is to initialize the new server block with
-     * the command-line data, but preserve whatever server name was
-     * previously set.  Also preserve server options unless the
-     * command-line explicitly overrides them.
+     * Purpose of this code is to initialize the new server block, but
+     * preserve whatever server name was previously set.  Also
+     * preserve server options unless the command-line explicitly
+     * overrides them.
      */
-    (void) strcpy(savename, current.servername);
-    saveport = current.port;
-    saveproto = current.protocol;
-    saveauth = current.authenticate;
+    save = current.server;
 
     memset(&current, '\0', sizeof(current));
 
-    (void) strcpy(current.servername, savename);
-    current.protocol = saveproto;
-    current.authenticate = saveauth;
+    current.server = save;
 }
 
 struct query *hostalloc(init)
@@ -270,65 +326,85 @@ struct query *init;       /* pointer to block containing initial values */
     return(node);
 }
 
-void prc_register()
+static void prc_register(void)
 /* register current parameters and append to the host list */
 {
-#define STR_FORCE(fld, len) if (cmd_opts.fld[0]) \
-                                       strcpy(current.fld, cmd_opts.fld)
-    STR_FORCE(remotename, USERNAMELEN);
-    STR_FORCE(password, PASSWORDLEN);
-    STR_FORCE(mailbox, FOLDERLEN);
-    STR_FORCE(smtphost, HOSTLEN);
-    STR_FORCE(mda, MDALEN);
-#undef STR_FORCE
-    
 #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld
-    FLAG_FORCE(protocol);
+    FLAG_FORCE(server.protocol);
+    FLAG_FORCE(server.port);
+    FLAG_FORCE(server.authenticate);
+    FLAG_FORCE(server.timeout);
+    FLAG_FORCE(server.envelope);
+    FLAG_FORCE(server.skip);
+    FLAG_FORCE(server.no_dns);
+
+#ifdef linux
+    FLAG_FORCE(server.interface);
+    FLAG_FORCE(server.monitor);
+    FLAG_FORCE(server.interface_pair);
+#endif /* linux */
+
+    FLAG_FORCE(remotename);
+    FLAG_FORCE(password);
+    FLAG_FORCE(mailbox);
+    FLAG_FORCE(smtphost);
+    FLAG_FORCE(mda);
+    FLAG_FORCE(preconnect);
+
     FLAG_FORCE(keep);
     FLAG_FORCE(flush);
     FLAG_FORCE(fetchall);
-    FLAG_FORCE(norewrite);
-    FLAG_FORCE(skip);
-    FLAG_FORCE(port);
-    FLAG_FORCE(authenticate);
-    FLAG_FORCE(timeout);
+    FLAG_FORCE(no_rewrite);
+    FLAG_FORCE(stripcr);
     FLAG_FORCE(limit);
+    FLAG_FORCE(fetchlimit);
+    FLAG_FORCE(batchlimit);
+
 #undef FLAG_FORCE
 
     (void) hostalloc(&current);
 }
 
-void optmerge(h2, h1)
+void optmerge(struct query *h2, struct query *h1)
 /* merge two options records; empty fields in h2 are filled in from h1 */
-struct query *h1;
-struct query *h2;
 {
-    append_uid_list(&h2->localnames, &h1->localnames);
-
-#define STR_MERGE(fld, len) if (*(h2->fld) == '\0') strcpy(h2->fld, h1->fld)
-    STR_MERGE(remotename, USERNAMELEN);
-    STR_MERGE(password, PASSWORDLEN);
-    STR_MERGE(mailbox, FOLDERLEN);
-    STR_MERGE(smtphost, HOSTLEN);
-    STR_MERGE(mda, MDALEN);
-#undef STR_MERGE
+    append_str_list(&h2->server.localdomains, &h1->server.localdomains);
+    append_str_list(&h2->localnames, &h1->localnames);
 
 #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
-    FLAG_MERGE(protocol);
+    FLAG_MERGE(server.protocol);
+    FLAG_MERGE(server.port);
+    FLAG_MERGE(server.authenticate);
+    FLAG_MERGE(server.timeout);
+    FLAG_MERGE(server.envelope);
+    FLAG_MERGE(server.skip);
+    FLAG_MERGE(server.no_dns);
+
+#ifdef linux
+    FLAG_MERGE(server.interface);
+    FLAG_MERGE(server.monitor);
+    FLAG_MERGE(server.interface_pair);
+#endif /* linux */
+
+    FLAG_MERGE(remotename);
+    FLAG_MERGE(password);
+    FLAG_MERGE(mailbox);
+    FLAG_MERGE(smtphost);
+    FLAG_MERGE(mda);
+    FLAG_MERGE(preconnect);
+
     FLAG_MERGE(keep);
     FLAG_MERGE(flush);
     FLAG_MERGE(fetchall);
-    FLAG_MERGE(norewrite);
-    FLAG_MERGE(skip);
-    FLAG_MERGE(port);
-    FLAG_MERGE(authenticate);
-    FLAG_MERGE(timeout);
+    FLAG_MERGE(no_rewrite);
+    FLAG_MERGE(stripcr);
     FLAG_MERGE(limit);
+    FLAG_MERGE(fetchlimit);
+    FLAG_MERGE(batchlimit);
 #undef FLAG_MERGE
-
 }
 
 /* easier to do this than cope with variations in where the library lives */
-int yywrap() {return 1;}
+int yywrap(void) {return 1;}
 
 /* rcfile_y.y ends here */