home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / elm23-2.zip / filter / rules.c < prev    next >
C/C++ Source or Header  |  1992-10-04  |  9KB  |  350 lines

  1.  
  2. static char rcsid[] ="@(#)$Id: rules.c,v 4.1 90/04/28 22:42:00 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein - elm@DSI.COM
  13.  *            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    rules.c,v $
  17.  * Revision 4.1  90/04/28  22:42:00  syd
  18.  * checkin of Elm 2.3 as of Release PL0
  19.  *
  20.  *
  21.  ******************************************************************************/
  22.  
  23. /** This file contains all the rule routines, including those that apply the
  24.     specified rules and the routine to print the rules out.
  25.  
  26. **/
  27.  
  28. #include <stdio.h>
  29. #include <pwd.h>
  30. #include <ctype.h>
  31. #include "defs.h"
  32. #ifdef I_TIME
  33. #  include <time.h>
  34. #endif
  35. #ifdef I_SYSTIME
  36. #  include <sys/time.h>
  37. #endif
  38. #include <fcntl.h>
  39.  
  40. #include "filter.h"
  41.  
  42. char *listrule();
  43.  
  44. int
  45. action_from_ruleset()
  46. {
  47.     /** Given the set of rules we've read in and the current to, from,
  48.         and subject, try to match one.  Return the ACTION of the match
  49.             or LEAVE if none found that apply.
  50.     **/
  51.  
  52.     register int iindex = 0, not, relation, try_next_rule, x;
  53.     struct condition_rec *cond;
  54.  
  55.     while (iindex < total_rules) {
  56.       cond = rules[iindex].condition;
  57.       try_next_rule = 0;
  58.  
  59.       while (cond != NULL && ! try_next_rule) {
  60.  
  61.         not = (cond->relation < 0);
  62.         relation = abs(cond->relation);
  63.  
  64.         switch (cond->matchwhat) {
  65.  
  66.           case TO     : x = contains(to, cond->argument1);         break;
  67.           case FROM   : x = contains(from, cond->argument1);     break;
  68.           case SUBJECT: x = contains(subject, cond->argument1);    break;
  69.           case LINES  : x = compare(lines, relation, cond->argument1);break;
  70.  
  71.           case CONTAINS: if (outfd != NULL) fprintf(outfd,
  72.        "filter (%s): Error: rules based on 'contains' are not implemented!\n",
  73.                 username);
  74.                 if (outfd != NULL) fclose(outfd);
  75.                 exit(0);
  76.  
  77.           case ALWAYS: not = FALSE; x = TRUE;            break;
  78.         }
  79.  
  80.         if ((not && x) || ((! not) && (! x))) /* this test failed (LISP?) */
  81.           try_next_rule++;
  82.         else
  83.           cond = cond->next;          /* next condition, if any?  */
  84.       }
  85.  
  86.       if (! try_next_rule) {
  87.         rule_choosen = iindex;
  88.          return(rules[rule_choosen].action);
  89.       }
  90.       iindex++;
  91.     }
  92.  
  93.     rule_choosen = -1;
  94.     return(LEAVE);
  95. }
  96.  
  97. #define get_the_time()    if (!gotten_time) {           \
  98.                thetime = time( (long *) 0);   \
  99.                timerec = localtime(&thetime); \
  100.                gotten_time++;           \
  101.             }
  102.  
  103. expand_macros(word, buffer, line, display)
  104. char *word, *buffer;
  105. int  line, display;
  106. {
  107.     /** expand the allowable macros in the word;
  108.         %d    = day of the month
  109.         %D    = day of the week
  110.             %h    = hour (0-23)
  111.         %m    = month of the year
  112.         %r    = return address of sender
  113.            %s    = subject of message
  114.            %S    = "Re: subject of message"  (only add Re: if not there)
  115.         %t    = hour:minute
  116.         %y    = year
  117.         or simply copies word into buffer. If "display" is set then
  118.         instead it puts "<day-of-month>" etc. etc. in the output.
  119.     **/
  120.  
  121. #ifndef    _POSIX_SOURCE
  122.     struct tm *localtime();
  123.     time_t time();
  124. #endif
  125.     struct tm *timerec;
  126.     long    thetime;
  127.     register int i, j=0, gotten_time = 0, reading_a_percent_sign = 0, len;
  128.  
  129.     for (i = 0, len = strlen(word); i < len; i++) {
  130.       if (reading_a_percent_sign) {
  131.         reading_a_percent_sign = 0;
  132.         switch (word[i]) {
  133.  
  134.           case 'r' : buffer[j] = '\0';
  135.              if (display)
  136.                 strcat(buffer, "<return-address>");
  137.              else
  138.                strcat(buffer, from);
  139.                      j = strlen(buffer);
  140.              break;
  141.  
  142.           case 's' : buffer[j] = '\0';
  143.              if (display)
  144.                 strcat(buffer, "<subject>");
  145.              else {
  146.                strcat(buffer, "\"");
  147.                strcat(buffer, subject);
  148.                strcat(buffer, "\"");
  149.              }
  150.                      j = strlen(buffer);
  151.              break;
  152.  
  153.           case 'S' : buffer[j] = '\0';
  154.              if (display)
  155.                 strcat(buffer, "<Re: subject>");
  156.              else {
  157.                if (! the_same(subject, "Re:"))
  158.                  strcat(buffer, "\"Re: ");
  159.                strcat(buffer, subject);
  160.                strcat(buffer, "\"");
  161.              }
  162.                      j = strlen(buffer);
  163.              break;
  164.  
  165.           case 'd' : get_the_time(); buffer[j] = '\0';
  166.              if (display)
  167.                strcat(buffer, "<day-of-month>");
  168.              else
  169.                strcat(buffer, itoa(timerec->tm_mday,FALSE));
  170.                      j = strlen(buffer);
  171.              break;
  172.  
  173.           case 'D' : get_the_time(); buffer[j] = '\0';
  174.              if (display)
  175.                strcat(buffer, "<day-of-week>");
  176.              else
  177.                strcat(buffer, itoa(timerec->tm_wday,FALSE));
  178.                      j = strlen(buffer);
  179.              break;
  180.  
  181.           case 'm' : get_the_time(); buffer[j] = '\0';
  182.              if (display)
  183.                strcat(buffer, "<month>");
  184.              else
  185.                strcat(buffer, itoa(timerec->tm_mon+1,FALSE));
  186.                      j = strlen(buffer);
  187.              break;
  188.  
  189.           case 'y' : get_the_time(); buffer[j] = '\0';
  190.              if (display)
  191.                strcat(buffer, "<year>");
  192.              else
  193.                strcat(buffer, itoa(timerec->tm_year,FALSE));
  194.                      j = strlen(buffer);
  195.              break;
  196.  
  197.           case 'h' : get_the_time(); buffer[j] = '\0';
  198.              if (display)
  199.                strcat(buffer, "<hour>");
  200.              else
  201.                strcat(buffer, itoa(timerec->tm_hour,FALSE));
  202.                      j = strlen(buffer);
  203.              break;
  204.  
  205.           case 't' : get_the_time(); buffer[j] = '\0';
  206.              if (display)
  207.                strcat(buffer, "<time>");
  208.                  else {
  209.                strcat(buffer, itoa(timerec->tm_hour,FALSE));
  210.                strcat(buffer, ":");
  211.                strcat(buffer, itoa(timerec->tm_min,TRUE));
  212.              }
  213.                      j = strlen(buffer);
  214.              break;
  215.  
  216.           default  : if (outfd != NULL) fprintf(outfd,
  217.    "filter (%s): Error on line %d translating %%%c macro in word \"%s\"!\n",
  218.                      username, line, word[i], word);
  219.              if (outfd != NULL) fclose(outfd);
  220.              exit(1);
  221.         }
  222.       }
  223.       else if (word[i] == '%')
  224.         reading_a_percent_sign++;
  225.       else
  226.         buffer[j++] = (word[i] == '_' ? ' ' : word[i]);
  227.     }
  228.     buffer[j] = '\0';
  229. }
  230.  
  231. print_rules()
  232. {
  233.     /** print the rules out.  A double check, of course! **/
  234.  
  235.     register int i = -1;
  236.     char     *whatname(), *actionname();
  237.     struct   condition_rec *cond;
  238.  
  239.     if (outfd == NULL) return;    /* why are we here, then? */
  240.  
  241.     while (++i < total_rules) {
  242.       if (rules[i].condition->matchwhat == ALWAYS) {
  243.         fprintf(outfd, "\nRule %d:  ** always ** \n\t%s %s\n", i+1,
  244.          actionname(rules[i].action), listrule(rules[i].argument2));
  245.         continue;
  246.       }
  247.  
  248.       fprintf(outfd, "\nRule %d:  if (", i+1);
  249.  
  250.       cond = rules[i].condition;
  251.  
  252.       while (cond != NULL) {
  253.         if (cond->relation < 0)
  254.           fprintf(outfd, "not %s %s %s%s%s",
  255.               whatname(cond->matchwhat),
  256.               relationname(- (cond->relation)),
  257.               quoteit(cond->matchwhat),
  258.               cond->argument1,
  259.               quoteit(cond->matchwhat));
  260.         else
  261.           fprintf(outfd, "%s %s %s%s%s",
  262.               whatname(cond->matchwhat),
  263.               relationname(cond->relation),
  264.               quoteit(cond->matchwhat),
  265.               cond->argument1,
  266.               quoteit(cond->matchwhat));
  267.  
  268.         cond = cond->next;
  269.  
  270.         if (cond != NULL) fprintf(outfd, " and ");
  271.       }
  272.  
  273.       fprintf(outfd, ") then\n\t  %s %s\n",
  274.          actionname(rules[i].action),
  275.          listrule(rules[i].argument2));
  276.     }
  277.     fprintf(outfd, "\n");
  278. }
  279.  
  280. char *whatname(n)
  281. int n;
  282. {
  283.     static char buffer[10];
  284.  
  285.     switch(n) {
  286.       case FROM   : return("from");
  287.       case TO     : return("to");
  288.       case SUBJECT: return("subject");
  289.       case LINES  : return ("lines");
  290.       case CONTAINS: return("contains");
  291.       default     : sprintf(buffer, "?%d?", n); return((char *)buffer);
  292.     }
  293. }
  294.  
  295. char *actionname(n)
  296. int n;
  297. {
  298.     switch(n) {
  299.       case DELETE_MSG : return("Delete");
  300.       case SAVE       : return("Save");
  301.       case SAVECC     : return("Copy and Save");
  302.       case FORWARD    : return("Forward");
  303.       case LEAVE      : return("Leave");
  304.       case EXEC       : return("Execute");
  305.       default         : return("?action?");
  306.     }
  307. }
  308.  
  309. int
  310. compare(line, relop, arg)
  311. int line, relop;
  312. char *arg;
  313. {
  314.     /** Given the actual number of lines in the message, the relop
  315.         relation, and the number of lines in the rule, as a string (!),
  316.            return TRUE or FALSE according to which is correct.
  317.     **/
  318.  
  319.     int rule_lines;
  320.  
  321.     rule_lines = atoi(arg);
  322.  
  323.     switch (relop) {
  324.       case LE: return(line <= rule_lines);
  325.       case LT: return(line <  rule_lines);
  326.       case GE: return(line >= rule_lines);
  327.       case GT: return(line >  rule_lines);
  328.       case NE: return(line != rule_lines);
  329.       case EQ: return(line == rule_lines);
  330.     }
  331.     return(-1);
  332. }
  333.  
  334. char *listrule(rule)
  335. char *rule;
  336. {
  337.     /** simply translates all underscores into spaces again on the
  338.         way past... **/
  339.  
  340.     static char buffer[SLEN];
  341.     register int i;
  342.  
  343.     i = strlen(rule);
  344.     buffer[i] = '\0';
  345.     while (--i >= 0)
  346.       buffer[i] = (rule[i] == '_' ? ' ' : rule[i]);
  347.  
  348.     return( (char *) buffer);
  349. }
  350.