Cosmetics + now alias replaces the full search request, not just the key.
[mymail.git] / mymail.c
index e6a2687..80864d2 100644 (file)
--- a/mymail.c
+++ b/mymail.c
@@ -46,7 +46,9 @@
 #include <time.h>
 
 #define MYMAIL_DB_MAGIC_TOKEN "mymail_index_file"
-#define VERSION "0.9.6"
+#define MYMAIL_VERSION "0.9.8"
+
+#define MYMAIL_DB_FORMAT_VERSION 1
 
 #define MAX_NB_SEARCH_CONDITIONS 32
 
 
 #define LEADING_FROM_LINE_REGEXP_STRING "^From .*\\(Mon\\|Tue\\|Wed\\|Thu\\|Fri\\|Sat\\|Sun\\) \\(Jan\\|Feb\\|Mar\\|Apr\\|May\\|Jun\\|Jul\\|Aug\\|Sep\\|Oct\\|Nov\\|Dec\\) [ 0123][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]\n$"
 
+/********************************************************************/
+
+struct alias_node {
+  char *alias, *value;
+  struct alias_node *next;
+};
+
 /* Global variables! */
 
 int global_quiet;
 int global_use_leading_time;
-
 regex_t global_leading_from_line_regexp;
+struct alias_node *global_alias_list;
 
 /********************************************************************/
 
@@ -184,6 +193,18 @@ char *default_value(char *current_value,
   }
 }
 
+/********************************************************************/
+
+void *safe_malloc(size_t n) {
+  void *p = malloc(n);
+  if(!p && n != 0) {
+    fprintf(stderr,
+            "selector: cannot allocate memory: %s\n", strerror(errno));
+    exit(EXIT_FAILURE);
+  }
+  return p;
+}
+
 FILE *safe_fopen(const char *path, const char *mode, const char *comment) {
   FILE *result = fopen(path, mode);
   if(result) {
@@ -199,7 +220,7 @@ FILE *safe_fopen(const char *path, const char *mode, const char *comment) {
 /*********************************************************************/
 
 void print_version(FILE *out) {
-  fprintf(out, "mymail version %s (%s)\n", VERSION, UNAME);
+  fprintf(out, "mymail version %s (%s)\n", MYMAIL_VERSION, UNAME);
 }
 
 void print_usage(FILE *out) {
@@ -227,7 +248,7 @@ void print_usage(FILE *out) {
   fprintf(out, "         set the mbox filename pattern for recursive search\n");
   fprintf(out, " -s <search pattern>, --search <search pattern>\n");
   fprintf(out, "         search for matching mails in the db file\n");
-  fprintf(out, " -d <db filename>, --db-file-generate <db filename>\n");
+  fprintf(out, " -d <db filename>, --db-file-output <db filename>\n");
   fprintf(out, "         set the db filename for indexing\n");
   fprintf(out, " -i, --index\n");
   fprintf(out, "         index mails\n");
@@ -321,6 +342,8 @@ void extract_mail(const char *mail_filename, unsigned long int position_in_mail,
   char raw_mbox_line[BUFFER_SIZE];
   FILE *mail_file;
 
+  /* printf("Extract\n"); */
+
   mail_file = safe_fopen(mail_filename, "r", "mbox for mail extraction");
   fseek(mail_file, position_in_mail, SEEK_SET);
 
@@ -392,9 +415,12 @@ void update_time(int db_key, const char *db_value, time_t *t) {
   const char *c;
   struct tm tm;
 
+  memset(&tm, 0, sizeof(struct tm));
+
   if(db_key == ID_LEADING_LINE) {
     c = db_value;
     while(*c && *c != ' ') c++; while(*c && *c == ' ') c++;
+    /* printf("From %s", db_value); */
     strptime(c, "%a %b %e %k:%M:%S %Y", &tm);
     *t = mktime(&tm);
   } else {
@@ -402,6 +428,7 @@ void update_time(int db_key, const char *db_value, time_t *t) {
       if(db_key == ID_DATE) {
         if(strptime(db_value, "%a, %d %b %Y %k:%M:%S", &tm) ||
            strptime(db_value, "%d %b %Y %k:%M:%S", &tm)) {
+          /* printf("Date: %s", db_value); */
           *t = mktime(&tm);
         }
       }
@@ -733,7 +760,7 @@ static struct option long_options[] = {
   { "version", no_argument, 0, 'v' },
   { "quiet", no_argument, 0, 'q' },
   { "use-leading-time", no_argument, 0, 't' },
-  { "db-file-generate", 1, 0, 'd' },
+  { "db-file-output", 1, 0, 'd' },
   { "db-pattern", 1, 0, 'p' },
   { "db-root", 1, 0, 'r' },
   { "db-list", 1, 0, 'l' },
@@ -761,6 +788,7 @@ static struct time_criterion time_criteria[] = {
   { "48h",       0, 48,       -1, -1 },
   { "week",      0, 24 *   7, -1, -1 },
   { "month",     0, 24 *  31, -1, -1 },
+  { "trimester", 0, 24 *  92, -1, -1 },
   { "year",      0, 24 * 365, -1, -1 },
 
   { "yesterday", 1, -1,       -1, -1 },
@@ -797,6 +825,14 @@ void init_condition(struct search_condition *condition, const char *full_string,
   char full_search_field[TOKEN_BUFFER_SIZE], *search_field;
   unsigned int k, m;
   const char *string;
+  struct alias_node *a;
+
+  for(a = global_alias_list; a; a = a->next) {
+    if(strcmp(full_string, a->alias) == 0) {
+      full_string = a->value;
+      break;
+    }
+  }
 
   string = parse_token(full_search_field, TOKEN_BUFFER_SIZE, ' ', full_string);
   search_field = full_search_field;
@@ -826,6 +862,7 @@ void init_condition(struct search_condition *condition, const char *full_string,
           condition->time_stop = 0;
         }
       }
+
       break;
     }
   }
@@ -880,6 +917,72 @@ void free_condition(struct search_condition *condition) {
   }
 }
 
+const char *eat_space(const char *s) {
+  while(*s == ' ' || *s == '\t') { s++; }
+  return s;
+}
+
+void read_rc_file(const char *rc_filename) {
+  char raw_line[BUFFER_SIZE];
+  char command[TOKEN_BUFFER_SIZE], tmp_token[TOKEN_BUFFER_SIZE];
+
+  FILE *rc_file;
+  int line_number;
+  const char *s;
+  char *t;
+
+  rc_file = fopen(rc_filename, "r");
+
+  if(rc_file) {
+    line_number = 1;
+    while(fgets(raw_line, BUFFER_SIZE, rc_file)) {
+      t = raw_line;
+      while(*t) { if(*t == '\n') { *t = '\0'; }; t++; }
+
+      s = raw_line;
+      s = eat_space(s);
+
+      if(*s && *s != '#') {
+        s = parse_token(command, TOKEN_BUFFER_SIZE, ' ', s);
+
+        if(strcmp(command, "alias") == 0) {
+          struct alias_node *a = safe_malloc(sizeof(struct alias_node));
+          a->next = global_alias_list;
+          global_alias_list = a;
+          if(s) {
+            s = eat_space(s);
+            s = parse_token(tmp_token, TOKEN_BUFFER_SIZE, '=', s);
+            a->alias = strdup(tmp_token);
+            if(s) {
+              s = eat_space(s);
+              a->value = strdup(s);
+            } else {
+              fprintf(stderr, "%s:%d syntax error, missing alias value.\n",
+                      rc_filename,
+                      line_number);
+              exit(EXIT_FAILURE);
+            }
+          } else {
+            fprintf(stderr, "%s:%d syntax error, missing alias key.\n",
+                    rc_filename,
+                    line_number);
+            exit(EXIT_FAILURE);
+          }
+        } else {
+          fprintf(stderr, "%s:%d syntax error, unknown command '%s'.\n",
+                  rc_filename,
+                  line_number,
+                  command);
+          exit(EXIT_FAILURE);
+        }
+      }
+
+      line_number++;
+    }
+    fclose(rc_file);
+  }
+}
+
 /*********************************************************************/
 /*********************************************************************/
 /*********************************************************************/
@@ -892,6 +995,7 @@ int main(int argc, char **argv) {
   char *mbox_filename_regexp_string = 0;
   char *default_search_field;
   char output_filename[PATH_MAX + 1];
+  char rc_filename[PATH_MAX + 1];
   int action_index = 0;
   int error = 0, show_help = 0;
   const unsigned int nb_fields_to_parse =
@@ -900,6 +1004,7 @@ int main(int argc, char **argv) {
   unsigned int f, n;
   unsigned int nb_search_conditions;
   struct search_condition search_conditions[MAX_NB_SEARCH_CONDITIONS];
+  struct alias_node *a, *b;
 
   if(regcomp(&global_leading_from_line_regexp, LEADING_FROM_LINE_REGEXP_STRING, 0)) {
     fprintf(stderr,
@@ -907,11 +1012,34 @@ int main(int argc, char **argv) {
     exit(EXIT_FAILURE);
   }
 
+  if(getenv("MYMAILRC")) {
+    sprintf(rc_filename, "%s", getenv("MYMAILRC"));
+  } else if(getenv("HOME")) {
+    sprintf(rc_filename, "%s/.mymailrc", getenv("HOME"));
+  } else {
+    rc_filename[0] = '\0';
+  }
+
+  global_alias_list = 0;
   global_quiet = 0;
   global_use_leading_time = 0;
   default_search_field = 0;
   strncpy(output_filename, "", PATH_MAX);
 
+  if(rc_filename[0]) {
+    read_rc_file(rc_filename);
+  }
+
+  /*
+  {
+#warning Test code added on 2013 May 02 11:17:01
+    struct alias_node *a;
+    for(a = global_alias_list; a; a = a->next) {
+      printf ("ALIAS [%s] [%s]\n", a->alias, a->value);
+    }
+  }
+  */
+
   setlocale(LC_ALL, "");
 
   nb_search_conditions = 0;
@@ -1074,7 +1202,11 @@ int main(int argc, char **argv) {
       }
     }
 
-    fprintf(db_file, "%s version_%s raw\n", MYMAIL_DB_MAGIC_TOKEN, VERSION);
+    fprintf(db_file,
+            "%s version_%s format_%d raw\n",
+            MYMAIL_DB_MAGIC_TOKEN,
+            MYMAIL_VERSION,
+            MYMAIL_DB_FORMAT_VERSION);
 
     while(optind < argc) {
       recursive_index_mbox(db_file,
@@ -1177,6 +1309,15 @@ int main(int argc, char **argv) {
     free_condition(&search_conditions[n]);
   }
 
+  a = global_alias_list;
+  while(a) {
+    b = a->next;
+    free(a->alias);
+    free(a->value);
+    free(a);
+    a = b;
+  }
+
   free(db_filename);
   free(db_filename_regexp_string);
   free(db_root_path);