home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume43 / procmail / part04 < prev    next >
Encoding:
Internet Message Format  |  1994-07-05  |  54.0 KB

  1. From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  2. Newsgroups: comp.sources.misc
  3. Subject: v43i059:  procmail - mail processing package v3.03, Part04/10
  4. Date: 5 Jul 1994 20:49:54 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <2vd2k2$i78@sparky.sterling.com>
  9. X-Md4-Signature: 1b07b57835a8dc4e8fb6b49ec572b5bc
  10.  
  11. Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  12. Posting-number: Volume 43, Issue 59
  13. Archive-name: procmail/part04
  14. Environment: sendmail, ZMailer, smail, MMDF, mailsurr, UNIX, POSIX
  15. Supersedes: procmail: Volume 38, Issue 19-31
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  procmail-3.03/man/procmail.man
  22. #   procmail-3.03/man/procmailex.man procmail-3.03/src/regexp.c
  23. # Wrapped by kent@sparky on Tue Jul  5 20:42:13 1994
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 4 (of 10)."'
  27. if test -f 'procmail-3.03/man/procmail.man' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'procmail-3.03/man/procmail.man'\"
  29. else
  30.   echo shar: Extracting \"'procmail-3.03/man/procmail.man'\" \(20759 characters\)
  31.   sed "s/^X//" >'procmail-3.03/man/procmail.man' <<'END_OF_FILE'
  32. XPlease read the README file in this directory first.
  33. X.ex
  34. X.Id $Id: procmail.man,v 1.51 1994/06/28 14:49:23 berg Exp $
  35. X.TH PROCMAIL 1 \*(Dt BuGless
  36. X.na
  37. X.SH NAME
  38. Xprocmail \- autonomous mail processor
  39. X.SH SYNOPSIS
  40. X.B procmail
  41. X.RB [ \-@PRESERVOPT@@TEMPFAILOPT@@OVERRIDEOPT@ ]
  42. X.RB [ "\-@FROMWHOPT@ \fIfromwhom\fP" ]
  43. X.RI [ "parameter\fB=\fPvalue " | " rcfile" ]
  44. X\&.\|.\|.
  45. X.br
  46. X.B procmail
  47. X.RB [ \-@TEMPFAILOPT@@OVERRIDEOPT@ ]
  48. X.RB [ "\-@FROMWHOPT@ \fIfromwhom\fP" ]
  49. X.RB [ "\-@ARGUMENTOPT@ \fIargument\fP" ]
  50. X.B \-@DELIVEROPT@
  51. X.I recipient
  52. X\&.\|.\|.
  53. X.br
  54. X.B procmail
  55. X.RB [ \-@PRESERVOPT@@TEMPFAILOPT@ ]
  56. X.B \-@MAILFILTOPT@
  57. X.RI [ "parameter\fB=\fPvalue" ]
  58. X\&.\|.\|.
  59. X.I rcfile
  60. X.if n .ti +0.5i
  61. X.RI [ argument ]
  62. X\&.\|.\|.
  63. X.I mail_from rcpt_to
  64. X\&.\|.\|.
  65. X.br
  66. X.B procmail
  67. X.B \-@VERSIONOPT@
  68. X.ad
  69. X.SH DESCRIPTION
  70. XFor a quick start, see
  71. X.B NOTES
  72. Xat the end.
  73. X.PP
  74. X.B Procmail
  75. Xshould be invoked automatically over the
  76. X.B @DOT_FORWARD@
  77. Xfile mechanism as soon as mail arrives.  Alternatively, when installed by
  78. Xa system administrator, it can be invoked from within the mailer immediately.
  79. XWhen invoked, it first sets some environment variables to default values,
  80. Xreads the mail message from stdin until an EOF, separates the body from the
  81. Xheader, and then, if no command line arguments are present, it starts to look
  82. Xfor a file named
  83. X.B @PROCMAILRC@
  84. Xin your home directory.  According to the processing recipes in this file,
  85. Xthe mail message that just arrived gets distributed into the right folder
  86. X(and more).@ETCRC_desc@
  87. X.PP
  88. XIf running suid root or with root privileges, procmail will be able to
  89. Xperform as a functionally enhanced, backwards compatible mail delivery agent.
  90. X.PP
  91. XProcmail can also be used as a general purpose mail filter, i.e. provisions
  92. Xhave been made to enable procmail to be invoked in a special sendmail rule.
  93. X.PP
  94. XThe rcfile format is described in detail in the
  95. X.BR procmailrc (5)
  96. Xman page.
  97. X.PP
  98. XThe weighted scoring technique is described in detail in the
  99. X.BR procmailsc (5)
  100. Xman page.
  101. X.PP
  102. XExamples for rcfile recipes can be looked up in the
  103. X.BR procmailex (5)
  104. Xman page.
  105. X.SS Signals
  106. X.TP 1.2i
  107. X.B TERMINATE
  108. XTerminate prematurely and requeue the mail.
  109. X.TP
  110. X.B HANGUP
  111. XTerminate prematurely and bounce the mail.
  112. X.TP
  113. X.B INTERRUPT
  114. XTerminate prematurely and bounce the mail.
  115. X.TP
  116. X.B QUIT
  117. XTerminate prematurely and silently lose the mail.
  118. X.TP
  119. X.B ALARM
  120. XForce a timeout (see
  121. X.BR TIMEOUT).
  122. X.TP
  123. X.B USR1
  124. XEquivalent to a
  125. X.BR VERBOSE =on.
  126. X.TP
  127. X.B USR2
  128. XEquivalent to a
  129. X.BR VERBOSE =off.
  130. X.SH OPTIONS
  131. X.TP 0.5i
  132. X.B \-@VERSIONOPT@
  133. XProcmail will print its version number and exit.
  134. X.TP
  135. X.B \-@PRESERVOPT@
  136. XPreserve any old environment.  Normally procmail clears the environment
  137. Xupon startup@KEEPENV@.  However, in any case: any default values will override
  138. Xany preexisting environment variables, i.e. procmail will not pay any attention
  139. Xto any predefined environment variables, it will happily overwrite them
  140. Xwith its own defaults.  For the list of environment variables that procmail
  141. Xwill preset see the
  142. X.BR procmailrc (5)
  143. Xman page.  If both \-@PRESERVOPT@ and \-@MAILFILTOPT@ are specified, the
  144. Xlist of preset environment variables shrinks to just: LOGNAME, HOME, SHELL,
  145. XORGMAIL and MAILDIR.
  146. X.TP
  147. X.B \-@TEMPFAILOPT@
  148. XMake procmail fail softly, i.e. if procmail cannot deliver the mail to
  149. Xany of the destinations you gave, the mail will not bounce, but will return
  150. Xto the mailqueue.  Another delivery-attempt will be made at some time in
  151. Xthe future.
  152. X.TP
  153. X.I "\fB\-@FROMWHOPT@\fP fromwhom"
  154. XCauses procmail to regenerate the leading `@FROM@' line with
  155. X.I fromwhom
  156. Xas the sender (instead of \-@FROMWHOPT@ one could use the alternate and
  157. Xobsolete \-@ALTFROMWHOPT@).  If
  158. X.I fromwhom
  159. Xconsists merely of a single `@REFRESH_TIME@', then procmail will only
  160. Xupdate the timestamp on the `@FROM@' line (if present, if not, it will
  161. Xgenerate a new one).
  162. X.TP
  163. X.B \-@OVERRIDEOPT@
  164. XInstead of allowing anyone to generate `@FROM@' lines, simply override
  165. Xthe fakes.
  166. X.TP
  167. X.I "\fB\-@ARGUMENTOPT@\fP argument"
  168. XThis will set $1 to be equal to
  169. X.IR argument .
  170. XIt can be used to pass meta information along to procmail.  This is
  171. Xtypically done by passing along the $@x information from the sendmail
  172. Xmailer rule.
  173. X.TP
  174. X.I "\fB\-@DELIVEROPT@\fP recipient .\|.\|."
  175. XThis turns on explicit delivery mode, delivery will be to the local user
  176. X.IR recipient .
  177. XThis, of course, only is possible if procmail has root
  178. Xprivileges@SETRUID@.
  179. XProcmail will setuid to the intended recipients and shall
  180. X.I only
  181. Xread the recipient's @PROCMAILRC@ file (if present, if not, delivery is like
  182. Xordinary mail).  This option is incompatible with
  183. X.BR \-@PRESERVOPT@ .
  184. X.TP
  185. X.B \-@MAILFILTOPT@
  186. XTurns procmail into a general purpose mail filter.  In this mode one rcfile
  187. Xmust be specified on the command line.  After the rcfile, procmail will
  188. Xaccept an unlimited number of arguments.@ETCRCS_desc@
  189. XFor some typical usage of this option you should look in the
  190. X.B EXAMPLES
  191. Xsection below.
  192. X.SH ARGUMENTS
  193. XAny arguments containing an '=' are considered to be environment variable
  194. Xassignments, they will
  195. X.I all
  196. Xbe evaluated after the default values have been
  197. Xassigned and before the first rcfile is opened.
  198. X.PP
  199. XAny other arguments are presumed to be rcfile paths (either absolute,
  200. Xor if they start with `@chCURDIR@@MCDIRSEP@' relative to the current
  201. Xdirectory;
  202. X.B any other relative
  203. Xpath is relative to $HOME, unless the
  204. X.B \-@MAILFILTOPT@
  205. Xoption has been given, in which case all relative paths are relative to the
  206. Xcurrent directory); procmail will start with the first one it finds on the
  207. Xcommand line.  The following ones will only be parsed if the preceding ones
  208. Xhave a not matching HOST-directive entry, or in case they should not exist.
  209. X.PP
  210. XIf no rcfiles are specified, it looks for
  211. X.BR $HOME/@PROCMAILRC@ .
  212. XIf not even that can be found, processing will continue according to
  213. Xthe default settings of the environment variables and the ones specified
  214. Xon the command line.
  215. X.SH EXAMPLES
  216. XExamples for rcfile recipes can be looked up in the
  217. X.BR procmailex (5)
  218. Xman page.
  219. XA small sample rcfile can be found in the
  220. X.B NOTES
  221. Xsection below.
  222. X.PP
  223. XThe
  224. X.B \-@MAILFILTOPT@
  225. Xoption is typically used when procmail is called from within a rule in the
  226. Xsendmail.cf file.  In order to be able to do this it is convenient to create
  227. Xan extra `procmail' mailer in your sendmail.cf file (in addition to the perhaps
  228. Xalready present `local' mailer that starts up procmail).  To create such a
  229. X`procmail' mailer I'd suggest something like:
  230. X.Sx 2
  231. XMprocmail, P=@BINDIR@/procmail, F=mSDFMhun, S=11, R=21,
  232. X        A=procmail \-@MAILFILTOPT@ $h $f $u
  233. X.Ex
  234. XThis enables you to use rules like the following (most likely in ruleset 0)
  235. Xto filter mail through the procmail mailer (please note the leading tab
  236. Xto continue the rule, and the tab to separate the comments):
  237. X.Sx 4
  238. XR$*<@some.where>$*
  239. X        $#procmail $@/etc/some.rc $:$1@some.where.procmail$2
  240. XR$*<@$*.procmail>$*
  241. X        $1<@$2>$3       Already filtered, map back
  242. X.Ex
  243. XAnd /etc/some.rc could be as simple as:
  244. X.Sx 6
  245. X:0                              # sink all junk mail
  246. X* ^Subject:.*junk
  247. X/dev/null
  248. X
  249. X:0                              # pass along all other mail
  250. X! \-oi \-f "$@"
  251. X.Ex
  252. XDo watch out when sending mail from within the /etc/some.rc file, if
  253. Xyou send mail to addresses which match the first rule again, you could
  254. Xbe creating an endless mail loop.
  255. X.SH FILES
  256. X.TP 2.3i
  257. X.B /etc/passwd
  258. Xto set the recipient's LOGNAME, HOME and SHELL variable defaults
  259. X.TP
  260. X.B @SYSTEM_MBOX@
  261. Xsystem mailbox@ETCRC_files@@ETCRCS_files@
  262. X.TP
  263. X.B $HOME/@PROCMAILRC@
  264. Xdefault rcfile
  265. X.TP
  266. X.B @SYSTEM_MBOX@@DEFlockext@
  267. Xlockfile for the system mailbox (not automatically used by procmail, unless
  268. X$DEFAULT equals @SYSTEM_MBOX@ and procmail is delivering to $DEFAULT)
  269. X.TP
  270. X.B @DEFsendmail@
  271. Xdefault mail forwarder
  272. X.TP
  273. X.B @UNIQ_PREFIX@????`hostname`
  274. Xtemporary `unique' zero-length files created by procmail
  275. X.SH "SEE ALSO"
  276. X.na
  277. X.nh
  278. X.BR procmailrc (5),
  279. X.BR procmailsc (5),
  280. X.BR procmailex (5),
  281. X.BR sh (1),
  282. X.BR csh (1),
  283. X.BR mail (1),
  284. X.BR mailx (1),
  285. X.BR binmail (1),
  286. X.BR uucp (1),
  287. X.BR aliases (5),
  288. X.BR sendmail (8),
  289. X.BR egrep (1),
  290. X.BR grep (1),
  291. X.BR biff (1),
  292. X.BR comsat (8),
  293. X.BR lockfile (1),
  294. X.BR formail (1),
  295. X.BR cron (1)
  296. X.hy
  297. X.ad
  298. X.SH DIAGNOSTICS
  299. X.TP 2.3i
  300. XAutoforwarding mailbox found
  301. XThe system mailbox had its suid or sgid bit set, procmail terminates with
  302. XEX_NOUSER assuming that this mailbox must not be delivered to.
  303. X.TP
  304. XBad substitution of "x"
  305. XNot a valid environment variable name specified.
  306. X.TP
  307. XClosing brace unexpected
  308. XThere was no corresponding opening brace (nesting block).
  309. X.TP
  310. XConflicting options
  311. XNot all option combinations are useful
  312. X.TP
  313. XConflicting x suppressed
  314. XFlag x is not compatible with some other flag on this recipe.
  315. X.TP
  316. XCouldn't create "x"
  317. XThe system mailbox was missing and could not/will not be created.
  318. X.TP
  319. XCouldn't determine implicit lockfile from "x"
  320. XThere were no `>>' redirectors to be found, using simply `$LOCKEXT' as
  321. Xlocallockfile.
  322. X.TP
  323. XCouldn't unlock "x"
  324. XLockfile was already gone, or write permission to the directory were the
  325. Xlockfile is has been denied.
  326. X.TP
  327. XDeadlock attempted on "x"
  328. XThe locallockfile specified on this recipe is equal to a still active
  329. X$LOCKFILE.@ETCRCS_error@
  330. X.TP
  331. XEnforcing stricter permissions on "x"
  332. XThe system mailbox of the recipient was found to be unsecured, procmail
  333. Xsecured it.
  334. X.TP
  335. XError while writing to "x"
  336. XNonexistent subdirectory, no write permission, pipe died or disk full.
  337. X.TP
  338. XExceeded LINEBUF
  339. XBuffer overflow detected, LINEBUF was too small, memory might be corrupted.
  340. X.TP
  341. XExcessive output quenched from "x"
  342. XThe program or filter "x" tried to produce too much output for the current
  343. XLINEBUF, the rest was discarded.
  344. X.TP
  345. XExtraneous x ignored
  346. XThe action line of this recipe makes flag x meaningless.
  347. X.TP
  348. XFailed forking "x"
  349. XProcess table is full (and NORESRETRY has been exhausted).
  350. X.TP
  351. XFailed to execute "x"
  352. XProgram not in path, or not executable.
  353. X.TP
  354. XForced unlock denied on "x"
  355. XNo write permission in the directory where
  356. X.B lockfile
  357. X"x" resides, or more than one procmail trying to force a lock at exactly the
  358. Xsame time.
  359. X.TP
  360. XForcing lock on "x"
  361. X.B Lockfile
  362. X"x" is going to be removed by force because of a timeout (see also:
  363. X.BR LOCKTIMEOUT ).
  364. X.TP
  365. XIncomplete recipe
  366. XThe start of a recipe was found, but it stranded in an EOF.
  367. X.TP
  368. XInsufficient privileges
  369. XProcmail either needs root privileges, or must have the
  370. Xright (e)uid and (e)gid to run in delivery mode.  Delivery will proceed
  371. Xto the invoker.
  372. X.TP
  373. XInvalid regexp "x"
  374. XThe regular expression "x" contains errors (most likely some missing or
  375. Xextraneous parens).
  376. X.TP
  377. XKernel-lock failed
  378. XWhile trying to use the kernel-supported locking calls, one of them failed
  379. X(usually indicates an OS error), procmail ignores this error and proceeds.
  380. X.TP
  381. XKernel-unlock failed
  382. XSee above.
  383. X.TP
  384. XLock failure on "x"
  385. XCan only occur if you specify some real weird (and illegal) lockfilenames
  386. Xor if the
  387. X.B lockfile
  388. Xcould not be created because of insufficient permissions or nonexistent
  389. Xsubdirectories.
  390. X.TP
  391. XLost "x"
  392. XProcmail tried to clone itself but could not find back rcfile "x" (it either
  393. Xgot removed or it was a relative path and you changed directory since
  394. Xprocmail opened it last time).
  395. X.TP
  396. XMissing closing brace
  397. XA nesting block was started, but never finished.
  398. X.TP
  399. XMissing name
  400. XThe \-@FROMWHOPT@ option needs an extra argument.
  401. X.TP
  402. XMissing argument
  403. XYou specified the \-@ARGUMENTOPT@ option but forgot the argument.
  404. X.TP
  405. XMissing rcfile
  406. XYou specified the \-@MAILFILTOPT@ option, procmail expects the name of an
  407. Xrcfile as argument.
  408. X.TP
  409. XMissing recipient
  410. XYou specified the \-@DELIVEROPT@ option or called procmail under a different
  411. Xname, it expects one or more recipients as arguments.
  412. X.TP
  413. XOut of memory
  414. XThe system is out of swap space (and NORESRETRY has been exhausted).
  415. X.TP
  416. XProcessing continued
  417. XThe unrecognised options on the command line are ignored, proceeding as
  418. Xusual.
  419. X.TP
  420. XProgram failure (nnn) of "x"
  421. XProgram that was started by procmail returned nnn instead of EX_OK (=@EX_OK@);
  422. Xif nnn is negative, then this is the signal the program died on.
  423. X.TP
  424. XRenaming bogus "x" into "x"
  425. XThe system mailbox of the recipient was found to be bogus, procmail performed
  426. Xevasive actions.
  427. X.TP
  428. XSkipped: "x"
  429. XCouldn't do anything with "x" in the rcfile (syntax error), ignoring it.
  430. X.TP
  431. XSuspicious rcfile "x"
  432. XThe owner of the rcfile was not the recipient or root, or the directory that
  433. Xcontained it was world writable (the rcfile was not used).
  434. X.TP
  435. XTerminating prematurely whilst waiting for .\|.\|.
  436. XProcmail received a signal while it was waiting for .\|.\|.
  437. X.TP
  438. XTimeout, terminating "x"
  439. XTimeout has occurred on program or filter "x".
  440. X.TP
  441. XTimeout, was waiting for "x"
  442. XTimeout has occurred on program, filter or file "x".  If it was a program or
  443. Xfilter, then it didn't seem to be running anymore.
  444. X.TP
  445. XTruncating "x" and retrying lock
  446. X"x" does not seem to be a valid filename or the file is not empty.
  447. X.TP
  448. XRescue of unfiltered data succeeded/failed
  449. XA filter returned unsuccessfully, procmail tried to get back the original text.
  450. X.TP
  451. XUnexpected EOL
  452. XMissing closing quote, or trying to escape EOF.
  453. X.TP
  454. XUnknown user "x"
  455. XThe specified recipient does not have a corresponding uid.
  456. X.SH "EXTENDED DIAGNOSTICS"
  457. XExtended diagnostics can be turned on and off through setting the
  458. XVERBOSE variable.
  459. X.TP 2.3i
  460. X[pid] time & date
  461. XProcmail's pid and a timestamp.  Generated whenever procmail logs a
  462. Xdiagnostic and at least a second has elapsed since the last timestamp.
  463. X.TP
  464. XAcquiring kernel-lock
  465. XProcmail now tries to kernel-lock the most recently opened file(descriptor).
  466. X.TP
  467. XAssigning "x"
  468. XEnvironment variable assignment.
  469. X.TP
  470. XBypassed locking "x"
  471. XThe mail spool directory was not accessible to procmail, it relied solely
  472. Xon kernel locks.
  473. X.TP
  474. XExecuting "x"
  475. XStarting program "x".  If it is started by procmail directly (without an
  476. Xintermediate shell), procmail will show where it separated the arguments
  477. Xby inserting commas.
  478. X.TP
  479. XHOST mismatched "x"
  480. XThis host was called "x", HOST contained something else.
  481. X.TP
  482. XLocking "x"
  483. XCreating lockfile "x".
  484. X.TP
  485. XLinking to "x"
  486. XCreating a hardlink between directory folders.
  487. X.TP
  488. XMatch on "x"
  489. XCondition matched.
  490. X.TP
  491. XNo match on "x"
  492. XCondition didn't match, recipe skipped.
  493. X.TP
  494. XNotified comsat: "$LOGNAME@offset:file"
  495. XSent comsat/biff a notice that mail arrived for user $LOGNAME at `offset'
  496. Xin `file'.
  497. X.TP
  498. XOpening "x"
  499. XOpening file "x" for appending.
  500. X.TP
  501. XRcfile: "x"
  502. XRcfile changed to "x".
  503. X.TP
  504. XReiterating kernel-lock
  505. XWhile attempting several locking methods, one of these failed.  Procmail will
  506. Xreiterate until they all succeed in rapid succession.
  507. X.TP
  508. XScore: added newtotal "x"
  509. XThis condition scored `added' points, which resulted in a `newtotal' score.
  510. X.TP
  511. XUnlocking "x"
  512. XRemoving lockfile "x" again.
  513. X.SH WARNINGS
  514. XYou should create a shell script that uses
  515. X.BR lockfile (1)
  516. Xbefore invoking your mail shell on any mailbox file other than the system
  517. Xmailbox (unless of course, your mail shell uses the same lockfiles (local
  518. Xor global) you specified in your rcfile).
  519. X.PP
  520. XIn the unlikely event that you absolutely need to kill procmail before it has
  521. Xfinished, first try and use the regular kill command (i.e.
  522. X.I not
  523. Xkill -9, see the subsection
  524. X.I Signals
  525. Xfor suggestions), otherwise some
  526. X.I lockfiles
  527. Xmight not get removed.
  528. X.PP
  529. XBeware when using the
  530. X.B \-@TEMPFAILOPT@
  531. Xoption, if procmail repeatedly is unable to deliver the mail (e.g. due to
  532. Xan incorrect rcfile), the system mailqueue could fill up.  This could
  533. Xaggravate both the local postmaster and other users.@ETCRC_warn@@ETCRCS_warn@
  534. X.SH BUGS
  535. XAfter removing a lockfile by force, procmail waits $SUSPEND seconds before
  536. Xcreating a new lockfile so that another process that decides to remove the
  537. Xstale lockfile will not remove the newly created lock by mistake.
  538. X.PP
  539. XProcmail uses the regular TERMINATE signal to terminate any runaway filter,
  540. Xbut it does not check if the filter responds to that signal and it only sends
  541. Xit to the filter itself, not to any of the filter's children.
  542. X.PP
  543. XA continued
  544. X.B Content-Length:
  545. Xfield is not handled correctly.
  546. X.SH MISCELLANEOUS
  547. XIf there is an existing
  548. X.B Content-Length:
  549. Xfield in the header of the mail procmail will trim it to report the right
  550. Xsize.  Procmail does not extend the field in length.
  551. X.PP
  552. XIf there is no
  553. X.B Content-Length:
  554. Xfield and procmail appends to regular mailfolders, any lines in the body of
  555. Xthe message that look like postmarks are prepended with `@ESCAP@' (disarms
  556. Xbogus mailheaders).  The regular expression that is used to search for these
  557. Xpostmarks is:
  558. X.RS
  559. X`@FROM_EXPR@'
  560. X.RE
  561. X.PP
  562. XIf the destination name used in explicit delivery mode is not in /etc/passwd,
  563. Xprocmail will proceed as if explicit delivery mode was not in effect.
  564. XIf not in explicit delivery mode and
  565. Xshould the uid procmail is running under, have no corresponding /etc/passwd
  566. Xentry, then HOME will default to @RootDir@, LOGNAME will default to #uid and
  567. XSHELL will default to @BinSh@.
  568. X.PP
  569. XWhen in explicit delivery mode, procmail will generate a leading `@FROM@'
  570. Xline if none is present.  If one is already present procmail will leave it
  571. Xintact.@TRUSTED_IDS@
  572. X.PP
  573. XFor security reasons procmail will only use an absolute or $HOME relative
  574. Xrcfile if it is either owned by the recipient or root and not world writable,
  575. Xor if the directory it is contained in is not world writable.
  576. X.PP
  577. XIf @SYSTEM_MBOX@ is a bogus mailbox (i.e. does not belong to the recipient,
  578. Xis unwritable, is a symbolic link or is a hard link), procmail will upon
  579. Xstartup try to rename it into a file starting with `@BOGUSprefix@' and
  580. Xending in an inode-sequence-code.  If this turns out to be impossible,
  581. X.B ORGMAIL
  582. Xwill have
  583. X.I no
  584. Xinitial value, and hence will inhibit delivery without a proper rcfile.
  585. X.PP
  586. XIf @SYSTEM_MBOX@ already is a valid mailbox, but has got too loose permissions
  587. Xon it, procmail will correct this.  To prevent procmail from doing this make
  588. Xsure the u+x bit is set.
  589. X.PP
  590. XWhen delivering to directories (or to MH folders) you
  591. X.B don't
  592. Xneed to use lockfiles to prevent several concurrently running procmail
  593. Xprograms from messing up.
  594. X.PP
  595. XDelivering to MH folders is slightly more time consuming than delivering
  596. Xto normal directories or mailboxes, because procmail has to search for
  597. Xthe next available number (instead of having the filename immediately
  598. Xavailable).
  599. X.PP
  600. XOn general failure procmail will return EX_CANTCREAT, unless option
  601. X.B \-@TEMPFAILOPT@
  602. Xis specified, in which case it will return EX_TEMPFAIL.
  603. X.PP
  604. XTo make `egrepping' of headers more consistent, procmail concatenates all
  605. Xcontinued header fields; but only internally.  When delivering the mail, line
  606. Xbreaks will appear as before.
  607. X.PP
  608. XIf procmail is called under a name not starting with `procmail' (i.e. if it
  609. Xis linked to another name and invoked as such), it comes up in explicit
  610. Xdelivery mode, and expects the recipients' names as command line arguments
  611. X(as if \-@DELIVEROPT@ had been specified).
  612. X.PP
  613. XComsat/biff notifications are done using @COMSATprotocol@.  They are sent off
  614. Xonce when procmail generates the regular logfile entry.  The notification
  615. Xmessages have the following extended format (or as close as you can get when
  616. Xfinal delivery was not to a file):
  617. X.RS
  618. X$LOGNAME@offset_of_message_in_mailbox@COMSATxtrsep@absolute_path_to_mailbox
  619. X.RE
  620. X.PP
  621. XWhenever procmail itself opens a file to deliver to, it
  622. X@KERNEL_LOCKING@.
  623. X.PP
  624. XProcmail is NFS-resistant and eight-bit clean.
  625. X.br
  626. X.ne 11
  627. X.SH NOTES
  628. XCalling up procmail with the \-@HELPOPT1@ or \-@HELPOPT2@ options will cause
  629. Xit to display a command-line help and recipe flag quick-reference page.
  630. X.PP
  631. X@CF_procmail@
  632. XIn this case your $HOME/@DOT_FORWARD@ (beware, it
  633. X.B has
  634. Xto be world readable) file should contain the line below.  Be sure to include
  635. Xthe single and double quotes, and it
  636. X.I must
  637. Xbe an
  638. X.I absolute
  639. Xpath.  The \fB#\fP\fIYOUR_USERNAME\fP is not actually a parameter that is
  640. Xrequired by procmail, in fact, it will be discarded by sh before procmail ever
  641. Xsees it; it is however a necessary kludge against overoptimising sendmail
  642. Xprograms:
  643. X.PP
  644. X.na
  645. X.nf
  646. X@FW_content@
  647. X.fi
  648. X.ad
  649. X.PP
  650. XProcmail can also be invoked to postprocess an already filled system
  651. Xmailbox.  This can be useful if you don't want to or can't use a
  652. X$HOME/@DOT_FORWARD@ file (in which case the following script could
  653. Xperiodically be called from within
  654. X.BR cron (1),
  655. Xor whenever you start reading mail):
  656. X.Sx 17
  657. X#!/bin/sh
  658. X
  659. Xif cd $HOME &&
  660. X test \-s @SYSTEM_MBOX@ &&
  661. X lockfile \-r0 \-l3600 .newmail.lock 2>/dev/null
  662. Xthen
  663. X  trap "rm \-f .newmail.lock" 1 2 3 15
  664. X  umask 077
  665. X  lockfile \-l3600 \-ml
  666. X  cat @SYSTEM_MBOX@ >>.newmail &&
  667. X   cat /dev/null >@SYSTEM_MBOX@
  668. X  lockfile \-mu
  669. X  formail \-@FM_SPLIT@ procmail <.newmail &&
  670. X   rm \-f .newmail
  671. X  rm \-f .newmail.lock
  672. Xfi
  673. Xexit 0
  674. X.Ex
  675. X.ne 14
  676. X.SS "A sample small @PROCMAILRC@:"
  677. X.na
  678. X.nf
  679. XPATH=/bin:/usr/bin:@BINDIR@
  680. XMAILDIR=$HOME/Mail      #you'd better make sure it exists
  681. XDEFAULT=$MAILDIR/mbox
  682. XLOGFILE=$MAILDIR/from
  683. X:0:
  684. X* ^From.*berg
  685. Xfrom_me
  686. X:0
  687. X* ^Subject:.*Flame
  688. X/dev/null
  689. X.fi
  690. X.ad
  691. END_OF_FILE
  692.   if test 20759 -ne `wc -c <'procmail-3.03/man/procmail.man'`; then
  693.     echo shar: \"'procmail-3.03/man/procmail.man'\" unpacked with wrong size!
  694.   fi
  695.   # end of 'procmail-3.03/man/procmail.man'
  696. fi
  697. if test -f 'procmail-3.03/man/procmailex.man' -a "${1}" != "-c" ; then 
  698.   echo shar: Will not clobber existing file \"'procmail-3.03/man/procmailex.man'\"
  699. else
  700.   echo shar: Extracting \"'procmail-3.03/man/procmailex.man'\" \(14982 characters\)
  701.   sed "s/^X//" >'procmail-3.03/man/procmailex.man' <<'END_OF_FILE'
  702. XPlease read the README file in this directory first.
  703. X.ex
  704. X.Id $Id: procmailex.man,v 1.31 1994/06/14 12:03:19 berg Exp $
  705. X.TH PROCMAILEX 5 \*(Dt BuGless
  706. X.na
  707. X.SH NAME
  708. Xprocmailex \- procmail rcfile examples
  709. X.SH SYNOPSIS
  710. X.B $HOME/@PROCMAILRC@ examples
  711. X.ad
  712. X.SH DESCRIPTION
  713. XFor a description of the rcfile format see
  714. X.BR procmailrc (5).
  715. X.PP
  716. XThe weighted scoring technique is described in detail in the
  717. X.BR procmailsc (5)
  718. Xman page.
  719. X.PP
  720. XThis man page shows several example recipes.  For examples of complete rcfiles
  721. Xyou can check the NOTES section in
  722. X.BR procmail (1),
  723. Xor look at the example rcfiles part of the procmail source distribution
  724. X(procmail*/examples/?procmailrc).
  725. X.SH EXAMPLES
  726. XSort out all mail coming from the scuba-dive mailing list into the mailfolder
  727. Xscubafile (uses the locallockfile scubafile.lock).
  728. X.Sx 3
  729. X:0:
  730. X* ^TOscuba
  731. Xscubafile
  732. X.Ex
  733. XForward all mail from peter about compilers to william (and keep a copy
  734. Xof it here in petcompil).
  735. X.Sx 10
  736. X:0
  737. X* ^From.*peter
  738. X* ^Subject:.*compilers
  739. X{
  740. X   :0 @CONTINUE@
  741. X   ! william@somewhere.edu
  742. X
  743. X   :0
  744. X   petcompil
  745. X}
  746. X.Ex
  747. XAn equivalent solution that accomplishes the same:
  748. X.Sx 7
  749. X:0 @CONTINUE@
  750. X* ^From.*peter
  751. X* ^Subject:.*compilers
  752. X! william@somewhere.edu
  753. X
  754. X   :0 @ALSO_NEXT_RECIPE@
  755. X   petcompil
  756. X.Ex
  757. XAn equivalent, but slightly slower solution that accomplishes the same:
  758. X.Sx 9
  759. X:0 @CONTINUE@
  760. X* ^From.*peter
  761. X* ^Subject:.*compilers
  762. X! william@somewhere.edu
  763. X
  764. X   :0
  765. X   * ^From.*peter
  766. X   * ^Subject:.*compilers
  767. X   petcompil
  768. X.Ex
  769. XIf your system doesn't generate or generates incorrect leading `From '
  770. Xlines on every mail, you can fix this by calling up procmail with
  771. Xthe \-@FROMWHOPT@@REFRESH_TIME@ option.  To fix the same problem by
  772. Xdifferent means, you could have inserted the following two
  773. Xrecipes above all other recipes in your rcfile.  They will filter the header
  774. Xof any mail through the first formail which will strip any leading `From '
  775. Xline, and then through the second formail which then regenerates it.
  776. X.Sx 5
  777. X:0 @FILTER@@PASS_HEAD@@WAIT_EXIT@
  778. X| formail \-@FM_DEL_INSERT@ "From "
  779. X
  780. X:0 @FILTER@@PASS_HEAD@@WAIT_EXIT@
  781. X| formail
  782. X.Ex
  783. XAdd the headers of all messages that didn't come from the postmaster
  784. Xto your private header collection (for
  785. Xstatistics or mail debugging); and use the lockfile `headc.lock'.  In order
  786. Xto make sure the lockfile is not removed until the pipe has finished,
  787. Xyou have to specify option `@WAIT_EXIT@'; otherwise the lockfile would be
  788. Xremoved as soon as the pipe has accepted the mail.
  789. X.Sx 3
  790. X:0 @PASS_HEAD@@WAIT_EXIT@@CONTINUE@:
  791. X* !@FROMMkey@
  792. X| uncompress headc.Z; cat >>headc; compress headc
  793. X.Ex
  794. XOr, if you would use the more efficient gzip instead of compress:
  795. X.Sx 3
  796. X:0 @PASS_HEAD@@WAIT_EXIT@@CONTINUE@:
  797. X* !@FROMMkey@
  798. X| gzip >>headc.gz
  799. X.Ex
  800. XForward all mails shorter than 1000 bytes to my home address (no lockfile
  801. Xneeded on this recipe).
  802. X.Sx 3
  803. X:0
  804. X* < 1000
  805. X! myname@home
  806. X.Ex
  807. XSplit up incoming digests from the surfing mailing list into their individual
  808. Xmessages, and store them into surfing, using surfing.lock as the locallockfile.
  809. X.Sx 3
  810. X:0:
  811. X* ^Subject:.*surfing.*Digest
  812. X| formail @FM_SKIP@1 \-@FM_DIGEST@@FM_SPLIT@ >>surfing
  813. X.Ex
  814. XStore everything coming from the postmaster or mailer-daemon (like bounced
  815. Xmail) into the file postm, using postm.lock as the locallockfile.
  816. X.Sx 3
  817. X:0:
  818. X* @FROMMkey@
  819. Xpostm
  820. X.Ex
  821. XA simple autoreply recipe.  It makes sure that neither mail from any daemon
  822. X(like bouncing mail or mail from mailing-lists), nor mail coming from yourself
  823. Xwill be autoreplied.  If this precaution would not be taken, disaster could
  824. Xresult (`ringing' mail).  In order for this recipe to autoreply to all the
  825. Xincoming mail, you should of course insert it before all other recipes in your
  826. Xrcfile.  However, it is advisable to put it
  827. X.I after
  828. Xany recipes that process the mails from subscribed mailinglists; it generally
  829. Xis not a good idea to generate autoreplies to mailinglists (yes, the
  830. X!^FROM_DAEMON regexp should already catch those, but if the mailinglist
  831. Xdoesn't follow accepted conventions, this might not be enough).
  832. X.Sx 4
  833. X:0 @PASS_HEAD@ @CONTINUE@
  834. X* !^FROM_DAEMON
  835. X* !^From +YOUR_USERNAME
  836. X| (formail \-@FM_REPLY@ \-@FM_ADD_ALWAYS@"Precedence: junk";\e
  837. X   echo "Mail received.") | $SENDMAIL \-t
  838. X.Ex
  839. XA more complicated autoreply recipe that implements the functional equivalent
  840. Xof the well known
  841. X.BR vacation (1)
  842. Xprogram.  This recipe is based on the same principles as the last one (prevent
  843. X`ringing' mail).  In addition to that however, it maintains a vacation database
  844. Xby extracting the name of the sender and appending it to the file
  845. X$ALREADYSENT, if the name is
  846. X.B not
  847. Xalready in there.  If the name was new, it's name will be appended to the
  848. Xdatabase and an autoreply will be sent.  To reliably extract the name of the
  849. Xsender, I let formail generate an autoreply header (thereby making it figure
  850. Xout the most appropriate sender address), and then telling it to extract the
  851. Xvalue of the `To:' field.
  852. X.Sx 17
  853. XSHELL=/bin/sh    # for other shells, this might need adjustment
  854. X
  855. X:0
  856. X* !^FROM_DAEMON
  857. X* !^From +YOUR_USERNAME
  858. X{
  859. X  FROM=`formail \-@FM_REPLY@@FM_EXTRACT@ To:`
  860. X  ALREADYSENT=$HOME/vacation     # the vacation database
  861. X
  862. X  :0 @CONTINUE@:                       # the lockfile is important
  863. X  * !? fgrep \-e "$FROM" $ALREADYSENT
  864. X  | echo $FROM >>$ALREADYSENT; \e
  865. X    (formail \-@FM_REPLY@@FM_ADD_ALWAYS@"Precedence: junk"; \e
  866. X      echo "I received your mail,"; \e
  867. X      echo "but I won't be back until Monday."; \e
  868. X      echo "-- "; cat $HOME/.signature \e
  869. X    ) | $SENDMAIL \-t
  870. X}
  871. X.Ex
  872. XStore all messages concerning TeX in separate, unique filenames, in a directory
  873. Xnamed texmail (this directory has to exist); there is no need to use lockfiles
  874. Xin this case, so we won't.
  875. X.Sx 3
  876. X:0
  877. X* (^TO|^Subject:.*)TeX[^t]
  878. Xtexmail
  879. X.Ex
  880. XThe same as above, except now we store the mails in numbered files (MH mail
  881. Xfolder), again the texmail directory should exist already.
  882. X.Sx 3
  883. X:0
  884. X* (^TO|^Subject:.*)TeX[^t]
  885. Xtexmail/.
  886. X.Ex
  887. XOr you could file the mail in several directory folders at the same time.
  888. XThe following recipe will deliver the mail to two MH-folders and one
  889. Xdirectory folder.  It is actually only one file with two extra hardlinks.
  890. X.Sx 3
  891. X:0
  892. X* (^TO|^Subject:.*)TeX[^t]
  893. Xtexmail/. wordprocessing dtp/.
  894. X.Ex
  895. XStore all the messages about meetings in a folder that is in a directory
  896. Xthat changes every month.  E.g. if it were January 1994, the folder
  897. Xwould have the name `94-01/meeting' and the locallockfile would be
  898. X`94-01/meeting.lock'.
  899. X.Sx 3
  900. X:0:
  901. X* meeting
  902. X`date +%y-%m`/meeting
  903. X.Ex
  904. XThe same as above, but, if the `94-01' directory wouldn't have existed, it
  905. Xis created automatically:
  906. X.Sx 9
  907. XMONTHFOLDER=`date +%y-%m`
  908. X
  909. X:0 @IGNORE_WRITERR@@CONTINUE@
  910. X* ? test ! \-d $MONTHFOLDER
  911. X| mkdir $MONTHFOLDER
  912. X
  913. X:0:
  914. X* meeting
  915. X${MONTHFOLDER}/meeting
  916. X.Ex
  917. XThe same as above, but now by slightly different means:
  918. X.Sx 6
  919. XMONTHFOLDER=`date +%y-%m`
  920. XDUMMY=`test \-d $MONTHFOLDER || mkdir $MONTHFOLDER`
  921. X
  922. X:0:
  923. X* meeting
  924. X${MONTHFOLDER}/meeting
  925. X.Ex
  926. XIf you are subscribed to several mailinglists and people cross-post to
  927. Xsome of them, you usually receive several duplicate mails (one from every
  928. Xlist).  The following simple recipe eliminates duplicate mails.  It tells
  929. Xformail to keep an 8KB cache file in which it will store the Message-IDs of
  930. Xthe most recent mails you received.  Since Message-IDs are guaranteed to
  931. Xbe unique for every new mail, they are ideally suited to weed out duplicate
  932. Xmails.  Simply put the following recipe at the top of your rcfile, and
  933. Xno duplicate mail will get past it.
  934. X.Sx 2
  935. X:0 @WAIT_EXIT_QUIET@@PASS_HEAD@: msgid.lock
  936. X| formail \-@FM_DUPLICATE@ 8192 msgid.cache
  937. X.Ex
  938. XWhen delivering to emacs folders (i.e. mailfolders managed by any emacs
  939. Xmail package, e.g. RMAIL or VM) directly, you should use emacs-compatible
  940. Xlockfiles.  The emacs mailers are a bit braindamaged in that respect, they get
  941. Xvery upset if someone delivers to mailfolders which they already have in their
  942. Xinternal buffers.  The following recipe assumes that $HOME equals /home/john.
  943. X.Sx 5
  944. XMAILDIR=Mail
  945. X
  946. X:0:/usr/local/lib/emacs/lock/!home!john!Mail!mailbox
  947. X* ^Subject:.*whatever
  948. Xmailbox
  949. X.Ex
  950. XAlternatively, you can have procmail deliver into its own set of mailboxes,
  951. Xwhich you then periodically empty and copy over to your emacs files using
  952. X.BR movemail .
  953. XMovemail uses mailbox.lock local lockfiles per mailbox.
  954. X.PP
  955. XTo extract certain headers from a mail and put them into environment
  956. Xvariables you can use any of the following constructs:
  957. X.Sx 5
  958. XSUBJECT=`formail \-@FM_EXTRACT@Subject:`    # regular field
  959. XFROM=`formail \-@FM_REPLY@@FM_TRUST@ \-@FM_EXTRACT@To:`        # special case
  960. X
  961. X:0 @PASS_HEAD@                            # alternate method
  962. XKEYWORDS=| formail \-@FM_EXTRACT@Keywords:
  963. X.Ex
  964. XIf you are using temporary files in a procmailrc file, and want to make
  965. Xsure that they are removed just before procmail exits, you could use
  966. Xsomething along the lines of:
  967. X.Sx 2
  968. XTEMPORARY=$HOME/tmp/pmail.$$
  969. XTRAP="/bin/rm \-f $TEMPORARY"
  970. X.Ex
  971. XThe TRAP keyword can also be used to change the exitcode of procmail.
  972. XI.e. if you want procmail to return an exitcode of `1' instead of its
  973. Xregular exitcodes, you could use:
  974. X.Sx 3
  975. XEXITCODE=""
  976. XTRAP="exit 1;"   # The trailing semi-colon is important
  977. X                 # since exit is not a standalone program
  978. X.Ex
  979. XOr, if the exitcode does not need to depend on the programs run from
  980. Xthe TRAP, you can use a mere:
  981. X.Sx 1
  982. XEXITCODE=1
  983. X.Ex
  984. XThe following recipe prints every incoming mail that looks like a postscript
  985. Xfile.
  986. X.Sx 3
  987. X:0 @BODY_GREP@@PASS_BODY@
  988. X* ^^%!
  989. X| lpr
  990. X.Ex
  991. XThe following recipe does the same, but is a bit more selective.  It only
  992. Xprints the postscript file if it comes from the print-server.  The first
  993. Xcondition matches only if it is found in the header (i.e. no preceding empty
  994. Xline).  The second condition only matches at the start of the body (i.e.
  995. Xright after the
  996. X.B first
  997. Xempty line).
  998. X.Sx 4
  999. X:0 @HEAD_GREP@@BODY_GREP@ @PASS_BODY@
  1000. X* ^^(.+$)*From[ :].*print-server
  1001. X* ^^(.+$)*^%!
  1002. X| lpr
  1003. X.Ex
  1004. XThe same as above, but now by slightly different means:
  1005. X.Sx 7
  1006. X:0
  1007. X* ^From[ :].*print-server
  1008. X{
  1009. X  :0 @BODY_GREP@ @PASS_BODY@
  1010. X  * ^^%!
  1011. X  | lpr
  1012. X}
  1013. X.Ex
  1014. XSuppose you have two accounts, you use both accounts regularly, but they are
  1015. Xin very distinct places (i.e. you can only read mail that arrived at either one
  1016. Xof the accounts).  You would like to forward mail arriving at account one to
  1017. Xaccount two, and the other way around.  The first thing that comes to mind is
  1018. Xusing .forward files at both sites; this won't work of course, since you will
  1019. Xbe creating a mail loop.  This mail loop can be avoided by inserting the
  1020. Xfollowing recipe in front of all other recipes in the @PROCMAILRC@ files on
  1021. Xboth sites.  If you make sure that you add the same X-Loop: field at both
  1022. Xsites, mail can now safely be forwarded to the other account from either of
  1023. Xthem.
  1024. X.Sx 4
  1025. X:0 @CONTINUE@
  1026. X* !^X-Loop: yourname@your.main.mail.address
  1027. X| formail \-@FM_ADD_ALWAYS@ "X-Loop: yourname@your.main.mail.address" | \e
  1028. X   $SENDMAIL \-oi yourname@the.other.account
  1029. X.Ex
  1030. XIf someone sends you a mail with the word `retrieve' in the subject, the
  1031. Xfollowing will automatically send back the contents of info_file to the
  1032. Xsender.  Like in all recipes where we send mail, we watch out for mail
  1033. Xloops.
  1034. X.Sx 6
  1035. X:0
  1036. X* !^From +YOUR_USERNAME
  1037. X* !^Subject:.*Re:
  1038. X* !^FROM_DAEMON
  1039. X* ^Subject:.*retrieve
  1040. X| (formail \-@FM_REPLY@ ; cat info_file) | $SENDMAIL \-oi \-t
  1041. X.Ex
  1042. XNow follows an example for a very simple fileserver accessible by mail.
  1043. XFor more demanding applications, I suggest you take a look at the mailinglist
  1044. Xpackage included with the procmail source distribution.  The most notable
  1045. Xdeficiency of the `fileserver' you see below is that it doesn't do any
  1046. Xaccess checking.  It simply looks at the Subject: field in the header and
  1047. Xextracts the names mentioned after the word `request'.  These names are
  1048. Xput in the variable FILE, which is subsequently used to cat the files.
  1049. XThe best way to enhance this fileserver would probably be to create a shell
  1050. Xscript to take care of the more complicated checks and operations.
  1051. X.Sx 17
  1052. X:0
  1053. X* !^X-Loop: yourname@your.main.mail.address
  1054. X* !^Subject:.*Re:
  1055. X* !^FROM_DAEMON
  1056. X* ^Subject:.*request
  1057. X{
  1058. X  MAILDIR=$HOME/fileserver   # chdir to the fileserver directory
  1059. X
  1060. X  :0 @PASS_HEAD@             # extract the requested filename(s)
  1061. X  FILES=| sed \-n \-e 's/^Subject:.*request \(.*\)/\1/p'
  1062. X
  1063. X  :0 @FILTER@                # reverse the mailheader
  1064. X  | formail \-@FM_REPLY@@FM_ADD_ALWAYS@ "X-Loop: yourname@your.main.mail.address"
  1065. X
  1066. X  :0
  1067. X  | (cat; cat $FILES) | $SENDMAIL \-oi \-t
  1068. X}
  1069. X.Ex
  1070. XThe following example preconverts all plain-text mail arriving in certain
  1071. Xencoded MIME formats into a more compact 8-bit format which can be used
  1072. Xand displayed more easily by most programs.  The mmencode program is part
  1073. Xof Nathaniel Borenstein's metamail package.
  1074. X.Sx 17
  1075. X:0
  1076. X* ^Content-Type: *text/plain
  1077. X{
  1078. X  :0 @FILTER@@PASS_BODY@@WAIT_EXIT@
  1079. X  * ^Content-Transfer-Encoding: *quoted-printable
  1080. X  | mmencode \-u \-q
  1081. X
  1082. X     :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@
  1083. X     | formail \-@FM_DEL_INSERT@ "Content-Transfer-Encoding: 8bit"
  1084. X
  1085. X  :0 @FILTER@@PASS_BODY@@WAIT_EXIT@
  1086. X  * ^Content-Transfer-Encoding: *base64
  1087. X  | mmencode \-u \-b
  1088. X
  1089. X     :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@
  1090. X     | formail \-@FM_DEL_INSERT@ "Content-Transfer-Encoding: 8bit"
  1091. X}
  1092. X.Ex
  1093. XThe following one is rather exotic, but it only serves to demonstrate a
  1094. Xfeature.  Suppose you have a file in your HOME directory called ".urgent",
  1095. Xand the (one) person named in that file is the sender of an incoming mail,
  1096. Xyou'd like that mail to be stored in $MAILDIR/urgent instead of in any of the
  1097. Xnormal mailfolders it would have been sorted in.  Then this is what you could
  1098. Xdo (beware, the filelength of $HOME/.urgent should be well below $LINEBUF,
  1099. Xincrease LINEBUF if necessary):
  1100. X.Sx 5
  1101. XURGMATCH=`cat $HOME/.urgent`
  1102. X
  1103. X:0 @BODY_GREP@:
  1104. X* $^From.*${URGMATCH}.*
  1105. Xurgent
  1106. X.Ex
  1107. XAn entirely different application for procmail would be to conditionally
  1108. Xapply filters to a certain (outgoing) text or mail.  A typical example
  1109. Xwould be a filter through which you pipe all outgoing mail, in order
  1110. Xto make sure that it will be MIME encoded only if it needs to be.
  1111. XI.e. in this case you could start procmail in the middle of a pipe like:
  1112. X.Sx 1
  1113. Xcat newtext | procmail ./mimeconvert | mail chris@where.ever
  1114. X.Ex
  1115. XThe
  1116. X.B mimeconvert
  1117. Xrcfile could contain something like (the =0x80= and =0xff= should
  1118. Xbe substituted with the real 8-bit characters):
  1119. X.Sx 10
  1120. XDEFAULT=|     # pipe to stdout instead of
  1121. X              # delivering mail as usual
  1122. X:0 @BODY_GREP@@FILTER@@PASS_BODY@@WAIT_EXIT@
  1123. X* [=0x80=-=0xff=]
  1124. X| mmencode -q
  1125. X
  1126. X  :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@
  1127. X  | formail \-I 'MIME-Version: 1.0' \e
  1128. X     \-I 'Content-Type: text/plain; charset=ISO-8859-1' \e
  1129. X     \-I 'Content-Transfer-Encoding: quoted-printable'
  1130. X.Ex
  1131. X.SH "SEE ALSO"
  1132. X.na
  1133. X.nh
  1134. X.BR procmail (1),
  1135. X.BR procmailrc (5),
  1136. X.BR procmailsc (5),
  1137. X.BR sh (1),
  1138. X.BR csh (1),
  1139. X.BR mail (1),
  1140. X.BR mailx (1),
  1141. X.BR binmail (1),
  1142. X.BR uucp (1),
  1143. X.BR aliases (5),
  1144. X.BR sendmail (8),
  1145. X.BR egrep (1),
  1146. X.BR grep (1),
  1147. X.BR biff (1),
  1148. X.BR comsat (8),
  1149. X.BR lockfile (1),
  1150. X.BR formail (1)
  1151. X.hy
  1152. X.ad
  1153. END_OF_FILE
  1154.   if test 14982 -ne `wc -c <'procmail-3.03/man/procmailex.man'`; then
  1155.     echo shar: \"'procmail-3.03/man/procmailex.man'\" unpacked with wrong size!
  1156.   fi
  1157.   # end of 'procmail-3.03/man/procmailex.man'
  1158. fi
  1159. if test -f 'procmail-3.03/src/regexp.c' -a "${1}" != "-c" ; then 
  1160.   echo shar: Will not clobber existing file \"'procmail-3.03/src/regexp.c'\"
  1161. else
  1162.   echo shar: Extracting \"'procmail-3.03/src/regexp.c'\" \(14786 characters\)
  1163.   sed "s/^X//" >'procmail-3.03/src/regexp.c' <<'END_OF_FILE'
  1164. X/************************************************************************
  1165. X *    Custom regular expression library, *fully* egrep compatible    *
  1166. X *                                    *
  1167. X *    Seems to be perfect.                        *
  1168. X *                                    *
  1169. X *    Copyright (c) 1991-1994, S.R. van den Berg, The Netherlands    *
  1170. X *    #include "../README"                        *
  1171. X ************************************************************************/
  1172. X#ifdef RCS
  1173. Xstatic /*const*/char rcsid[]=
  1174. X "$Id: regexp.c,v 1.39 1994/06/28 16:56:43 berg Exp $";
  1175. X#endif
  1176. X#include "includes.h"
  1177. X#include "robust.h"
  1178. X#include "shell.h"
  1179. X#include "misc.h"
  1180. X#include "regexp.h"
  1181. X
  1182. X#define R_BEG_GROUP    '('
  1183. X#define R_OR        '|'
  1184. X#define R_END_GROUP    ')'
  1185. X#define R_0_OR_MORE    '*'
  1186. X#define R_0_OR_1    '?'
  1187. X#define R_1_OR_MORE    '+'
  1188. X#define R_DOT        '.'
  1189. X#define R_SOL        '^'
  1190. X#define R_EOL        '$'
  1191. X#define R_BEG_CLASS    '['
  1192. X#define R_NOT_CLASS    '^'
  1193. X#define R_RANGE        '-'
  1194. X#define R_END_CLASS    ']'
  1195. X#define R_ESCAPE    '\\'
  1196. X
  1197. X#define R_BEG_WORD    '<'
  1198. X#define R_END_WORD    '>'
  1199. X#define NO_WORD_CLASS    "[^a-zA-Z0-9_]"
  1200. X
  1201. X#define BITS_P_CHAR        8
  1202. X#define OPB            (1<<BITS_P_CHAR)
  1203. X#define DONE_NODE        (OPB<<1)
  1204. X#define DONE_MASK        (DONE_NODE-1)
  1205. X#define LOOPL_NODE        (OPB<<2)
  1206. X#define LOOPR_NODE        (OPB<<3)
  1207. X#define LOOP_MASK        (LOOPL_NODE-1)
  1208. X#define OPC_SEMPTY        OPB              /* stack empty special */
  1209. X#define OPC_TSWITCH        (OPB+1)              /* task switch special */
  1210. X#define OPC_DOT            (OPB+2)
  1211. X#define OPC_BOTEXT        (OPB+3)
  1212. X#define OPC_EPS            (OPB+4)
  1213. X#define OPC_JUMP        (OPB+5)
  1214. X#define OPC_CLASS        (OPB+6)
  1215. X#define OPC_FIN            (OPB+7)
  1216. X#define OPC_FILL        (OPB+8)          /* filler opcode, not executed */
  1217. X          /* Don't change any opcode above without checking skplen[] */
  1218. X#define bit_type        unsigned
  1219. X#define bit_bits        (sizeof(bit_type)*8)
  1220. X#define bit_index(which)    ((unsigned)(which)/bit_bits)
  1221. X#define bit_mask(which)        ((unsigned)1<<(unsigned)(which)%bit_bits)
  1222. X#define bit_toggle(name,which)    (name[bit_index(which)]^=bit_mask(which))
  1223. X#define bit_test(name,which)    (!!(name[bit_index(which)]&bit_mask(which)))
  1224. X#define bit_set(name,which,value)    \
  1225. X (value?(name[bit_index(which)]|=bit_mask(which)):\
  1226. X (name[bit_index(which)]&=~bit_mask(which)))
  1227. X#define bit_field(name,size)    bit_type name[((size)+bit_bits-1)/bit_bits]
  1228. X
  1229. X#define SZ(x)        (sizeof(struct x))
  1230. X#define Ceps        (struct eps*)
  1231. X#define epso(to,add)    (Ceps((char*)(to)+(add)))
  1232. X#define ii        (aleps.topc)
  1233. X#define jj        (aleps.au.jju)
  1234. X#define spawn        sp.awn
  1235. X
  1236. Xstatic struct eps*r;
  1237. Xstatic struct{unsigned topc;union{struct eps*tnext;unsigned jju;}au;}aleps;
  1238. Xstatic uchar*p,*cachea,*cachep;
  1239. Xstatic size_t cacher;
  1240. Xstatic case_ignore,errorno;
  1241. X
  1242. Xstruct jump {unsigned opcj_;struct eps*nextj;};
  1243. Xstruct mchar {unsigned opcc_;struct eps*next1_,*p1_,*p2_;};
  1244. Xstruct chclass {unsigned opc_;struct eps*next_,*pos1,*pos2;
  1245. X bit_field(c,OPB);};
  1246. X                      /* length array, used by skiplen() */
  1247. Xstatic /*const*/char skplen[]=           /* it SHOULD have been const, but */
  1248. X {SZ(eps),SZ(jump),SZ(chclass),0,0};   /* some !@#$%^&*() compilers disagree */
  1249. X                               /* epsilon transition */
  1250. Xstatic void puteps(spot,to)struct eps*const spot;const struct eps*const to;
  1251. X{ spot->opc=OPC_EPS;spot->next=Ceps to;spot->spawn=0;
  1252. X}
  1253. X
  1254. X#define Cc(p,memb)    (((struct chclass*)(p))->memb)
  1255. X#define rAc        Cc(r,c)
  1256. X
  1257. Xstatic void bseti(i,j)unsigned i;const int j;
  1258. X{ bit_set(rAc,i,j);               /* mark 'i' as being in the class */
  1259. X  if(case_ignore)                  /* mark the other case too */
  1260. X   { if(i-'A'<'Z'-'A')                        /* uppercase */
  1261. X    i+='a'-'A';
  1262. X     else if(i-'a'<'z'-'a')                    /* lowercase */
  1263. X    i-='a'-'A';
  1264. X     else
  1265. X    return;                              /* no case */
  1266. X     bit_set(rAc,i,j);
  1267. X   }
  1268. X}
  1269. X                       /* general purpose length routine */
  1270. Xstatic struct eps*skiplen(ep)const struct eps*const ep;
  1271. X{ return epso(ep,(ep->opc&DONE_MASK)<OPC_EPS?
  1272. X   SZ(mchar):skplen[(ep->opc&DONE_MASK)-OPC_EPS]);
  1273. X}
  1274. X
  1275. Xstatic int por P((const struct eps*const e));
  1276. X
  1277. Xstatic void psimp(e)const struct eps*const e;
  1278. X{ switch(*p)
  1279. X   { case R_BEG_GROUP:p++;              /* not so simple after all */
  1280. X    if(por(e))
  1281. X       errorno=1;
  1282. X    return;
  1283. X     case R_BEG_CLASS:                       /* a simple class */
  1284. X      { unsigned i,j=R_NOT_CLASS==*++p;
  1285. X    if(e)
  1286. X     { r->opc=OPC_CLASS;r->next=Ceps e;Cc(r,pos1)=Cc(r,pos2)=0;
  1287. X       i=maxindex(rAc);
  1288. X       do rAc[i]=j?~0:0;                 /* preset the bit field */
  1289. X       while(i--);
  1290. X     }
  1291. X    if(j)                      /* skip the 'not' modifier */
  1292. X     { p++;
  1293. X       if(e)
  1294. X          bit_toggle(rAc,'\n');
  1295. X     }
  1296. X    if(*p==R_END_CLASS)      /* right at the start, cannot mean the end */
  1297. X     { p++;
  1298. X       if(e)
  1299. X          i=R_END_CLASS,bit_toggle(rAc,R_END_CLASS);
  1300. X     }
  1301. X    else if(*p==R_RANGE)                /* take it literally */
  1302. X     { p++;
  1303. X       if(e)
  1304. X          i=R_RANGE,bit_toggle(rAc,R_RANGE);
  1305. X     }
  1306. X    for(;;p++)
  1307. X     { switch(*p)
  1308. X        { case R_END_CLASS:p++;
  1309. X          case '\0':r=epso(r,SZ(chclass));
  1310. X         return;
  1311. X          case R_RANGE:
  1312. X         switch(*++p)
  1313. X          { default:
  1314. X               if(e)
  1315. X              while(++i<*p)            /* mark all in the range */
  1316. X                 bseti(i,!j);
  1317. X               break;
  1318. X            case '\0':case R_END_CLASS:p--;        /* literally */
  1319. X          }
  1320. X        }
  1321. X       if(e)
  1322. X          bseti(i= *p,!j);              /* a normal character, mark it */
  1323. X     }
  1324. X      }
  1325. X     case '\0':
  1326. X    return;
  1327. X     case R_DOT:             /* matches everything but a newline */
  1328. X    if(e)
  1329. X     { r->opc=OPC_DOT;
  1330. X       goto fine;
  1331. X     }
  1332. X    goto fine2;
  1333. X     case R_EOL:case R_SOL:              /* match a newline (in effect) */
  1334. X    if(p[1]==R_SOL)
  1335. X     { p++;
  1336. X       if(e)
  1337. X        {  r->opc=OPC_BOTEXT;
  1338. X           goto fine;
  1339. X        }
  1340. X     }
  1341. X    else if(e)
  1342. X     { r->opc='\n';
  1343. X       goto fine;
  1344. X     }
  1345. X    goto fine2;
  1346. X     case R_ESCAPE:                      /* quote something */
  1347. X    switch(*++p)
  1348. X     { case R_BEG_WORD:case R_END_WORD:
  1349. X        { uchar*pold=p;
  1350. X          p=(uchar*)NO_WORD_CLASS;psimp(e);p=pold+1;
  1351. X          if(e)
  1352. X         bit_toggle(Cc(epso(r,-(int)SZ(chclass)),c),'\n');
  1353. X          return;
  1354. X        }
  1355. X       case '\0':p--;                 /* nothing to quote */
  1356. X     }
  1357. X   }
  1358. X  if(e)                              /* a regular character */
  1359. X   { r->opc=case_ignore&&(unsigned)*p-'A'<'Z'-'A'?*p+'a'-'A':*p;
  1360. Xfine:
  1361. X     r->next=Ceps e;Cc(r,pos1)=Cc(r,pos2)=0;
  1362. X   }
  1363. Xfine2:
  1364. X  p++;r=epso(r,SZ(mchar));
  1365. X}
  1366. X
  1367. X#define EOS(x)    (jj?Ceps e:(x))
  1368. X
  1369. Xstatic void pnorm(e)const struct eps*const e;
  1370. X{ void*pold;struct eps*rold;
  1371. X  for(;;)
  1372. X   { pold=p;rold=r;psimp(Ceps 0);ii= *p;            /* skip it first */
  1373. X     jj=p[1]==R_OR||p[1]==R_END_GROUP||!p[1];
  1374. X     if(e)
  1375. X    p=pold,pold=r;
  1376. X     switch(ii)               /* check for any of the postfix operators */
  1377. X      { case R_0_OR_MORE:r++;
  1378. X       if(e)              /* first an epsilon, then the rest */
  1379. X          puteps(rold,EOS(r)),r=rold+1,psimp(rold);
  1380. X       goto incagoon;
  1381. X    case R_1_OR_MORE:                   /* first the rest */
  1382. X       if(e)                      /* and then an epsilon */
  1383. X        { puteps(r,rold);
  1384. X          if(jj)
  1385. X         (r+1)->opc=OPC_JUMP,(r+1)->next=Ceps e;
  1386. X          r=rold;psimp(Ceps pold);
  1387. X        }
  1388. X       r++;
  1389. X       if(p[1]==R_OR||p[1]==R_END_GROUP||!p[1])
  1390. X          r=epso(r,SZ(jump));
  1391. X       goto incagoon;
  1392. X    case R_0_OR_1:r++;
  1393. X       if(e)              /* first an epsilon, then the rest */
  1394. X          puteps(rold,r=EOS(r)),pold=r,r=rold+1,psimp(Ceps pold);
  1395. Xincagoon:  switch(*++p)            /* at the end of this group already? */
  1396. X        { case R_OR:case R_END_GROUP:case '\0':
  1397. X         return;
  1398. X        }
  1399. X       continue;                 /* regular end of the group */
  1400. X    case R_OR:case R_END_GROUP:case '\0':
  1401. X       if(e)
  1402. X          r=rold,psimp(e);
  1403. X       return;
  1404. X      }
  1405. X     if(e)            /* no fancy postfix operators, plain vanilla */
  1406. X    r=rold,psimp(Ceps pold);
  1407. X   }
  1408. X}
  1409. X
  1410. Xstatic int por(e)const struct eps*const e;
  1411. X{ uchar*pvold;struct eps*rvold;
  1412. X  if(!e)
  1413. X   { rvold=r;
  1414. X     if(cachea==(pvold=p))
  1415. X      { p=cachep;r=epso(rvold,cacher);
  1416. X    goto ret0;
  1417. X      }
  1418. X   }
  1419. X  for(;;)
  1420. X   { uchar*pold;struct eps*rold;
  1421. X     for(pold=p,rold=r;;)
  1422. X      { switch(*p)
  1423. X     { default:pnorm(Ceps 0);r=rold;          /* still in this group */
  1424. X          continue;
  1425. X       case '\0':case R_END_GROUP:           /* found the end of the group */
  1426. X          if(p==pold)                 /* empty 'or' group */
  1427. X           { if(e)
  1428. X            r->opc=OPC_JUMP,r->next=Ceps e;
  1429. X         r=epso(r,SZ(jump));
  1430. X           }
  1431. X          else
  1432. X         p=pold,pnorm(e);            /* normal last group */
  1433. X          if(!e)
  1434. X           { if(*p)
  1435. X            p++;
  1436. X         cachea=pvold;cachep=p;cacher=(char*)r-(char*)rvold;
  1437. X         goto ret0;
  1438. X           }
  1439. X          if(*p)
  1440. X           { p++;
  1441. Xret0:         return 0;
  1442. X           }
  1443. X          return 1;
  1444. X       case R_OR:r++;
  1445. X          if(p==pold)                 /* empty 'or' group */
  1446. X           { if(e)
  1447. X            puteps(rold,e);              /* special epsilon */
  1448. X           }
  1449. X          else
  1450. X           { p=pold;pnorm(e);          /* normal 'or' group, first an */
  1451. X         if(e)                   /* epsilon, then the rest */
  1452. X            puteps(rold,r);
  1453. X           }
  1454. X          p++;
  1455. X     }
  1456. X    break;
  1457. X      }
  1458. X   }
  1459. X}
  1460. X          /* go down recursively, mark loopbacks on the way up again */
  1461. Xstatic struct eps*maxback(down)struct eps*down;
  1462. X{ ii=0;                   /* didn't find a loop at this level (yet) */
  1463. X  for(;;)
  1464. X   { switch(down->opc&LOOP_MASK)            /* chase JUMP chains */
  1465. X      { default:
  1466. X       goto ret0;                 /* oops, not an EPS, return */
  1467. X    case OPC_JUMP:down->opc=OPC_JUMP|DONE_NODE;    /* mark them as used */
  1468. X    case OPC_JUMP|DONE_NODE:down=down->next;
  1469. X       continue;
  1470. X    case OPC_EPS|DONE_NODE:ii=1;   /* used EPS found, return loop number */
  1471. X       return down->spawn==Ceps&aleps?down:down->spawn;
  1472. X    case OPC_EPS:;            /* unused EPS found, the work starts */
  1473. X      }
  1474. X     break;
  1475. X   }
  1476. X  if(!down->spawn)     /* has it been visited (belongs to previous group?) */
  1477. X   { struct eps*left;                    /* no, so process it */
  1478. X     down->opc=OPC_EPS|DONE_NODE;down->spawn=Ceps&aleps;     /* mark as used */
  1479. X     left=maxback(down->next);           /* init loop no. and recurse left */
  1480. X     if(ii)                    /* loop found directly below us? */
  1481. X    down->opc|=LOOPL_NODE;                 /* mark a left-loop */
  1482. X     ;{ struct eps*right;         /* recurse right, take the smallest */
  1483. X    if((right=maxback(down+1))&&(char*)left>(char*)right)     /* loop no. */
  1484. X       left=right;
  1485. X      }
  1486. X     if(ii)                       /* loop found directly below? */
  1487. X      { down->opc|=LOOPR_NODE;                /* mark a right-loop */
  1488. X    if(!(down->opc&LOOPL_NODE))    /* if we didn't also have a left-loop */
  1489. X       ii=0;        /* we tell our predecessor we are not a loop */
  1490. X      }
  1491. X     if(!left)                        /* found no loop at all? */
  1492. X      { down->spawn=down;         /* then give ourselves our own loop no. */
  1493. X    goto ret0;
  1494. X      }
  1495. X     if((down->spawn=left)!=down)     /* save the loop no., check if it's us */
  1496. X    return left;                   /* if not, pass the number up */
  1497. X   }                     /* otherwise we are the end of the loop */
  1498. Xret0:
  1499. X  return 0;                           /* no loop whatsoever */
  1500. X}
  1501. X
  1502. Xstruct eps*bregcomp(a,ign_case)const char*const a;
  1503. X{ struct eps*st;size_t i;      /* first a trial run, determine memory needed */
  1504. X  skplen[OPC_FILL-OPC_EPS]=SZ(eps)-ioffsetof(struct eps,sp);  /* a constant! */
  1505. X  errorno=0;p=(uchar*)a;case_ignore=ign_case;r=Ceps&aleps;cachea=0;por(Ceps 0);
  1506. X  st=r=
  1507. X   malloc((i=(char*)r-(char*)&aleps)+sizeof r->opc);
  1508. X  p=(uchar*)a;
  1509. X  if(!por(epso(st,i)))                       /* really compile */
  1510. X     errorno=1;
  1511. X  r->opc=OPC_FIN;
  1512. X  if(errorno)
  1513. X     nlog("Invalid regexp"),logqnl(a);
  1514. X  for(r=st;;st=skiplen(st))         /* simplify the compiled code (i.e. */
  1515. X     switch(st->opc)              /* take out cyclic epsilon references) */
  1516. X      { case OPC_FIN:
  1517. X       return r;                         /* finished */
  1518. X    case OPC_EPS:             /* check for any closed epsilon circles */
  1519. X       if(!st->spawn)               /* they can't be executed */
  1520. X        { maxback(st);     /* if not visited yet, recurse and mark loops */
  1521. X          ;{ register struct eps*i;
  1522. X         for(i=r;;i=skiplen(i))         /* search the whole program */
  1523. X          { switch(i->opc&LOOP_MASK)
  1524. X             { default:                /* renumber regulars */
  1525. X            { register struct eps*f;        /* if needed */
  1526. X              if(((f=i->next)->opc&DONE_MASK)==OPC_EPS&&f->spawn)
  1527. X               { for(;f->spawn!=f;f=f->spawn);   /* search start */
  1528. X                 i->next=f;                  /* of loop */
  1529. X               }
  1530. X            }           /* spare the used nodes in this group */
  1531. X               case OPC_EPS|DONE_NODE:case OPC_JUMP|DONE_NODE:
  1532. X               case OPC_FILL:
  1533. X              continue;
  1534. X               case OPC_FIN:;
  1535. X             }
  1536. X            break;
  1537. X          }
  1538. X           }
  1539. X          ;{ register struct eps*i;
  1540. X         for(i=r;;i=skiplen(i))         /* search the whole program */
  1541. X          { switch(i->opc)      /* unmark/transform the used nodes */
  1542. X             { case OPC_EPS|DONE_NODE|LOOPL_NODE:i->next=i+1;
  1543. X               case OPC_EPS|DONE_NODE|LOOPR_NODE:i->sp.sopc=OPC_FILL;
  1544. X               case OPC_JUMP|DONE_NODE:i->opc=OPC_JUMP;
  1545. X              continue;
  1546. X               case OPC_EPS|DONE_NODE|LOOPL_NODE|LOOPR_NODE:
  1547. X               case OPC_EPS|DONE_NODE:i->opc=OPC_EPS;
  1548. X               default:
  1549. X              continue;
  1550. X               case OPC_FIN:;
  1551. X             }
  1552. X            break;
  1553. X          }
  1554. X           }
  1555. X        }
  1556. X      }
  1557. X}
  1558. X
  1559. X#define XOR1        \
  1560. X (ioffsetof(struct chclass,pos1)^ioffsetof(struct chclass,pos2))
  1561. X#define PC(this,t)    (*(struct eps**)((char*)(this)+(t)))
  1562. X
  1563. Xchar*bregexec(code,text,str,len,ign_case)struct eps*code;
  1564. X const uchar*const text;const uchar*str;size_t len;int ign_case;
  1565. X{ register struct eps*reg,*stack,*other,*thiss;unsigned i,th1,ot1;
  1566. X  struct eps*initstack,*initcode;
  1567. X  static struct mchar tswitch={OPC_TSWITCH,Ceps&tswitch};
  1568. X  static struct eps sempty={OPC_SEMPTY,&sempty};
  1569. X  sempty.spawn=initstack= &sempty;
  1570. X  if((initcode=code)->opc==OPC_EPS)
  1571. X     initcode=(initstack=code)+1,code->spawn= &sempty;
  1572. X  th1=ioffsetof(struct chclass,pos1);ot1=ioffsetof(struct chclass,pos2);
  1573. X  if(str--==text||*str=='\n') /* make sure any beginning-of-line-hooks catch */
  1574. X   { thiss=Ceps&tswitch;len++;i='\n';
  1575. X     goto setups;
  1576. X   }
  1577. X  other=Ceps&tswitch;
  1578. X  do
  1579. X   { i= *++str;                 /* get the next real-text character */
  1580. X     if(ign_case&&i-'A'<'Z'-'A')
  1581. X    i+='a'-'A';                 /* transmogrify it to lowercase */
  1582. Xlastrun:                     /* switch this & other pc-stack */
  1583. X     th1^=XOR1;ot1^=XOR1;thiss=other;
  1584. Xsetups:
  1585. X     other=Ceps&tswitch;stack=initstack;reg=initcode;
  1586. X     goto nostack;
  1587. X     for(;;)                 /* pop next entry off this pc-stack */
  1588. X      { thiss=PC(reg=thiss,th1);PC(reg,th1)=0;reg=reg->next;
  1589. X    goto nostack;
  1590. X    for(;;)                /* pop next entry off the work-stack */
  1591. X       for(reg=stack->next,stack=stack->spawn;;)
  1592. Xnostack:    { switch(reg->opc-OPB)
  1593. X           { default:
  1594. X            if(i==reg->opc)          /* regular character match */
  1595. X               goto yep;
  1596. X            break;        /* push spawned branch on the work-stack */
  1597. X         case OPC_EPS-OPB:reg->spawn=stack;reg=(stack=reg)+1;
  1598. X            continue;
  1599. X         case OPC_JUMP-OPB:reg=reg->next;
  1600. X            continue;
  1601. X         case OPC_FIN-OPB:
  1602. X            return (char*)str;               /* one past the match */
  1603. X         case OPC_SEMPTY-OPB:
  1604. X            goto empty_stack;
  1605. X         case OPC_TSWITCH-OPB:
  1606. X            goto pcstack_switch;
  1607. X         case OPC_BOTEXT-OPB:
  1608. X            if(str<text)           /* only at the very beginning */
  1609. X               goto yep;
  1610. X            break;
  1611. X         case OPC_CLASS-OPB:
  1612. X            if(bit_test(((struct chclass*)reg)->c,i))
  1613. X               goto yep;               /* character in class */
  1614. X            break;
  1615. X         case OPC_DOT-OPB:                 /* dot-wildcard */
  1616. X            if(i!='\n')
  1617. Xyep:               if(!PC(reg,ot1))             /* state not yet pushed */
  1618. X              PC(reg,ot1)=other,other=reg; /* push location onto */
  1619. X           }                       /* other pc-stack */
  1620. X          break;
  1621. X        }
  1622. Xempty_stack:;                      /* the work-stack is empty */
  1623. X      }
  1624. Xpcstack_switch:;                   /* this pc-stack is empty */
  1625. X   }
  1626. X  while(--len);                         /* still text to search */
  1627. X  if(ign_case!=2)                          /* out of text */
  1628. X   { ign_case=2;len=1;str++;
  1629. X     goto lastrun;                 /* check if we just matched */
  1630. X   }
  1631. X  return 0;                             /* no match */
  1632. X}
  1633. END_OF_FILE
  1634.   if test 14786 -ne `wc -c <'procmail-3.03/src/regexp.c'`; then
  1635.     echo shar: \"'procmail-3.03/src/regexp.c'\" unpacked with wrong size!
  1636.   fi
  1637.   # end of 'procmail-3.03/src/regexp.c'
  1638. fi
  1639. echo shar: End of archive 4 \(of 10\).
  1640. cp /dev/null ark4isdone
  1641. MISSING=""
  1642. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1643.     if test ! -f ark${I}isdone ; then
  1644.     MISSING="${MISSING} ${I}"
  1645.     fi
  1646. done
  1647. if test "${MISSING}" = "" ; then
  1648.     echo You have unpacked all 10 archives.
  1649.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1650. else
  1651.     echo You still must unpack the following archives:
  1652.     echo "        " ${MISSING}
  1653. fi
  1654. exit 0
  1655. exit 0 # Just in case...
  1656.