+struct time_criterion {
+ char *label;
+ int day_criterion;
+ int start_hour, end_hour;
+ int past_week_day;
+};
+
+/*********************************************************************/
+
+static struct time_criterion time_criteria[] = {
+
+ { "1h", 0, 1, -1, -1 },
+ { "8h", 0, 8, -1, -1 },
+ { "24h", 0, 24, -1, -1 },
+ { "48h", 0, 48, -1, -1 },
+ { "week", 0, 24 * 7, -1, -1 },
+ { "2weeks", 0, 24 * 14, -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 },
+ { "today", 1, -1, -1, 0 },
+
+ { "monday", 1, -1, -1, 1 },
+ { "tuesday", 1, -1, -1, 2 },
+ { "wednesday", 1, -1, -1, 3 },
+ { "thursday", 1, -1, -1, 4 },
+ { "friday", 1, -1, -1, 5 },
+ { "saturday", 1, -1, -1, 6 },
+ { "sunday", 1, -1, -1, 7 },
+
+};
+
+/*********************************************************************/
+
+time_t time_for_past_day(int day) {
+ struct tm *tm;
+ int delta_day;
+ tm = localtime(&global_current_time);
+ if(day > 0) {
+ delta_day = (7 + tm->tm_wday - day) % 7;
+ } else {
+ delta_day = - day;
+ }
+ return global_current_time - (delta_day * 3600 * 24 + tm->tm_sec + 60 * tm->tm_min + 3600 * tm->tm_hour);
+}
+
+void init_condition(struct search_condition *condition, const char *full_string,
+ const char *default_search_field) {
+ 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;
+
+ if(search_field[0] == '!') {
+ search_field++;
+ condition->negation = 1;
+ } else {
+ condition->negation = 0;
+ }
+
+ condition->db_key = -1;
+
+ /* Time condition */
+
+ for(k = 0; k < sizeof(time_criteria) / sizeof(struct time_criterion); k++) {
+ if(strcmp(time_criteria[k].label, search_field) == 0) {
+ condition->db_key = ID_TIME_INTERVAL;
+ if(time_criteria[k].day_criterion) {
+ condition->time_start = time_for_past_day(time_criteria[k].past_week_day);
+ condition->time_stop = condition->time_start + 3600 * 24;
+ } else {
+ condition->time_start = global_current_time - 3600 * time_criteria[k].start_hour;
+ if(time_criteria[k].end_hour >= 0) {
+ condition->time_stop = global_current_time - 3600 * time_criteria[k].end_hour;
+ } else {
+ condition->time_stop = 0;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if(condition->db_key == -1) {
+
+ /* No time condition matched, look for the search fields */
+
+ for(m = 0; (m < MAX_ID) && condition->db_key == -1; m++) {
+ if(strncmp(field_keys[m], search_field, strlen(search_field)) == 0) {
+ condition->db_key = m;
+ }
+ }
+
+ /* None match, if there is a default search field, re-run the search with it */
+
+ if(condition->db_key == -1) {
+ if(default_search_field) {
+ for(m = 0; (m < MAX_ID) && condition->db_key == -1; m++) {
+ if(strncmp(field_keys[m],
+ default_search_field, strlen(default_search_field)) == 0) {
+ condition->db_key = m;
+ }
+ }
+ string = full_string;
+ if(string[0] == '!') { string++; }
+ }
+ }
+
+ if(condition->db_key == -1) {
+ fprintf(stderr,
+ "mymail: Syntax error in field key \"%s\".\n",
+ search_field);
+ exit(EXIT_FAILURE);
+ }
+
+ if(regcomp(&condition->db_value_regexp,
+ string,
+ REG_ICASE)) {
+ fprintf(stderr,
+ "mymail: Syntax error in regexp \"%s\" for field \"%s\".\n",
+ string,
+ field_keys[condition->db_key]);
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+void free_condition(struct search_condition *condition) {
+ if(condition->db_key != ID_TIME_INTERVAL) {
+ regfree(&condition->db_value_regexp);
+ }
+}
+
+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);
+ }
+}
+
+/*********************************************************************/
+/*********************************************************************/