procmail
[Top] [All Lists]

Re: maintaining a list that procmail can check

2001-07-06 09:49:46
On  5 Jul, David W. Tamkin wrote:
| OK, folks, please bear with me.  I'm trying to figure something out, so this
| is a bit on the stream-of-consciousness side.
| 
| I'm thinking of a setup where procmail could check a list of filenames [...]
| 
| So I'm looking for the setup with the most net efficiency for procmail to
| 
| (1) check whether a name is listed
| (2) add a name to the list
| and
| (3) remove a name from the list
| 
| I figure that a flat file with one name per line is not so good; [...]
| 
| A flat file with a regexp makes checking easier, just calling it as an
| INCLUDERC:
| 
| files="(\
| name1|\
| name2|\
| name3|\
| name4\
| )"
| 
| but adding would require calling an editor, and removing would require not
| only calling an editor but giving special handling to the bottommost entry
| because removing it would mean taking the pipe symbol off the entry above it.
| 
| I was considering keeping the filenames as hard links in a special directory
| to a zero-size file.  Adding or removing would involve calling ln or rm with
| no shells nor editing instructions.  Checking, though, would mean running
| test for every incoming message, which may mean calling a shell [sometimes,
| even when there is a /bin/test, it's a shell script that calls the shell's
| `test' built-in].
| 
| All right: suppose I make the valid names hard links in a given directory to
| a file containing one variable assignment.  Then instead of checking with
| test, I check by trying to assign the name to INCLUDERC.  If the file exists,
| the variable gets the value.  If the file does not exist, procmail reports an
| error for inability to open the INCLUDERC and the variable does not get the
| value.  Either way, there's no fork for checking.  A control message to add
| or delete a name can simply call ln or rm, two relatively slight programs,
| with no need for a shell.  (Ln will always work, because I'll keep one link
| under a name that procmail will never look for; the file will never disappear
| completely.)
| 
| Any improvements?
| Any better approaches?
| 

This isn't offered as necessarily better... just different. It's
something I played around with this morning that seems to get around the
need for an editor to to maintain a separate file.  It would surely
break miserably if the list of files is large, but if the list of files
is small enough to be contained comfortably in a variable, something
like this may be an alternative.

I used a test message like:

To: deh+file(_at_)tradersdata(_dot_)com
Subject: filetest

add     ghi789

where add could be (test|add|rm).

The data file ("filelist") looks like:

files=^A@@@@@^Aabc123^Adef456^Aghi789^A

where those are actual ^A (\001) chars delimiting the filenames, there
is no newline, and the first file "@@@@@" is guaranteed to never be in
the rm list (Note 1).  ^A is chosen because it's not likely to be in a
filename, but is obviously configurable. The lack of a newline takes
advantage of the fact that procmail does not append a newline (unless
specifically told to). There is no doubt that, even if some value is
found, this can be improved. It's offered as a possible starting point
because it only requires one external program (cat, and only on rm), and
doesn't use perl which David has at least some proclivity to avoid. ;-)

# .testrc
TESTDIR=$HOME/.procmail/test
LOGABSTRACT=no
LOGFILERC=$TESTDIR/testlog.dattier
LOGFILE=$LOGFILERC
VERBOSE=no
NL="
"

:0
* ^To: deh\+file(_at_)tradersdata(_dot_)com
* ^Subject: filetest
* B ?? ()\/(test|add|rm)[       ]+.*
{
  DOTHIS="$MATCH"
  :0
  * DOTHIS ?? ^^\/(test|add|rm)
  { WHATTODO=$MATCH }
  :0
  * $ DOTHIS ?? ^^$WHATTODO[    ]+\/[^  ].*
  { FILE="$MATCH" }
  :0
  * -2^0 WHATTODO ?? ^^(test|add|rm)^^
  * -2^0 FILE ?? [a-z0-9]+     # Note 2
  *  3^0
  {
     # probably want something more elaborate here
     LOG="BAILED$NL"
  }
  :0 E
  {
    INCLUDERC=$TESTDIR/filelist
    LOG="do *$WHATTODO* to *$FILE* from *$files*$NL"   # Note 3
    :0
    * WHATTODO ?? ^^test^^
    {
      :0
      * $ files ?? ^A$FILE^A
      { RESULT=ok }
      :0 E
      { RESULT="no such file" }
    }
    :0 E
    * WHATTODO ?? ^^add^^
    {
      :0
      * $ ! files ?? ^A${FILE}^A
      {
        LOGFILE=$TESTDIR/filelist
        LOG="$FILE^A"
        LOGFILE=$LOGFILERC
        RESULT=ok
      }
      :0 E
      { RESULT="already listed" }
    }
    :0 E
    * WHATTODO ?? ^^rm^^
    {
      :0
      * $ files ?? ^A${FILE}\/^A.*
      {
        aftFILE="$MATCH"
        :0 c:$TESTDIR/filelist.LCK
        | cat /dev/null >$TESTDIR/filelist
        :0 a
        * $ files ?? ^^\/.*^A${FILE}^A
        * MATCH ?? ^^\/.*[^^A]
        * MATCH ?? ^^\/.*[^A]
        * MATCH ?? ^^\/.*[^^A]
        {
          LOGFILE=$TESTDIR/filelist
          LOG="files=${MATCH:-''}$aftFILE"
          LOGFILE=$LOGFILERC
          RESULT=ok
      }
    }
    :0 E
    { RESULT="not listed" }
  }
  LOG="$WHATTODO $FILE: ${RESULT:-who knows?}$NL"   # Note 3
}

:0
/dev/null

Notes:

1. The purpose of "@@@@@" in the data file is to preclude the need
for special handling of "rm filename" when "filename" is the first
in the list. This kind of borrows from part of Sean's suggestion.

2. Any character except ^A in the filename should be ok (maybe even
newline?), but this assumes that at least one "sane" character is used
in each filename.

3. These are superfluous and were used simply for hand-holding during
my play time.

4. Each place where ^A appears in the rcfile is actually \001 not the
two chars "^" and "A" as above.  And each [     ] character class
includes the usual space and tab chars.

5. In most of the places where there are RESULT= assignments, something
more informative/functional would be inserted.

6. It's been lightly tested only.

-- 
                         /"\
Don Hammond              \ /     ASCII Ribbon Campaign
Raleigh, NC US            X        Against HTML Mail,
                         / \      and News Too

_______________________________________________
procmail mailing list
procmail(_at_)lists(_dot_)RWTH-Aachen(_dot_)DE
http://MailMan.RWTH-Aachen.DE/mailman/listinfo/procmail