/[imapfilter]/imapfilter/file.c
ViewVC logotype

Diff of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.26.2.2 by lefcha, Mon Jan 21 15:45:02 2002 UTC revision 1.63 by lefcha, Fri Feb 13 12:17:15 2004 UTC
# Line 1  Line 1 
1  #include <stdio.h>  #include <stdio.h>
2  #include <errno.h>  #include <unistd.h>
 #include <sys/types.h>  
 #include <regex.h>  
3  #include <string.h>  #include <string.h>
4  #include <stdlib.h>  #include <errno.h>
5  #include <limits.h>  #include <limits.h>
6    #include <sys/types.h>
7  #include <sys/stat.h>  #include <sys/stat.h>
8    #include <fcntl.h>
9    
10  #include "config.h"  #include "config.h"
11  #include "imapfilter.h"  #include "imapfilter.h"
12  #include "data.h"  #include "pathnames.h"
13    
14    
15    extern char *home;
16    extern options_t opts;
17    
18    
19    /*
20     * Create imapfilter's home directory.
21     */
22    int
23    create_homedir(void)
24    {
25            char hd[PATH_MAX];
26    
27            snprintf(hd, PATH_MAX, "%s/%s", home, PATHNAME_HOME);
28    
29            if (!exists_dir(hd)) {
30                    if (mkdir(hd, S_IRUSR | S_IWUSR | S_IXUSR))
31                            error("could not create directory %s; %s\n", hd,
32                                strerror(errno));
33            } else {
34                    check_dir_perms(hd, S_IRUSR | S_IWUSR | S_IXUSR);
35            }
36            return 0;
37    }
38    
39    
40    /*
41     * Check if a file exists.
42     */
43    int
44    exists_file(char *fname)
45    {
46            struct stat fs;
47    
48  extern char logfile[PATH_MAX];          if (access(fname, F_OK))
49  extern unsigned int options;                  return 0;
50    
51  long timeout = -1;              /* Server non-response timeout in seconds. */          stat(fname, &fs);
52            if (!S_ISREG(fs.st_mode)) {
53                    error("file %s not a regular file\n", fname);
54                    return ERROR_FILEOPEN;
55            }
56            return 1;
57    }
58    
59    
60  /*  /*
61   * Find the path to configuration file, open it and call parse_config().   * Check if a directory exists.
62   */   */
63  int read_config(char *cfg)  int
64  {  exists_dir(char *dname)
65      int r;  {
66      FILE *fp;          struct stat ds;
67      char *home = NULL;  
68      char *c = NULL;          if (access(dname, F_OK))
69                    return 0;
70      if (!cfg) {  
71          cfg = c = (char *) xmalloc(PATH_MAX * sizeof(char));          stat(dname, &ds);
72            if (!S_ISDIR(ds.st_mode)) {
73          home = getenv("HOME");                  error("file %s not a directory\n", dname);
74                    return ERROR_FILEOPEN;
75          snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");          }
76      }          return 1;
77  #ifdef DEBUG  }
78      printf("debug: configuration file: '%s'\n", cfg);  
79  #endif  
80  #ifdef CHECK_PERMISSIONS  /*
81      check_permissions(cfg);   * Create a file with the specified permissions.
82  #endif   */
83      fp = fopen(cfg, "r");  int
84    create_file(char *fname, mode_t mode)
85      if (!fp)  {
86          fatal(ERROR_FILE_OPEN, "imapfilter: opening config file %s; %s\n",          int fd;
87                cfg, strerror(errno));  
88            fd = 0;
89      if (c)  
90          free(c);          if (!exists_file(fname)) {
91                    fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, mode);
92      if ((r = parse_config(fp)))                  if (fd == -1) {
93          fatal(ERROR_CONFIG_PARSE,                          error("could not create file %s; %s\n", fname,
94                "imapfilter: parse error in config file at row %d\n", r);                              strerror(errno));
95                            return ERROR_FILEOPEN;
96      fclose(fp);                  }
97                    close(fd);
98  #ifdef DEBUG          }
99      printf("debug: options: %0#10x\n", options);          return 0;
100  #endif  }
101    
102      return 0;  
103  }  /*
104     * Check the permissions of a file.
105     */
106  #ifdef CHECK_PERMISSIONS  int
107  /*  check_file_perms(char *fname, mode_t mode)
108   * Check the permissions of the configuration file.  {
109   */          struct stat fs;
110  int check_permissions(char *cfg)  
111  {          if (opts.verbosity <= -1)
112      struct stat fs;                  return 0;
113    
114      if (stat(cfg, &fs)) {          if (stat(fname, &fs)) {
115          error("imapfilter: getting file %s status; %s\n", cfg,                  error("getting file %s status; %s\n", fname,
116                strerror(errno));                      strerror(errno));
117          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
118      }          }
119      if (!S_ISREG(fs.st_mode)) {          if (!S_ISREG(fs.st_mode)) {
120          error("imapfilter: file %s not a regular file\n", cfg);                  error("file %s not a regular file\n", fname);
121          return ERROR_TRIVIAL;                  return ERROR_TRIVIAL;
122      }          }
123      if ((fs.st_mode & 00777) != (S_IRUSR | S_IWUSR)) {          if ((fs.st_mode & 00777) != mode) {
124          error("imapfilter: warning: improper config file %s permissions\n"                  error("warning: file's %s mode should be %o not %o\n", fname,
125                "imapfilter: warning: file's mode should be 600 not %o\n",                      mode, fs.st_mode & 00777);
126                cfg, fs.st_mode & 00777);                  return ERROR_TRIVIAL;
127          return ERROR_TRIVIAL;          }
128      }          return 0;
129      return 0;  }
130  }  
131  #endif  
132    /*
133  /*   * Check the permissions of a directory.
134   * Parse configuration file.   */
135   */  int
136  int parse_config(FILE * fp)  check_dir_perms(char *dname, mode_t mode)
137  {  {
138      int i, r = 0;          struct stat ds;
139      unsigned int row = 0;  
140      char line[LINE_MAX];          if (opts.verbosity <= -1)
141      regex_t creg[13];                  return 0;
142      regmatch_t match[7];  
143      const char *reg[13] = {          if (stat(dname, &ds)) {
144          "^([[:blank:]]*\n|#.*\n)$",                  error("getting file %s status; %s\n", dname,
145  #ifndef SSL_TLS                      strerror(errno));
146          "^[[:blank:]]*ACCOUNT[[:blank:]]+([[:graph:]]*):([[:graph:]]*)@([[:alnum:].-]+)(:[[:digit:]]+)?[[:blank:]]*\n$",                  return ERROR_TRIVIAL;
147  #else          }
148          "^[[:blank:]]*ACCOUNT[[:blank:]]+([[:graph:]]*):([[:graph:]]*)@([[:alnum:].-]+)(:[[:digit:]]+)?[[:blank:]]*([[:blank:]]SSL|[[:blank:]]SSL2|[[:blank:]]SSL3|[[:blank:]]TLS1)?[[:blank:]]*\n$",          if (!S_ISDIR(ds.st_mode)) {
149  #endif                  error("file %s not a directory\n", dname);
150          "^[[:blank:]]*FOLDER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+([[:print:]]+)[[:blank:]]*\n$",                  return ERROR_TRIVIAL;
151          "^[[:blank:]]*FILTER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]*([[:blank:]]OR|[[:blank:]]AND)?[[:blank:]]*\n$",          }
152          "^[[:blank:]]*ACTION[[:blank:]]+(DELETE|COPY[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|MOVE[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|LIST)[[:blank:]]*([[:graph:]]*)[[:blank:]]*\n$",          if ((ds.st_mode & 00777) != mode) {
153          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(ANSWERED|DELETED|DRAFT|FLAGGED|NEW|OLD|RECENT|SEEN|UNANSWERED|UNDELETED|UNDRAFT|UNFLAGGED|UNSEEN)[[:blank:]]*\n$",                  error("warning: dir's %s mode should be %o not %o\n", dname,
154          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(BCC|BODY|CC|FROM|SUBJECT|TEXT|TO)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",                      mode, ds.st_mode & 00777);
155          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(HEADER)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",                  return ERROR_TRIVIAL;
156          "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*(LARGER|SMALLER|OLDER|NEWER)[[:blank:]]+([[:digit:]]+)[[:blank:]]*\n$",          }
157          "^[[:blank:]]*JOB[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]*\n$",          return 0;
         "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(LOGFILE)[[:blank:]]*=[[:blank:]]*([[:print:]]+)\n$",  
         "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(HEADERS|NAMESPACE)[[:blank:]]*=[[:blank:]]*(YES|NO)[[:blank:]]*\n$",  
         "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(TIMEOUT)[[:blank:]]*=[[:blank:]]*(-?[[:digit:]]+)\n$"  
     };  
   
     for (i = 0; i < 13; i++)  
         regcomp(&creg[i], reg[i], REG_EXTENDED | REG_ICASE);  
   
     while (fgets(line, LINE_MAX - 1, fp)) {  
         row++;  
         if (!regexec(&creg[0], line, 0, match, 0))  
             continue;  
 #ifndef SSL_TLS  
         else if (!regexec(&creg[1], line, 5, match, 0))  
 #else  
         else if (!regexec(&creg[1], line, 6, match, 0))  
 #endif  
             set_account(line, match);  
         else if (!regexec(&creg[2], line, 3, match, 0))  
             r = set_mboxgrp(line, match);  
         else if (!regexec(&creg[3], line, 3, match, 0))  
             r = set_filter(line, match);  
         else if (!regexec(&creg[4], line, 5, match, 0))  
             r = set_action(line, match);  
         else if (!regexec(&creg[5], line, 7, match, 0) ||  
                  !regexec(&creg[6], line, 7, match, 0) ||  
                  !regexec(&creg[7], line, 7, match, 0) ||  
                  !regexec(&creg[8], line, 7, match, 0))  
             r = set_mask(line, match);  
         else if (!regexec(&creg[9], line, 3, match, 0))  
             r = set_job(line, match);  
         else if (!regexec(&creg[10], line, 4, match, 0) ||  
                  !regexec(&creg[11], line, 4, match, 0) ||  
                  !regexec(&creg[12], line, 4, match, 0))  
             set_options(line, match);  
         else  
             return row;  
   
         if (r == ERROR_CONFIG_PARSE)  
             return row;  
     }  
   
     for (i = 0; i < 13; i++)  
         regfree(&creg[i]);  
   
     destroy_data();  
   
     return 0;  
 }  
   
   
 /*  
  * Set other options found in config file.  
  */  
 void set_options(char *line, regmatch_t * match)  
 {  
     if (!strncasecmp(line + match[2].rm_so, "logfile", 7)) {  
         if (!*logfile)  
             strncat(logfile, line + match[3].rm_so,  
                     min((match[3].rm_eo - match[3].rm_so), PATH_MAX - 1));  
     } else if (!strncasecmp(line + match[2].rm_so, "header", 6)) {  
         if (!strncasecmp(line + match[3].rm_so, "yes", 3))  
             options |= OPTION_HEADERS;  
         else  
             options &= ~(OPTION_HEADERS);  
     } else if (!strncasecmp(line + match[2].rm_so, "namespace", 9)) {  
         if (!strncasecmp(line + match[3].rm_so, "yes", 3))  
             options |= OPTION_NAMESPACE;  
         else  
             options &= ~(OPTION_NAMESPACE);  
     } else if (!strncasecmp(line + match[2].rm_so, "timeout", 7)) {  
         errno = 0;  
         timeout = strtol(line + match[3].rm_so, NULL, 10);  
         if (errno)  
             timeout = 0;  
     }  
158  }  }

Legend:
Removed from v.1.26.2.2  
changed lines
  Added in v.1.63

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26