home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / procmail / part05 < prev    next >
Text File  |  1992-02-02  |  45KB  |  1,349 lines

  1. Newsgroups: comp.sources.misc
  2. From: berg@messua.informatik.rwth-aachen.de (Stephen R. van den Berg)
  3. Subject:  v28i005:  procmail - mail processing program v2.61, Part05/05
  4. Message-ID: <1992Feb2.030912.24307@sparky.imd.sterling.com>
  5. X-Md4-Signature: 336d75c5d8aa2448ce514e787f9bf642
  6. Date: Sun, 2 Feb 1992 03:09:12 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: berg@messua.informatik.rwth-aachen.de (Stephen R. van den Berg)
  10. Posting-number: Volume 28, Issue 5
  11. Archive-name: procmail/part05
  12. Environment: UNIX, sendmail, smail, MMDF
  13. Supersedes: procmail: Volume 25, Issue 01-04
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 5 (of 5)."
  22. # Contents:  procmail/man/procmail.man procmail/procmail.c
  23. # Wrapped by berg@tabaqui on Fri Jan 31 14:16:37 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'procmail/man/procmail.man' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'procmail/man/procmail.man'\"
  27. else
  28. echo shar: Extracting \"'procmail/man/procmail.man'\" \(23776 characters\)
  29. sed "s/^X//" >'procmail/man/procmail.man' <<'END_OF_FILE'
  30. X.de Id
  31. X.ds Rv \\$3
  32. X.ds Dt \\$4
  33. X..
  34. X.Id $Id: procmail.man,v 2.19 1992/01/31 12:50:54 berg Rel $
  35. X.de Sh
  36. X.br
  37. X.ne 11
  38. X.SH "\\$1"
  39. X..
  40. X.de Ss
  41. X.br
  42. X.ne 10
  43. X.SS "\\$1"
  44. X..
  45. X.de Tp
  46. X.br
  47. X.ne 9
  48. X.TP "\\$1"
  49. X..
  50. X.de Rs
  51. X.na
  52. X.nf
  53. X.RS
  54. X..
  55. X.de Re
  56. X.RE
  57. X.fi
  58. X.ad
  59. X..
  60. X.TH PROCMAIL 1 \*(Dt BuGless
  61. X.SH NAME
  62. X.na
  63. Xprocmail \- autonomous mail processor
  64. X.SH SYNOPSIS
  65. X.B procmail
  66. X[
  67. X.B \-+PRESERVOPT++TEMPFAILOPT+
  68. X]
  69. X.RI [ " parameter\fB=\fPvalue " | " rcfile " ]
  70. X\&.\|.\|.
  71. X.br
  72. X.B procmail
  73. X[
  74. X.B \-+PRESERVOPT++TEMPFAILOPT+
  75. X]
  76. X.B \-+DELIVEROPT+
  77. X.I recipient
  78. X.br
  79. X.B procmail
  80. X.B \-+VERSIONOPT+
  81. X.ad
  82. X.Sh DESCRIPTION
  83. XFor a quick start, see
  84. X.B NOTES
  85. Xat the end.
  86. X.LP
  87. X.B Procmail
  88. Xshould be invoked automatically over the
  89. X.B +DOT_FORWARD+
  90. Xfile mechanism as soon as mail arrives.  Alternatively, when installed by
  91. Xa system administrator, it can be invoked from within the mailer immediately.
  92. XWhen invoked, it first sets some environment variables to default values,
  93. Xreads the mail message from stdin until an EOF, separates the body from the
  94. Xheader, and then, if no command line arguments are present, it starts to look
  95. Xfor a file named
  96. X.B +PROCMAILRC+
  97. Xin your home directory.  According to the processing recipes in this file,
  98. Xthe mail message that just arrived gets distributed into the right folder
  99. X(and more).
  100. X.LP
  101. XIf running suid root or with root priviliges, procmail will be able to
  102. Xperform as a functionally enhanced, backwards compatible mail delivery agent.
  103. X.Ss Defaults
  104. X.Tp 2.2i
  105. X.B "USER, HOME and SHELL"
  106. XYour (the recipient's) defaults
  107. X.Tp
  108. X.B SHELLMETAS
  109. X\&+DEFshellmetas+
  110. X.Tp
  111. X.B SHELLFLAGS
  112. X\&+DEFshellflags+
  113. X.Tp
  114. X.BR ORGMAIL
  115. X\&+SYSTEM_MBOX+
  116. X.Tp
  117. X.B MAILDIR
  118. X\&+DEFmaildir+
  119. X.Tp
  120. X.B DEFAULT
  121. X\&+DEFdefault+
  122. X.Tp
  123. X.B MSGPREFIX
  124. X\&+DEFmsgprefix+
  125. X.Tp
  126. X.B SENDMAIL
  127. X\&+DEFsendmail+
  128. X.Tp
  129. X.B LOCKEXT
  130. X\&+DEFlockext+
  131. X.Tp
  132. X.B LOCKFILE
  133. X\&+DEFdefaultlock+
  134. X.br
  135. X(only if in explicit delivery mode and no rcfile is found)
  136. X.Ss Environment
  137. X.LP
  138. XBefore you get lost in the multitude of environment variables, keep in mind
  139. Xthat all of them have reasonable defaults.
  140. X.Tp 1.2i
  141. X.B MAILDIR
  142. XCurrent directory while procmail is executing (that means that all paths
  143. Xare relative to $MAILDIR).
  144. X.Tp
  145. X.B DEFAULT
  146. XDefault
  147. X.B mailbox
  148. Xfile (if not told otherwise, procmail will dump mail in this mailbox).
  149. X.Tp
  150. X.B MSGPREFIX
  151. XFilename prefix that is used when delivering to a directory (not used when
  152. Xdelivering to an MH directory).
  153. X.Tp
  154. X.B LOGFILE
  155. XAll incoming messages will be logged here with their `+FROM+' and `Subject:'
  156. Xlines in the header, and an additional line specifying what folder it
  157. Xfinally went to and how long (in bytes) the message was.  This file will
  158. Xalso contain any error or diagnostic messages from procmail
  159. X(normally none :-) or any other programs started by procmail.  If this file
  160. Xis not specified it defaults to
  161. X.BR +console+ .
  162. XYou can turn on
  163. X.I extended diagnostics
  164. Xby prepending a `+DEBUGPREFIX+' to the desired pathname.
  165. X.Tp
  166. X.B LOG
  167. XAnything assigned to this variable will be echoed in $LOGFILE.
  168. X.Tp
  169. X.B ORGMAIL
  170. XUsually the system mailbox (\fBOR\fPi\fBG\fPinal \fBMAIL\fPbox).  If, for
  171. Xsome obscure reason (like `\fBfilesystem full\fP') the mail could not be
  172. Xdelivered, then this mailbox will be the last resort.  If procmail
  173. Xfails to save the mail in here (deep, deep trouble :-), then the mail
  174. Xwill bounce back to the sender.
  175. X.Tp
  176. X.B LOCKFILE
  177. XGlobal semaphore file.  If this file already exists, procmail
  178. Xwill wait until it has gone before proceeding, and will create it itself
  179. X(cleaning it up when ready, of course).  If more than one
  180. X.I lockfile
  181. Xare specified, then the previous one will be removed before trying to create
  182. Xthe new one.
  183. X.Tp
  184. X.B LOCKEXT
  185. XDefault extension that is appended to a destination file to determine
  186. Xwhat local
  187. X.I lockfile
  188. Xto use (only if turned on, on a per-recipe basis).
  189. X.Tp
  190. X.B LOCKSLEEP
  191. XNumber of seconds procmail will sleep before retrying on a
  192. X.I lockfile
  193. X(if it already existed); if not specified, it defaults to +DEFlocksleep+
  194. Xseconds.
  195. X.Tp
  196. X.B LOCKTIMEOUT
  197. XNumber of seconds that have to have passed since a
  198. X.I lockfile
  199. Xwas last modified/created before procmail decides that this must be an
  200. Xerroneously leftover lockfile that can be removed by force now.  If zero,
  201. Xthen no timeout will be used and procmail will wait forever until the
  202. Xlockfile is removed; if not specified, it defaults to +DEFlocktimeout+ seconds.
  203. XThis variable is useful to prevent indefinite hangups of
  204. X.BR sendmail /procmail.
  205. X.Tp
  206. X.B TIMEOUT
  207. XNumber of seconds that have to have passed before procmail decides that
  208. Xsome child it started must be hanging.  The offending program will receive
  209. Xa TERMINATE signal from procmail, and processing of the rcfile will continue.
  210. XIf zero, then no timeout will be used and procmail will wait forever until the
  211. Xchild has terminated; if not specified, it defaults to +DEFtimeout+ seconds.
  212. X.Tp
  213. X.B HOST
  214. XIf this is not the
  215. X.I hostname
  216. Xof the machine, processing of the current
  217. X.I rcfile
  218. Xwill immediately cease. If other rcfiles were specified on the
  219. Xcommand line, processing will continue with the next one.  If all rcfiles
  220. Xare exhausted, the program will terminate, but will not generate an error
  221. X(i.e. to the mailer it will seem that the mail has been delivered).  Only the
  222. Xfirst +HOSTNAMElen+ characters of the HOST are significant.
  223. X.Tp
  224. X.B UMASK
  225. XThe name says it all (if it doesn't, then forget about this one :-).  It
  226. Xis taken as an
  227. X.B octal
  228. Xnumber.  If not specified, it defaults to +INIT_UMASK+.
  229. X.Tp
  230. X.B SHELLMETAS
  231. XIf any of the characters in SHELLMETAS appears in the line specifying
  232. Xa filter or program, the line will be fed to $SHELL
  233. Xinstead of being executed directly.
  234. X.Tp
  235. X.B SHELLFLAGS
  236. XAny invocation of $SHELL will be like:
  237. X.br
  238. X"$SHELL" "$SHELLFLAGS" "$*";
  239. X.Tp
  240. X.B SENDMAIL
  241. XIf you're not using the
  242. X.I forwarding
  243. Xfacility don't worry about this one.  It specifies the program being
  244. Xcalled to forward any mail.
  245. X.br
  246. XIt gets invoked as: "$SENDMAIL" "$@";
  247. X.Tp
  248. X.B NORESRETRY
  249. XNumber of retries that are to be made if any `\fBprocess table full\fP',
  250. X`\fBfile table full\fP', `\fBout of memory\fP' or
  251. X`\fBout of swap space\fP' error should occur.  If this number is negative,
  252. Xthen procmail will retry indefinitely; if not specified, it defaults to two
  253. Xtimes.  The retries occur with a $SUSPEND second interval.  The idea behind
  254. Xthis is, that if the
  255. X.I swap
  256. X.I space
  257. Xhas been exhausted or the
  258. X.I process
  259. X.I table
  260. Xis full, usually several other programs will either detect this
  261. Xand abort or crash 8-), and thereby freeing valuable
  262. X.I resources
  263. Xfor procmail.
  264. X.Tp
  265. X.B SUSPEND
  266. XNumber of seconds that procmail will pause if it has to wait for something
  267. Xthat is currently unavailable (memory, fork, etc.); if not specified, it will
  268. Xdefault to +DEFsuspend+ seconds.  See also:
  269. X.BR LOCKSLEEP .
  270. X.Tp
  271. X.B LINEBUF
  272. XLength of the internal line buffers, cannot be set smaller than +MINlinebuf+.
  273. XAll lines read from the rcfile
  274. X.RI ( not
  275. Xthe mail itself, which can have arbitrary line lengths, or could be a binary
  276. Xfile for that matter) should not exceed $LINEBUF characters before and after
  277. Xexpansion.  If not specified, it defaults to +DEFlinebuf+.
  278. X.Tp
  279. X.B DELIVERED
  280. XIf set (to a dummy value) procmail will pretend (to the mail agent) the mail
  281. Xhas been delivered.  If mail cannot be delivered after meeting this
  282. Xassignment, the mail will be lost (i.e. it will not bounce).
  283. X.Ss Signals
  284. X.Tp 1.2i
  285. X.B TERMINATE
  286. XTerminate prematurely and requeue the mail.
  287. X.Tp
  288. X.B HANGUP
  289. XTerminate prematurely and bounce the mail.
  290. X.Tp
  291. X.B INTERRUPT
  292. XTerminate prematurely and bounce the mail.
  293. X.Tp
  294. X.B QUIT
  295. XTerminate prematurely and silently lose the mail.
  296. X.Tp
  297. X.B ALARM
  298. XForce a timeout (see
  299. X.BR TIMEOUT).
  300. X.Sh OPTIONS
  301. X.Tp 0.5i
  302. X.B \-+VERSIONOPT+
  303. XProcmail will print its version number and exit.
  304. X.Tp
  305. X.B \-+PRESERVOPT+
  306. XPreserve any old environment.  Normally procmail clears the environment
  307. Xupon startup. However, in any case: any default values will override any
  308. Xpreexisting environment variables, i.e. procmail will not pay any attention
  309. Xto any predefined environment variables, it will happily overwrite them
  310. Xwith his own defaults.
  311. X.Tp
  312. X.B \-+TEMPFAILOPT+
  313. XMake procmail fail softly, i.e. if procmail cannot deliver the mail to
  314. Xany of the destinations you gave, the mail will not bounce, but will return
  315. Xto the mailqueue.  Another delivery-attempt will be made at some time in
  316. Xthe future.
  317. X.Tp
  318. X.I "\fB\-+DELIVEROPT+\fP recipient"
  319. XThis turns on explicit delivery mode, delivery will be to the local user
  320. X.IR recipient .
  321. XThis, of course, only is possible if procmail has root priviliges.
  322. XFor security reasons procmail will refuse to accept more arguments when using
  323. Xthis mode, procmail will setuid to the intended recipient and will
  324. X.I only
  325. Xread the recipient's +PROCMAILRC+ file (if present, if not, delivery is like
  326. Xordinary mail).
  327. X.Sh ARGUMENTS
  328. XAny arguments containing an '=' are considered to be environment variable
  329. Xassignments, they will
  330. X.I all
  331. Xbe evaluated after the default values have been
  332. Xassigned and before the first rcfile is opened.
  333. X.LP
  334. XAny other arguments are presumed to be rcfile paths (absolute or relative to
  335. X$HOME); procmail will start with the first one it finds on the command line.
  336. XThe following ones will only be parsed if the preceding ones have a not
  337. Xmatching HOST-directive entry, or in case they should not exist.
  338. X.LP
  339. XIf no rcfiles are specified, it looks for
  340. X.BR $HOME/+PROCMAILRC+ .
  341. XIf not even that can be found processing will continue according to
  342. Xthe default settings of the environment variables and the ones specified
  343. Xon the command line.
  344. X.Sh "RCFILE FORMAT"
  345. XEnvironment variable
  346. X.B assignments
  347. Xand
  348. X.B recipes
  349. Xcan be freely intermixed in the rcfile. If any environment variable has
  350. Xa special meaning to procmail, it will be used appropiately the moment
  351. Xit is parsed. (i.e. you can change the current directory whenever you
  352. Xwant by specifying a new
  353. X.BR MAILDIR ,
  354. Xswitch lockfiles by specifying a new
  355. X.B LOCKFILE
  356. X(usually one won't need this particular application though), change
  357. Xthe umask at any time, etc., the possibilities are endless :-).
  358. X.LP
  359. XThe assignments and substitutions of these environment variables are handled
  360. Xexactly like in
  361. X.BR sh (1)
  362. X(that includes all possible quotes and escapes),
  363. Xwith the added bonus that blanks around the '=' sign are ignored and that,
  364. Xif an environment variable appears without a trailing '=', it will be
  365. Xremoved from the environment.
  366. X.LP
  367. X.Ss Comments
  368. XA word beginning with # and all the following characters up to a NEWLINE
  369. Xare ignored.
  370. X.Ss Recipes
  371. X.LP
  372. XA line starting with ':' marks the beginning of a recipe.  It has the
  373. Xfollowing format:
  374. X.LP
  375. X:
  376. X.RI [ " number " ]
  377. X.RI [ " flags " ]
  378. X.RI "[ : [" " locallockfile " "] ]"
  379. X.LP
  380. XThe
  381. X.I number
  382. Xis optional (defaults to 1) and specifies the number of conditionals
  383. Xfollowing this line.  Conditionals are complete lines that are passed on to
  384. Xthe internal egrep
  385. X.BR literally ,
  386. Xexcept for leading blanks.
  387. XIf a conditional starts with an '!', the condition is inverted.  If you really
  388. Xwant the conditional to start with an '!', precede the '!' by a '\\'.
  389. XThese conditionals are
  390. X.B completely
  391. Xcompatible to the normal egrep regular expressions.  Conditionals are anded; if
  392. X.I number
  393. Xis zero, then the condition is always true and no conditionals are expected
  394. Xnext.
  395. X.LP
  396. X.I Flags
  397. Xcan be any of the following:
  398. X.Tp 0.5i
  399. X.B +HEAD_GREP+
  400. XEgrep the header (default).
  401. X.Tp
  402. X.B +BODY_GREP+
  403. XEgrep the body.
  404. X.Tp
  405. X.B +DISTINGUISH_CASE+
  406. XTell the internal egrep to distinguish between upper and lower case (defaults
  407. Xto ignoring case).
  408. X.Tp
  409. X.B +ALSO_NEXT_RECIPE+
  410. XThis recipe will depend on the last preceding recipe without the
  411. X`+ALSO_NEXT_RECIPE+' or `+ALSO_N_IF_SUCC+' flag.  This allows you to chain
  412. Xactions that depend on a common condition.  The number of conditionals that
  413. Xare expected to follow default to none.
  414. X.Tp
  415. X.B +ALSO_N_IF_SUCC+
  416. XHas the same meaning as the `+ALSO_NEXT_RECIPE+' flag, but will depend on the
  417. X.I successful
  418. Xcompletion of the immediately preceding recipe as well.
  419. X.Tp
  420. X.B +PASS_HEAD+
  421. XFeed the header to the pipe (default).
  422. X.Tp
  423. X.B +PASS_BODY+
  424. XFeed the body to the pipe (default).
  425. X.Tp
  426. X.B +FILTER+
  427. XConsider the pipe as a filter (ignored if a file).
  428. X.Tp
  429. X.B +CONTINUE+
  430. XContinue processing rcfile even if this recipe matches (not needed if 'f'
  431. Xspecified).
  432. X.Tp
  433. X.B +WAIT_EXIT+
  434. XWait for the filter or program to finish and check its exitcode (normally
  435. Xignored); if the filter is unsuccessful, then the text will
  436. Xnot have been filtered.  This flag is also recommended if you specified any
  437. X.I locallockfile
  438. Xon this recipe.
  439. X.Tp
  440. X.B +IGNORE_WRITERR+
  441. XIgnore any write errors on this recipe (i.e. usually due to an early closed
  442. Xpipe).
  443. X.Ss "Local lockfile"
  444. X.LP
  445. XIf you put a second ':' on the first recipe line, then procmail will use a
  446. X.I locallockfile
  447. X(for this recipe only).  You optionally can specify the locallockfile
  448. Xto use; if you don't however, procmail
  449. Xwill use the filename specified as the destination (or the filename
  450. Xfollowing the first '>>') and will append $LOCKEXT to it.
  451. X.Ss "Recipe destination"
  452. X.LP
  453. XThe next line can start with the following characters:
  454. X.Tp
  455. X.B !
  456. XForwards to all the specified mail addresses.
  457. X.Tp
  458. X.B |
  459. XStarts the specified program, possibly in $SHELL if any
  460. Xof the characters $SHELLMETAS are found.
  461. X.LP
  462. XAnything else will be taken as a mailbox name (either a filename or a
  463. Xdirectory, absolute or relative to the current directory (see $MAILDIR)).
  464. XIf it is a filename (or nonexistent), the mail will be appended to it.  If
  465. Xit is a directory, the mail will be delivered to a newly created, guaranteed
  466. Xto be unique, file named $MSGPREFIX* in the specified directory.  If the
  467. Xdirectory name ends in "/.", then this directory is presumed to be an MH
  468. Xfolder; i.e. procmail will use the lowest number it finds available.
  469. X.Sh EXAMPLES
  470. XSome example recipes are listed below:
  471. X.br
  472. XSort out all mail to mailling list scuba-dive.
  473. X.LP
  474. X.ne 3
  475. X.Rs
  476. X:
  477. X^TOscuba
  478. Xscubafile
  479. X.Re
  480. X.LP
  481. XForward all mail from peter about compilers to william (and keep a copy
  482. Xof it here in petcompil).
  483. X.LP
  484. X.ne 6
  485. X.Rs
  486. X:2 +PASS_BODY++CONTINUE+
  487. X^From.*peter
  488. X^Subject:.*compilers
  489. X! william@somewhere.edu
  490. X:+ALSO_NEXT_RECIPE+
  491. Xpetcompil
  492. X.Re
  493. X.LP
  494. XAdd the headers of all messages that didn't come from the postmaster
  495. Xto your private header collection (for
  496. Xstatistics or mail debugging); and use the lockfile `headc.lock'.  In order
  497. Xto make sure the lockfile is not removed until the pipe has finished,
  498. Xyou have to specify option 'w'; otherwise the lockfile would be removed as
  499. Xsoon as the pipe has accepted the mail.
  500. X.LP
  501. X.ne 3
  502. X.Rs
  503. X:+PASS_HEAD++WAIT_EXIT++CONTINUE+:
  504. X!From +(postmaster|Mailer)
  505. X| uncompress headc.Z; cat >>headc; compress headc
  506. X.Re
  507. X.Sh CAVEATS
  508. XIf you don't explicitly tell procmail to wait (recipe option 'w') for a
  509. Xprogram to finish, it won't wait and will terminate early (not knowing if
  510. Xthe program returns success).  That also means that any locallockfile on this
  511. Xrecipe might get removed
  512. X.I before
  513. Xthe program has terminated.
  514. X.LP
  515. XContinued lines in a recipe that are to be executed are concatenated
  516. X.I before
  517. Xbeing parsed, hence
  518. X.I any
  519. Xbackslash-newline combinations in them are removed regardless.
  520. X.LP
  521. XDon't put comments on the condition lines (the regular expressions) in a recipe,
  522. Xthese lines are fed to the internal egrep
  523. X.IR literally .
  524. X(Except for any
  525. X.I leading
  526. Xwhitespace, `!' or `\\', it will be stripped.
  527. XPrecede it by a `\\' if you want it to be taken literally too.)
  528. X.LP
  529. XWatch out for deadlocks when doing unhealthy things like forwarding mail
  530. Xto your own account.  Deadlocks can be broken by proper use of
  531. X.BR LOCKTIMEOUT .
  532. X.LP
  533. XAny default values that procmail has for some environment variables will
  534. X.B always
  535. Xoverride the ones that were already defined.  If you really want to
  536. Xoverride the defaults, you either have to put them in the
  537. X.B rcfile
  538. Xor in the command line as arguments.
  539. X.Sh FILES
  540. X.Tp 2.3i
  541. X.B /etc/passwd
  542. Xto get the recipient's USER, HOME and SHELL variable defaults
  543. X.Tp
  544. X.B +SYSTEM_MBOX+
  545. Xsystem mailbox
  546. X.Tp
  547. X.B $HOME/+PROCMAILRC+
  548. Xdefault rcfile
  549. X.Tp
  550. X.B +SYSTEM_MBOX+.lock
  551. Xlockfile for the system mailbox (automatically used if no rcfile is found, not
  552. Xused by procmail otherwise unless you explicitly tell it to)
  553. X.Tp
  554. X.B +DEFsendmail+
  555. Xdefault mail forwarder
  556. X.Tp
  557. X.B +UNIQ_PREFIX+???`hostname`
  558. Xtemporary `unique' zero-length files created by procmail
  559. X.Sh "SEE ALSO"
  560. X.na
  561. X.BR sh (1),
  562. X.BR csh (1),
  563. X.BR mail (1),
  564. X.BR binmail (1),
  565. X.BR uucp (1C),
  566. X.BR aliases (5),
  567. X.BR sendmail (8),
  568. X.BR egrep (1V),
  569. X.BR lockfile (1),
  570. X.BR formail (1)
  571. X.ad
  572. X.Sh DIAGNOSTICS
  573. X.Tp 2.3i
  574. XBad substitution of "x"
  575. XNot a valid environment variable name specified.
  576. X.Tp
  577. XCouldn't unlock "x"
  578. XLockfile was already gone, or write permission to the directory were the
  579. Xlockfile is has been denied.
  580. X.Tp
  581. XError while writing to "x"
  582. XNonexistent subdirectory, no write permission, pipe died or disk full.
  583. X.Tp
  584. XExceeded LINEBUF
  585. XBuffer overflow detected, LINEBUF was too small, memory might be corrupted.
  586. X.Tp
  587. XFailed forking "x"
  588. XProcess table is full (and NORESRETRY has been exhausted).
  589. X.Tp
  590. XFailed to execute "x"
  591. XProgram not in path, or not executable.
  592. X.Tp
  593. XForced unlock denied on "x"
  594. XNo write permission in the directory where
  595. X.B lockfile
  596. Xresides, or more than one procmail trying to force a lock at exactly the same
  597. Xtime.
  598. X.Tp
  599. XForcing lock on "x"
  600. XSpecified
  601. X.B lockfile
  602. Xis going to be removed by force because of a timeout (see also:
  603. X.BR LOCKTIMEOUT ).
  604. X.Tp
  605. XLock failure on "x"
  606. XCan only occur if you specify some real weird (and illegal) lockfilenames
  607. Xor if the
  608. X.B lockfile
  609. Xcould not be created because of insufficient permissions or noexistent
  610. Xsubdirectories.
  611. X.Tp
  612. XMail bounced
  613. XProcmail hasn't been able to deliver the mail correctly.
  614. X.Tp
  615. XMail lost
  616. XProcmail could not bounce or requeue the mail anymore.
  617. X.Tp
  618. XMail requeued
  619. XProcmail could not deliver the mail, another delivery attempt will be done
  620. Xsome time in the future.
  621. X.Tp
  622. XOut of memory
  623. XThe system is out of swap space (and NORESRETY has been exhausted).
  624. X.Tp
  625. XProcessing continued
  626. XThe unrecognised options on the command line are ignored, proceeding as
  627. Xusual.
  628. X.Tp
  629. XProgram failure of "x"
  630. XProgram that was started by procmail didn't return EX_OK (=0).
  631. X.Tp
  632. XSkipped: "x"
  633. XCouldn't do anything with "x" in the rcfile (syntax error), ignoring it.
  634. X.Tp
  635. XTerminating prematurely whilst waiting for .\|.\|.
  636. XProcmail received a signal while it was waiting for .\|.\|.
  637. X.Tp
  638. XTimeout, terminating "x"
  639. XTimeout has occurred on program/filter "x".
  640. X.Tp
  641. XTruncating "x" and retrying lock
  642. X"x" does not seem to be a valid filename or the file is not empty.
  643. X.Tp
  644. XRescue of unfiltered data succeeded/failed
  645. XA filter returned unsuccessfully, procmail tried to get back the original text.
  646. X.Tp
  647. XUnexpected EOL
  648. XMissing closing quote, or trying to escape EOF.
  649. X.Sh "EXTENDED DIAGNOSTICS"
  650. X.Tp 2.3i
  651. XAssigning "x"
  652. XEnvironment variable assignment
  653. X.Tp
  654. XExecuting "x"
  655. XStarting program "x"
  656. X.Tp
  657. XHOST mismatched "x"
  658. XThis host was called "x", HOST contained something else
  659. X.Tp
  660. XLocking "x"
  661. XCreating lockfile "x"
  662. X.Tp
  663. XMatch on "x"
  664. XConditional matched
  665. X.Tp
  666. XNo match on "x"
  667. XConditional didn't match, recipe skipped
  668. X.Tp
  669. XOpening "x"
  670. XOpening file "x" for appending
  671. X.Tp
  672. XRcfile: "x"
  673. XRcfile changed to "x"
  674. X.Tp
  675. XUnlocking "x"
  676. XRemoving lockfile "x" again
  677. X.Sh WARNINGS
  678. XYou should create a shell script that uses
  679. X.BR lockfile (1)
  680. Xbefore invoking your mail shell on any mailbox file other than the system
  681. Xmailbox (unless of course, your mail shell uses the same lockfiles (local
  682. Xor global) you specified in your rcfile).
  683. X.LP
  684. XIn the unlikely event that you absolutely need to kill procmail before it has
  685. Xfinished, first try and use the regular kill command (i.e.
  686. X.I not
  687. Xkill -9, see the subsection
  688. X.I Signals
  689. Xfor suggestions), otherwise some
  690. X.I lockfiles
  691. Xmight not get removed.
  692. X.LP
  693. XBeware when using the
  694. X.B \-+TEMPFAILOPT+
  695. Xoption, if procmail repeatedly is unable to deliver the mail (e.g. due to
  696. Xan incorrect rcfile), the system mailqueue could fill up.  This could
  697. Xaggravate both the local postmaster and other users.
  698. X.LP
  699. X+IFS_DISCARDING+
  700. X.Sh BUGS
  701. XThe only substitutions of environment variables that can be handled by
  702. Xprocmail itself are of the type $name, ${name}, $$ and $\-; whereas $\- will
  703. Xbe substituted by the name of the last folder delivered to.
  704. X.LP
  705. XIf the standard
  706. X.BR getpwnam() (3)
  707. Xis case sensitive, and some users have login names with uppercase letters in
  708. Xthem, procmail will be unable to deliver mail to them, unless started with
  709. Xtheir uid.
  710. X.LP
  711. XAfter a lockfile is removed by force, a suspension of $SUSPEND seconds
  712. Xis taken into account, in order to prevent the inadvertent immediate removal
  713. Xof any newly created lockfile by another program.
  714. X.LP
  715. XA line buffer of length $LINEBUF is used when processing the
  716. X.IR rcfile ,
  717. Xany expansions
  718. X.B have
  719. Xto fit within this limit; if they don't, behaviour is undefined.
  720. X.LP
  721. XProcmail uses the regular TERMINATE signal to terminate any runaway filter,
  722. Xbut it does not check if the filter responds to that signal and it only sends
  723. Xit to the filter itself, not to any of the filter's children.
  724. X.LP
  725. XIf the global lockfile has a
  726. X.I relative
  727. Xpath, and the current directory
  728. Xis not the same as when the global lockfile was created, then the global
  729. Xlockfile will not be removed if procmail exits at that point (remedy:
  730. Xuse
  731. X.I absolute
  732. Xpaths to specify global lockfiles).
  733. X.LP
  734. XSome braindamaged mailers want
  735. X.I all
  736. Xlines that start with `+FROM+' to be escaped,
  737. Xprocmail only escapes those that could really be dangerous; to support those
  738. Xother mailers you should consider using
  739. X.BR formail (1)
  740. Xas a filter for all your mail.
  741. X.Sh MISCELLANEOUS
  742. XWhitespace is ignored in the rcfile, except on the
  743. Xlines that are fed to the internal egrep where only leading whitespace is
  744. Xignored; i.e. you can indent everything.
  745. X.LP
  746. XIf the regular expression starts with `\fB+TOkey+\fP' it will be substituted by
  747. X`\fB+TOsubstitute+\fP', which should catch all destination
  748. Xspecifications.
  749. X.LP
  750. XAny lines in the body of the message that look like postmarks are prepended
  751. Xwith `+ESCAP+' (disarms bogus mailheaders).  The regular expression that is
  752. Xused to search for these postmarks is:
  753. X.Rs
  754. X"+FROM_EXPR+"
  755. X.Re
  756. X.LP
  757. XShould the uid procmail is running under, have no corresponding /etc/passwd
  758. Xentry, then HOME will default to +Tmp+, USER will default to #uid.
  759. X.LP
  760. XIf +SYSTEM_MBOX+ is a bogus mailbox (i.e. does not belong to the recipient,
  761. Xis unwritable, is a symbolic link or is a hard link), procmail will upon
  762. Xstartup try to rename it into a file starting with `+BOGUSprefix+' and
  763. Xending in an inode-sequence-code.  If this turns out to be impossible,
  764. X.B ORGMAIL
  765. Xwill have
  766. X.I no
  767. Xinitial value.
  768. X.LP
  769. XWhen delivering to directories (or to MH folders) you
  770. X.B don't
  771. Xneed to use lockfiles to prevent several concurrently running procmail
  772. Xprograms from messing up.
  773. X.LP
  774. XDelivering to MH folders is slightly more time consuming than delivering
  775. Xto normal directories or mailboxes, because procmail has to search for
  776. Xthe first available number (instead of having the filename immediately
  777. Xavailable).
  778. X.LP
  779. XOn general failure procmail will return EX_CANTCREAT, unless option
  780. X.B \-+TEMPFAILOPT+
  781. Xis specified, in which case it will return EX_TEMPFAIL.
  782. X.LP
  783. XProcmail performs the locking in an NFS-secure way.
  784. X.Sh NOTES
  785. XFor
  786. X.I really
  787. Xcomplicated processing you can even consider calling
  788. X.B procmail
  789. Xrecursively.
  790. X.br
  791. X.ne 9
  792. X.LP
  793. XIf procmail is
  794. X.I not
  795. Xinstalled globally as the default mail delivery agent (ask your system
  796. Xadministrator), you have to make sure it is invoked when your mail arrives.
  797. XIn this case your $HOME/+DOT_FORWARD+ (beware, it
  798. X.B has
  799. Xto be world readable) file should contain (include the single and double
  800. Xquotes,
  801. X.I must
  802. Xbe an
  803. X.I absolute
  804. Xpath):
  805. X.LP
  806. X.na
  807. X.nf
  808. X+FW_content+
  809. X.fi
  810. X.ad
  811. X.br
  812. X.ne 14
  813. X.Ss "A sample small +PROCMAILRC+:"
  814. X.na
  815. X.nf
  816. XPATH=/bin:/usr/bin:/usr/local/bin
  817. XMAILDIR=$HOME/Mail      #you'd better make sure it exists
  818. XDEFAULT=$MAILDIR/mbox
  819. XLOGFILE=$MAILDIR/from
  820. XLOCKFILE=$HOME/.lockmail
  821. X:
  822. X^From.*berg
  823. Xfrom_me
  824. X:
  825. X^Subject:.*Flame
  826. X/dev/null
  827. X.fi
  828. X.ad
  829. X.Sh AUTHOR
  830. XStephen R. van den Berg at RWTH-Aachen, Germany
  831. X.Rs
  832. Xberg@messua.informatik.rwth-aachen.de
  833. Xberg@physik.tu-muenchen.de
  834. X.Re
  835. END_OF_FILE
  836. if test 23776 -ne `wc -c <'procmail/man/procmail.man'`; then
  837.     echo shar: \"'procmail/man/procmail.man'\" unpacked with wrong size!
  838. fi
  839. # end of 'procmail/man/procmail.man'
  840. fi
  841. if test -f 'procmail/procmail.c' -a "${1}" != "-c" ; then 
  842.   echo shar: Will not clobber existing file \"'procmail/procmail.c'\"
  843. else
  844. echo shar: Extracting \"'procmail/procmail.c'\" \(17403 characters\)
  845. sed "s/^X//" >'procmail/procmail.c' <<'END_OF_FILE'
  846. X/************************************************************************
  847. X *    procmail.c    an autonomous mail processor            *
  848. X *                                    *
  849. X *    Seems to be perfect.                        *
  850. X *                                    *
  851. X *    Copyright (c) 1990-1992, S.R. van den Berg, The Netherlands    *
  852. X *    The sources can be freely copied for non-commercial use.    *
  853. X *    #include "README"                        *
  854. X *                                    *
  855. X ************************************************************************/
  856. X#ifdef RCS
  857. Xstatic char rcsid[]="$Id: procmail.c,v 2.26 1992/01/31 11:35:36 berg Rel $";
  858. X#endif
  859. X#include "config.h"
  860. X#define MAIN
  861. X#include "procmail.h"
  862. X#include "shell.h"
  863. X#include "patchlevel.h"
  864. X
  865. Xchar*buf,*buf2,*globlock,*loclock,*tolock,*lastfolder;
  866. Xconst char shellflags[]="SHELLFLAGS",shell[]="SHELL",
  867. X shellmetas[]="SHELLMETAS",lockext[]="LOCKEXT",newline[]="\n",binsh[]=BinSh,
  868. X unexpeof[]="Unexpected EOL\n",*const*gargv,*sgetcp,*rcfile=PROCMAILRC,
  869. X dirsep[]=DIRSEP,msgprefix[]="MSGPREFIX",devnull[]=DevNull,Mail[]="Mail ",
  870. X executing[]="Executing",oquote[]=" \"",cquote[]="\"\n",procmailn[]="procmail",
  871. X whilstwfor[]=" whilst waiting for ",sdelivered[]="DELIVERED";
  872. Xstatic const char slinebuf[]="LINEBUF",tokey[]=TOkey,eumask[]="UMASK",
  873. X tosubstitute[]=TOsubstitute,lockfile[]="LOCKFILE",defaultf[]="DEFAULT",
  874. X maildir[]="MAILDIR",couldnread[]="Couldn't read",logfile[]="LOGFILE",
  875. X orgmail[]="ORGMAIL",user[]="USER",tmp[]=Tmp,home[]="HOME",sfolder[]=FOLDER,
  876. X sendmail[]="SENDMAIL",host[]="HOST",Log[]="LOG",From[]=FROM,
  877. X exflags[]=RECFLAGS,system_mbox[]=SYSTEM_MBOX;
  878. Xstruct varval strenvvar[]={{"LOCKSLEEP",DEFlocksleep},
  879. X {"LOCKTIMEOUT",DEFlocktimeout},{"SUSPEND",DEFsuspend},
  880. X {"NORESRETRY",DEFnoresretry},{"TIMEOUT",DEFtimeout}};
  881. Xlong lastdump;
  882. Xint retval=EX_CANTCREAT,sh,pwait,lcking,locknext,verbose,rc= -2,tofolder,
  883. X tofile,ignwerr,fakedelivery,linebuf=mx(DEFlinebuf,STRLEN(system_mbox)<<1);
  884. Xvolatile int nextexit;
  885. Xvolatile time_t alrmtime;
  886. Xpid_t thepid;
  887. X
  888. Xmain(argc,argv)const char*const argv[];
  889. X{ static char flags[maxindex(exflags)-1];
  890. X  char*themail,*thebody,*chp,*startchar,*chp2;long tobesent,filled;
  891. X  int i,lastcond,succeed;uid_t uid;gid_t gid;
  892. X  for(lastcond=i=argc=0;(chp=(char*)argv[++argc])&&*chp=='-';)
  893. X     for(;;)                           /* processing options */
  894. X      { switch(*++chp)
  895. X     { case VERSIONOPT:log(VERSION);return EX_OK;
  896. X       case PRESERVOPT:i=1;continue;
  897. X       case TEMPFAILOPT:retval=EX_TEMPFAIL;continue;
  898. X       case DELIVEROPT:
  899. X /*
  900. X  *    if delivery is not to the current uid, this option can be specified;
  901. X  *    for security reasons there may be NO command line arguments following
  902. X  *    it
  903. X  *    more command line arguments are only allowed if the uid is to be
  904. X  *    the recipient (i.e. the recipient started it itself, e.g. from its
  905. X  *    .forward file)
  906. X  */
  907. X          if(!chp[1]&&argv[++argc]&&!argv[argc+1])
  908. X           { lastcond=1;            /* save the recipient's name */
  909. X         for(chp=chp2=(char*)argv[argc];*chp;chp++)
  910. X            if(*chp>='A'&&*chp<='Z')     /* kludge it into lowercase */
  911. X               *chp+='a'-'A';        /* because getpwnam might be */
  912. X         break;                       /* case sensitive */
  913. X           }
  914. X       default:log("Unrecognised options:");logqnl(chp);log(PROCMAIL_USAGE);
  915. X          log("Processing continued\n");
  916. X       case '\0':;
  917. X     }
  918. X    break;
  919. X      }
  920. X  if(!i)
  921. X     *environ=0;                     /* drop the environment */
  922. X#ifndef DONT_DISCARD_IFS
  923. X  else
  924. X     sputenv("IFS");                     /* drop IFS in any case */
  925. X#endif
  926. X  gargv=argv+argc;umask(INIT_UMASK);thepid=getpid();fclose(stdout);
  927. X  fclose(stderr);rclose(STDOUT);rclose(STDERR);             /* sure is sure */
  928. X  if(0>opena(devnull)||0>opena(console)&&0>opena(devnull))
  929. X     return EX_OSFILE;              /* couldn't open stdout and stderr */
  930. X  setbuf(stdin,(char*)0);buf=malloc(linebuf);buf2=malloc(linebuf);chdir(tmp);
  931. X  ultstr(0,(unsigned long)(i=getuid()),buf);
  932. X {struct passwd*pass;
  933. X  if(geteuid()==ROOT_uid&&lastcond&&(pass=getpwnam(chp2))||(pass=getpwuid(i)))
  934. X    /*
  935. X     *    set preferred uid to the intended recipient
  936. X     */
  937. X   { gid=pass->pw_gid;uid=pass->pw_uid;
  938. X     setdef(home,pass->pw_dir);chdir(pass->pw_dir);
  939. X     setdef(user,pass->pw_name?pass->pw_name:buf);setdef(shell,pass->pw_shell);
  940. X   }
  941. X  else             /* user could not be found, set reasonable defaults */
  942. X    /*
  943. X     *    set preferred uid to nobody, just in case we are running as root
  944. X     */
  945. X   { setdef(home,tmp);setdef(user,buf);setdef(shell,binsh);
  946. X     setgid(gid=NOBODY_gid);setuid(uid=NOBODY_uid);
  947. X   }
  948. X  endpwent();
  949. X }
  950. X /*
  951. X  *    create the original/default mailbox file, chown it to the recipient
  952. X  */
  953. X  setdef(orgmail,system_mbox);chp=(char*)getenv(orgmail);
  954. X  strncpy(buf,chp,i=lastdirsep(chp)-chp);
  955. X {struct stat stbuf;    /* check if the recipient's system mailbox is a link */
  956. X  if(!lstat(chp,&stbuf))
  957. X     if(!(stbuf.st_mode&S_IWUSR)||S_ISLNK(stbuf.st_mode)||
  958. X      (S_ISDIR(stbuf.st_mode)?!(stbuf.st_mode&S_IXUSR):stbuf.st_nlink!=1))
  959. X    goto bogusbox;
  960. X     else if(stbuf.st_uid!=uid)             /* the recipient doesn't own it */
  961. X      {
  962. Xbogusbox:                         /* bogus mailbox found! */
  963. X    ultoan((unsigned long)stbuf.st_ino,          /* i-node numbered */
  964. X     strchr(strcpy(buf+i,BOGUSprefix),'\0'));
  965. X    if(rename(chp,buf))           /* try and move it out of the way */
  966. X       goto fishy;         /* couldn't rename, something is fishy here */
  967. X      }
  968. X     else
  969. X    goto notfishy;                       /* everything is fine */
  970. X  buf[i]='\0';
  971. X  if(!stat(buf,&stbuf)&&(stbuf.st_mode&S_IRWXG)==S_IRWXG&&
  972. X   stbuf.st_gid==(gid_t)(filled=getegid()))
  973. X     umask(INIT_UMASK&~S_IRWXG);                /* keep the gid? */
  974. X  else
  975. X     filled=gid;
  976. X  if(!NFSxopen(chp,NORMperm))           /* create one if it doesn't exist */
  977. X     chown(chp,uid,(gid_t)filled);         /* give it to the recipient */
  978. X  else                  /* we don't deliver to links, security reasons */
  979. Xfishy:
  980. X     sputenv(orgmail);
  981. X  umask(INIT_UMASK);
  982. Xnotfishy:;
  983. X }
  984. X  if(!lastcond)                       /* not explicit delivery mode */
  985. X    /*
  986. X     *    really change the uid now, since we are not in explicit delivery mode
  987. X     */
  988. X   { setgid(gid);setuid(uid);
  989. X   }
  990. X  setdef(shellmetas,DEFshellmetas);setdef(shellflags,DEFshellflags);
  991. X  setdef(maildir,DEFmaildir);setdef(defaultf,DEFdefault);
  992. X  setdef(sendmail,DEFsendmail);setdef(lockext,DEFlockext);
  993. X  setdef(msgprefix,DEFmsgprefix);chdir(getenv(maildir));nextrcfile();
  994. X  thebody=themail=malloc(1);filled=0;
  995. X#ifdef SIGXCPU
  996. X  signal(SIGXCPU,SIG_IGN);signal(SIGXFSZ,SIG_IGN);
  997. X#endif
  998. X  signal(SIGPIPE,SIG_IGN);signal(SIGTERM,srequeue);signal(SIGINT,sbounce);
  999. X  signal(SIGHUP,sbounce);signal(SIGQUIT,slose);
  1000. X  signal(SIGALRM,ftimeout);
  1001. Xchangedmail:
  1002. X  themail=readdyn(themail,&filled);             /* read in the mail */
  1003. Xonlyhead:
  1004. X  startchar=filled+(thebody=themail);
  1005. X  while(thebody<startchar&&*thebody++=='\n');         /* skip leading garbage */
  1006. X  while(thebody=egrepin("[^\n]\n[\n\t ]",thebody,(long)(startchar-thebody),1))
  1007. X     if(*--thebody!='\n')
  1008. X    thebody[-1]=' ';            /* concatenate continuated lines */
  1009. X     else
  1010. X    goto eofheader;               /* empty line marks end of header */
  1011. X  thebody=startchar;
  1012. Xeofheader:
  1013. X  for(chp=mx(themail,thebody-1);
  1014. X   chp=egrepin(FROM_EXPR,chp,(long)(startchar-chp),1);)
  1015. X   { while(*--chp!='\n');               /* where did this line start? */
  1016. X     ++chp;tmemmove(chp+1,chp,startchar++-chp);*chp=ESCAP;  /* bogus header! */
  1017. X     themail=realloc(chp2=themail,++filled+1);
  1018. X#define ADJUST(x)    ((x)=themail+((x)-chp2))
  1019. X     ADJUST(thebody);ADJUST(startchar);ADJUST(chp);
  1020. X   }
  1021. X  do                         /* main rcfile interpreter loop */
  1022. X   { alarm((unsigned)(alrmtime=0));                /* reset timeout */
  1023. X     while(chp=(char*)argv[argc])      /* interpret command line specs first */
  1024. X      { argc++;
  1025. Xlikearg:
  1026. X    strcpy(buf,chp);
  1027. X    if(chp=strchr(buf,'='))
  1028. X     { strcpy(sgetcp=buf2,++chp);readparse(chp,sgetc,2);goto argenv;
  1029. X     }
  1030. X      }
  1031. X     if(rc<0)                         /* open new rc file */
  1032. X      {     i=rc;
  1033. X     while(*buf='\0',0>bopen(strcat(
  1034. X      strchr(dirsep,*rcfile)?buf:cat(tgetenv(home),MCDIRSEP),rcfile)))
  1035. X     { log(couldnread);logqnl(buf);
  1036. X       if(!nextrcfile())              /* not available? try the next */
  1037. X        { if(i==-2&&!lastcond)     /* no rcfile & explicit delivery mode */
  1038. X           { chp=DEFdefaultlock;goto likearg;         /* acquire lock */
  1039. X           }
  1040. X          goto nomore_rc;
  1041. X        }
  1042. X     }
  1043. X       /*
  1044. X    *    set uid back to recipient in any case, since we might just
  1045. X    *    have opened his/her .procmailrc
  1046. X    */
  1047. X    succeed=lastcond=0;setgid(gid);setuid(uid);
  1048. X      }
  1049. X     unlock(&loclock);                /* unlock any local lockfile */
  1050. X     do skipspace();                      /* skip whitespace */
  1051. X     while(testb('\n'));
  1052. X     if(testb(':'))                       /* check for a recipe */
  1053. X      { readparse(buf,getb,0);sh=strtol(buf,&chp,10);
  1054. X    if(chp==buf)                     /* no number parsed */
  1055. X       sh= -1;
  1056. X    if(tolock)         /* clear temporary buffer for lockfile name */
  1057. X       free(tolock);
  1058. X    for(i=maxindex(flags);flags[i]=0,i--;);          /* clear the flags */
  1059. X    for(tolock=0,locknext=0;;)
  1060. X     { switch(i= *chp++)
  1061. X        { default:
  1062. X         if(!(chp2=strchr(exflags,i)))       /* check for a valid flag */
  1063. X          { --chp;break;
  1064. X          }
  1065. X         flags[chp2-exflags]=1;                 /* set the flag */
  1066. X          case ' ':case '\t':continue;
  1067. X          case '\0':
  1068. X         if(*chp!=TMNATE)        /* if not the real end, skip */
  1069. X            continue;
  1070. X         break;
  1071. X          case ':':locknext=1;        /* yep, local lockfile specified */
  1072. X         if(*chp||*++chp!=TMNATE)
  1073. X          { tolock=tstrdup(chp);chp=strchr(chp,'\0')+1;
  1074. X          }
  1075. X        }
  1076. X       if(concatenate(chp))
  1077. X          skipped(chp);                /* display any leftovers */
  1078. X       break;
  1079. X     }
  1080. X    if(sh<0)      /* assume the appropriate default nr of conditions */
  1081. X       sh=!flags[ALSO_NEXT_RECIPE]&&!flags[ALSO_N_IF_SUCC];
  1082. X    startchar=themail;tobesent=thebody-themail;
  1083. X    if(flags[BODY_GREP])               /* what needs to be egrepped? */
  1084. X       if(flags[HEAD_GREP])
  1085. X          tobesent=filled;
  1086. X       else
  1087. X        { startchar=thebody;tobesent=filled-tobesent;
  1088. X        }
  1089. X    i=flags[ALSO_NEXT_RECIPE]?lastcond:1;          /* init test value */
  1090. X    if(flags[ALSO_N_IF_SUCC])
  1091. X       i=lastcond&&succeed;        /* only if the last recipe succeeded */
  1092. X    while(sh--)                    /* any conditions (left) */
  1093. X     { skipspace();getbl(buf2);
  1094. X       if(!strncmp(buf2,tokey,STRLEN(tokey)))         /* magic TOkey? */
  1095. X          cat(tosubstitute,buf2+STRLEN(tokey));
  1096. X       else if(*buf=='!'&&!strncmp(buf2+1,tokey,STRLEN(tokey)))  /* yes! */
  1097. X          strcat(cat("!",tosubstitute),buf2+1+STRLEN(tokey));
  1098. X       else
  1099. X          strcpy(buf,buf2);
  1100. X       if(i)                 /* check out all conditions */
  1101. X        { i=!!egrepin((*buf=='!'||*buf=='\\')+buf,startchar,tobesent,
  1102. X           flags[DISTINGUISH_CASE])^*buf=='!';
  1103. X          if(verbose)
  1104. X           { log(i?"M":"No m");log("atch on");logqnl(buf);
  1105. X           }
  1106. X        }
  1107. X     }
  1108. X    if(!flags[ALSO_NEXT_RECIPE]&&!flags[ALSO_N_IF_SUCC])
  1109. X       lastcond=i;               /* save the outcome for posterity */
  1110. X    startchar=themail;tobesent=filled;        /* body, header or both? */
  1111. X    if(flags[PASS_HEAD])
  1112. X     { if(!flags[PASS_BODY])
  1113. X          tobesent=thebody-themail;
  1114. X     }
  1115. X    else if(flags[PASS_BODY])
  1116. X       tobesent-=(startchar=thebody)-themail;
  1117. X    chp=strchr(strcpy(buf,tgetenv(sendmail)),'\0');succeed=sh=0;
  1118. X    pwait=flags[WAIT_EXIT];ignwerr=flags[IGNORE_WRITERR];skipspace();
  1119. X    if(testb('!'))                     /* forward the mail */
  1120. X     { readparse(chp+1,getb,0);
  1121. X       if(i)
  1122. X          goto forward;
  1123. X     }
  1124. X    else if(testb('|'))                    /* pipe the mail */
  1125. X     { getbl(buf2);
  1126. X       for(chp=buf2;*(chp=strchr(chp,'\0')-1)=='\\'&&getbl(chp););
  1127. X       if(i)
  1128. X        { if(sh=!!strpbrk(buf2,tgetenv(shellmetas)))
  1129. X         strcpy(buf,buf2);     /* copy literally, shell will parse */
  1130. X          else
  1131. X           { sgetcp=buf2;readparse(buf,sgetc,0);    /* parse it yourself */
  1132. X           }
  1133. Xforward:      *buf2='\0';
  1134. X          if(!tolock)       /* an explicit lockfile specified already */
  1135. X           { chp=buf;
  1136. X         while(i= *chp)        /* find the implicit lockfile ('>>name') */
  1137. X            if(chp++,i=='>'&&*chp=='>')
  1138. X             { chp=pstrspn(chp+1," \t");
  1139. X               tmemmove(buf2,chp,i=strcspn(chp,EOFName));buf2[i]='\0';
  1140. X               if(sh)         /* expand any environment variables */
  1141. X            { chp=tstrdup(buf);sgetcp=buf2;readparse(buf,sgetc,0);
  1142. X              strcpy(buf2,buf);strcpy(buf,chp);free(chp);
  1143. X            }
  1144. X               break;
  1145. X             }
  1146. X           }
  1147. X          lcllock();inittmout(buf);
  1148. X          if(flags[FILTER])
  1149. X           { if(startchar==themail&&tobesent!=filled)     /* if only 'h' */
  1150. X          { long dfilled=0;
  1151. X            if(pipthrough(buf,startchar,tobesent))
  1152. X               continue;
  1153. X            chp=readdyn(malloc(1),&dfilled);filled-=tobesent;
  1154. X            if(tobesent<dfilled)   /* adjust buffer size (grow only) */
  1155. X               themail=realloc(themail,dfilled+filled);
  1156. X            tmemmove(themail+dfilled,thebody,filled);
  1157. X            tmemmove(themail,chp,dfilled);free(chp);
  1158. X            themail=realloc(themail,1+(filled+=dfilled));goto onlyhead;
  1159. X          }
  1160. X         if(pipthrough(buf,startchar,tobesent))
  1161. X            continue;
  1162. X         succeed=1;filled=startchar-themail;goto changedmail;
  1163. X           }
  1164. X          if(!pipin(buf,startchar,tobesent)&&(succeed=1,!flags[CONTINUE]))
  1165. X         goto mailed;
  1166. X        }
  1167. X     }
  1168. X    else           /* dump the mail into a mailbox file or directory */
  1169. X     { readparse(buf,getb,0);
  1170. X       if(concatenate(chp=strchr(buf,'\0')+1))
  1171. X          skipped(chp);                 /* report any leftovers */
  1172. X       if(i)
  1173. X        { strcpy(buf2,buf);lcllock();strcpy(buf2,buf);tofile=1;
  1174. X          if(dump(deliver(buf2),startchar,tobesent))
  1175. X         writeerr(buf);
  1176. X          else if(succeed=1,!flags[CONTINUE])
  1177. X         goto mailed;
  1178. X          tofile=tofolder=0;
  1179. X        }
  1180. X     }
  1181. X      }
  1182. X     else if(testb('#'))                   /* no comment :-) */
  1183. X    getbl(buf);
  1184. X     else                    /* then it must be an assignment */
  1185. X      { for(*(chp=buf)='\0';;)                /* get the variable name */
  1186. X     { switch(i=getb())
  1187. X        { case ' ':case '\t':skipspace();i=testb('=')?'=':0;
  1188. X          case '\n':case '=':case EOF:*chp='\0';goto eofvarname;
  1189. X        }
  1190. X       if(!alphanum(*chp++=i))
  1191. X          for(;;*chp++=i)             /* it was garbage after all */
  1192. X         switch(i=getb())
  1193. X          { case ' ':case '\t':case '\n':case EOF:*chp='\0';
  1194. X               skipped(buf);goto mainloop;
  1195. X          }
  1196. X     }
  1197. Xeofvarname:
  1198. X    if(i!='=')                   /* removal or assignment? */
  1199. X     { sputenv(buf);continue;
  1200. X     }
  1201. X    *chp='=';readparse(++chp,getb,1);
  1202. Xargenv: sputenv(buf);chp[-1]='\0';
  1203. X    if(!strcmp(buf,slinebuf))
  1204. X     { if((linebuf=renvint(0L,chp)+XTRAlinebuf)<MINlinebuf+XTRAlinebuf)
  1205. X          linebuf=MINlinebuf+XTRAlinebuf;           /* check minimum size */
  1206. X       free(buf);free(buf2);buf=malloc(linebuf);buf2=malloc(linebuf);
  1207. X     }
  1208. X    else if(!strcmp(buf,maildir))
  1209. X     { if(chdir(chp))
  1210. X        { log("Couldn't chdir to");logqnl(chp);
  1211. X        }
  1212. X     }
  1213. X    else if(!strcmp(buf,logfile))
  1214. X     { close(STDERR);
  1215. X       if(verbose=DEBUGPREFIX==*chp)         /* turn on diagnostics? */
  1216. X          chp++;
  1217. X       if(0>opena(chp))
  1218. X          if(0>opena(console))
  1219. X         retval=EX_OSFILE;      /* bad news, but can't tell anyone */
  1220. X          else
  1221. X         writeerr(chp);
  1222. X     }
  1223. X    else if(!strcmp(buf,Log))
  1224. X       log(chp);
  1225. X    else if(!strcmp(buf,sdelivered))            /* fake delivery */
  1226. X     { lcking=1;
  1227. X       if((thepid=sfork())>0)
  1228. X        { nextexit=2;lcking=0;return EX_OK; /* signals may cause trouble */
  1229. X        }
  1230. X       else
  1231. X        { if(!forkerr(thepid,procmailn))
  1232. X         fakedelivery=1;
  1233. X          thepid=getpid();lcking=0;
  1234. X          if(nextexit)             /* signals occurred so far? */
  1235. X           { log(newline);terminate();
  1236. X           }
  1237. X        }
  1238. X     }
  1239. X    else if(!strcmp(buf,lockfile))
  1240. X     { lockit(chp,&globlock);chown(chp,uid,gid);
  1241. X     }
  1242. X    else if(!strcmp(buf,eumask))
  1243. X       umask((int)strtol(chp,(char**)0,8));
  1244. X    else if(!strcmp(buf,host))
  1245. X     { if(strncmp(chp,chp2=(char*)hostname(),HOSTNAMElen))
  1246. X        { yell("HOST mismatched",chp2);
  1247. X          if(rc<0||!nextrcfile())          /* if no rcfile opened yet */
  1248. X           { retval=EX_OK;terminate();      /* exit gracefully as well */
  1249. X           }
  1250. X          rclose(rc);rc= -1;
  1251. X        }
  1252. X     }
  1253. X    else
  1254. X     { i=MAXvarvals;
  1255. X       do                      /* several numeric assignments */
  1256. X          if(!strcmp(buf,strenvvar[i].name))
  1257. X           { strenvvar[i].val=renvint(strenvvar[i].val,chp);break;
  1258. X           }
  1259. X       while(i--);
  1260. X     }
  1261. X      }
  1262. Xmainloop:;
  1263. X   }
  1264. X  while(rc<0||!testb(EOF));                /* main interpreter loop */
  1265. Xnomore_rc:
  1266. X  tofile=1;
  1267. X  if(dump(deliver(tgetenv(defaultf)),themail,filled))          /* default */
  1268. X   { writeerr(buf);        /* if it fails, don't panic, try the last resort */
  1269. X     if(dump(deliver(tgetenv(orgmail)),themail,filled))
  1270. X    writeerr(buf);goto mailerr;            /* now you can panic */
  1271. X   }
  1272. Xmailed:
  1273. X  retval=EX_OK;                  /* we're home free, mail delivered */
  1274. Xmailerr:
  1275. X  unlock(&loclock);*thebody='\0';      /* Terminate the header, just in case */
  1276. X  if(!strncmp(From,chp=themail,STRLEN(From)))  /* Check for a "From " header */
  1277. X   { if(chp=strchr(themail,'\n'))
  1278. X    *chp++='\0';
  1279. X     else
  1280. X    chp=thebody;
  1281. X     log(themail);log(newline);         /* preserve mailbox format (any length) */
  1282. X   }
  1283. X  if(chp=egrepin(NSUBJECT,chp,(long)(thebody-chp),0))
  1284. X   { for(chp2= --chp;*--chp2!='\n'&&*chp2;);
  1285. X     if(chp-++chp2>MAXSUBJECTSHOW)            /* keep it within bounds */
  1286. X    chp2[MAXSUBJECTSHOW]='\0';
  1287. X     *chp='\0';detab(chp2);log(" ");log(chp2);log(newline);
  1288. X   }
  1289. X  log(sfolder);i=strlen(strncpy(buf,lastfolder,MAXfoldlen))+STRLEN(sfolder);
  1290. X  buf[MAXfoldlen]='\0';detab(buf);log(buf);i-=i%TABWIDTH;    /* last dump */
  1291. X  do log(TABCHAR);
  1292. X  while((i+=TABWIDTH)<LENoffset);
  1293. X  ultstr(7,lastdump,buf);log(buf);log(newline);terminate();
  1294. X}
  1295. X
  1296. Xdirmail()                /* buf should contain directory name */
  1297. X{ char*chp;struct stat stbuf;
  1298. X  if((chp=strchr(buf,'\0')-1)-1>=buf&&chp[-1]==*MCDIRSEP&&*chp=='.')
  1299. X   { *chp='\0';strcpy(buf2,buf);               /* it ended in /. */
  1300. X   }
  1301. X  else
  1302. X   { chp=0;strcpy(buf2,strcat(buf,MCDIRSEP));
  1303. X   }
  1304. X  if(unique(buf2,strchr(buf2,'\0'),NORMperm))
  1305. X   { if(chp)
  1306. X      { unsigned long i=0;
  1307. X    do ultstr(0,++i,chp);               /* find first empty MH folder */
  1308. X    while(link(buf2,buf));
  1309. X    unlink(buf2);goto opn;
  1310. X      }
  1311. X     stat(buf2,&stbuf);
  1312. X     ultoan((unsigned long)stbuf.st_ino,      /* filename with i-node number */
  1313. X      strchr(strcat(buf,tgetenv(msgprefix)),'\0'));
  1314. X     if(!myrename(buf2,buf))           /* rename it, we need the same i-node */
  1315. Xopn:    return opena(buf);
  1316. X   }
  1317. X  return -1;
  1318. X}
  1319. END_OF_FILE
  1320. if test 17403 -ne `wc -c <'procmail/procmail.c'`; then
  1321.     echo shar: \"'procmail/procmail.c'\" unpacked with wrong size!
  1322. fi
  1323. # end of 'procmail/procmail.c'
  1324. fi
  1325. echo shar: End of archive 5 \(of 5\).
  1326. cp /dev/null ark5isdone
  1327. MISSING=""
  1328. for I in 1 2 3 4 5 ; do
  1329.     if test ! -f ark${I}isdone ; then
  1330.     MISSING="${MISSING} ${I}"
  1331.     fi
  1332. done
  1333. if test "${MISSING}" = "" ; then
  1334.     echo You have unpacked all 5 archives.
  1335.     rm -f ark[1-9]isdone
  1336. else
  1337.     echo You still need to unpack the following archives:
  1338.     echo "        " ${MISSING}
  1339. fi
  1340. ##  End of shell archive.
  1341. exit 0
  1342. -- 
  1343. Sincerely,                                berg@messua.informatik.rwth-aachen.de
  1344.            Stephen R. van den Berg (AKA BuGless).    berg@physik.tu-muenchen.de
  1345.  
  1346. He did a quarter of the work in *half* the time!
  1347.  
  1348. exit 0 # Just in case...
  1349.