home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume38 / procmail / part06 < prev    next >
Text File  |  1993-07-05  |  50KB  |  1,235 lines

  1. Newsgroups: comp.sources.misc
  2. From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  3. Subject: v38i025:  procmail - mail processing package v2.90, Part06/11
  4. Message-ID: <1993Jul1.151140.21429@sparky.imd.sterling.com>
  5. X-Md4-Signature: 67d7a60a2d5b53ceec60c1634904ee1f
  6. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Thu, 1 Jul 1993 15:11:40 GMT
  9. Approved: kent@sparky.imd.sterling.com
  10.  
  11. Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  12. Posting-number: Volume 38, Issue 25
  13. Archive-name: procmail/part06
  14. Environment: sendmail, smail, MMDF, mailsurr, UNIX, POSIX
  15. Supersedes: procmail: Volume 35, Issue 21-32,124,125
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 6 (of 11)."
  24. # Contents:  procmail/INSTALL procmail/mailinglist/INSTALL
  25. #   procmail/mailinglist/INTRO procmail/mailinglist/bin/delink
  26. #   procmail/src/goodies.c procmail/src/lockfile.c
  27. # Wrapped by berg@tubastos on Thu Jul  1 14:06:16 1993
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'procmail/INSTALL' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'procmail/INSTALL'\"
  31. else
  32. echo shar: Extracting \"'procmail/INSTALL'\" \(8379 characters\)
  33. sed "s/^X//" >'procmail/INSTALL' <<'END_OF_FILE'
  34. XDiscusses:
  35. X        1. Getting the lot to compile
  36. X        2. IMPORTANT info for people with remote filesystems (like NFS)
  37. X        3. DEBUGGING AID
  38. X        4. Setting up the environment
  39. X        5. Extra options if you are a system administrator
  40. X
  41. X                ---
  42. X
  43. X1. Getting the lot to compile
  44. X   --------------------------
  45. X
  46. XTo install procmail, lockfile and formail: edit Makefile & config.h accordingly
  47. Xand type 'make install'.
  48. XIntended configurable options in Makefile are:
  49. X    the install-destinations and the LOCKINGTEST directories.
  50. XIntended configurable options in config.h are:
  51. X    MMDF support, standard environment presettings, trusted userids.
  52. X
  53. X'make install' will:
  54. X      - implicitly do a 'make init', which will check your basic utilities for
  55. X    POSIX compliance, and generates correcting Makefiles accordingly
  56. X      - execute autoconf (a shell script that repeatedly calls the C compiler
  57. X    to determine if certain features/symbols are supported), which will
  58. X    create a file named autoconf.h
  59. X      - create three stripped binaries, a shell script and five man pages in
  60. X    the new/ subdirectory (all that is needed to install):
  61. X    procmail, lockfile, formail, mailstat, procmail.1, lockfile.1,
  62. X    formail.1, procmailrc.5, procmailex.5
  63. X      - copy these binaries and mailstat to $(BINDIR)
  64. X      - copy the man pages to $(MAN1DIR) and $(MAN5DIR)
  65. X
  66. X'make deinstall' will:
  67. X      - remove the just installed files in $(BINDIR)
  68. X      - remove the just installed files in $(MAN1DIR) and $(MAN5DIR)
  69. X
  70. X
  71. XMinimal requirements (for regular uses):
  72. X
  73. Xprocmail must be installed.
  74. X
  75. XOptional files (depending on your requirements):
  76. X
  77. Xlockfile only needs to be installed if you plan to read several mailboxes
  78. X    with one of the standard mailers that don't support lockfiles.
  79. Xformail only needs to be installed if mail sometimes arrives in nonstandard
  80. X    mailbox format (or if you want to generate auto replies, split up
  81. X    mailboxes/digests etc., see the man page of formail for more info).
  82. Xmailstat is an "example" shell script that can be used as is to produce
  83. X    summaries of the procmail generated logfiles; it is not needed by
  84. X    procmail itself in any way.
  85. X
  86. Xprocmail, lockfile, formail and mailstat are all *standalone* programs, i.e.
  87. Xthey do *not* use any compiled-in paths or files, they all can be used and
  88. Xinstalled independently without the need to install the others.
  89. X
  90. XIf things don't compile automagically, I suggest you take a look at:
  91. Xsrc/autoconf, autoconf.h, config.h, src/includes.h
  92. X
  93. XFor autoconf to work as intended, your compiler should either be fully ANSI
  94. Xcompliant, or you should NOT turn off all warnings; enabling all warnings
  95. Xshouldn't hurt.     In most cases the default options in the Makefile will do.
  96. X
  97. XThe sources are supposed to be fully ANSI, K&R and POSIX compliant.
  98. X
  99. XN.B. If you encounter any difficulty at all in installing procmail (e.g. if you
  100. X     had to change Makefile or config.h in unpredicted ways, or a simple
  101. X     "make install" doesn't work), I'd very much like to hear about it; who
  102. X     knows, next time you might be able to simply "make install" as well.
  103. X
  104. X                ---
  105. X
  106. X2. IMPORTANT info for people with remote filesystems (like NFS)
  107. X   ------------------------------------------------------------
  108. X
  109. XThe autoconf script tries to determine what kernel locking functions are
  110. Xavailable *and* reliable on your system.  In order to do this it exercises
  111. Xall the available locking methods (fcntl(), lockf() and flock()) on some
  112. Xsample files extensively.
  113. X
  114. XThese tests produce results which depend on the filesystem which is being
  115. Xused to perform the tests.  If you haven't defined LOCKINGTEST in the Makefile
  116. X(you can include as many directories as you want) autoconf will prompt you
  117. Xto enter any additional directories (preferably on distinct filesystems)
  118. Xyou want it to run the tests on.
  119. X
  120. XWhen specifying directories to test, it would probably be advisable to
  121. Xpick exactly those directories which belong to a unique fileserver-fileclient
  122. Xpair.  I.e. one local file system will suffice.     Only if you have remote
  123. Xfilesystems, you might have to specify several.
  124. XThis makes sure that the locking tests will properly reflect the (lowest common
  125. Xdenominator) locking capabilities on all filesystems available.
  126. X
  127. XIf you have a very heterogenous environment (like several OS versions
  128. Xon machines (perhaps even from different vendors) that have NFS mounted file
  129. Xsystems all over each other), then it could happen that some tests which
  130. Xare reliable with one remote filesystem, turn out to be unreliable across
  131. Xanother (it all depends on the OS versions of clients and servers).
  132. X
  133. XIf do not want to perform the locking tests on all those filesystems, but
  134. Xif you know what locking methods are unreliable anyway, then you can edit
  135. Xsome defines in the config.h file (NO_fcntl_LOCK, NO_lockf_LOCK and
  136. XNO_flock_LOCK).     These can be uncommented by hand to prevent procmail
  137. Xfrom using them.
  138. X
  139. XThe most typical case would be if you happen to be using NFS.  Autoconf
  140. Xnormally is very well capable of finding out if your lockd is reliable enough.
  141. XIn a very heterogenous environment (many different servers, many different
  142. Xlockd's (of perhaps different version and patchlevel)) however, it might
  143. Xbe hard to determine if all the lockd's are equally reliable.  In such a
  144. Xcase (typically on SunOS :-), you might consider uncommenting both
  145. XNO_fcntl_LOCK and NO_lockf_LOCK (NO_flock_LOCK normally doesn't rely on the
  146. Xinfamous lockd, so you can leave it commented out).  But, only do so if you
  147. Xthink you know it better than autoconf.
  148. X
  149. X                ---
  150. X
  151. X3. DEBUGGING AID
  152. X   -------------
  153. X
  154. XSince procmail is intended to run completely independent of any terminals, it
  155. Xdoesn't use the stderr output to display error messages.  It is recommended,
  156. Xespecially during debugging, to specify a LOGFILE (see man page) in the
  157. Xrcfile or on the command line.    Procmail will log all serious problems it
  158. Xencounters.  Of course, instead of a regular file, one could also specify a
  159. Xterminal as the default logfile.
  160. X
  161. XAlso, procmail can be persuaded to be a lot more verbose by inserting the
  162. Xfollowing assignment at the top of your rcfile:
  163. X
  164. X    VERBOSE=on
  165. X
  166. XTherefore a suggested command line for your first trial run (no rcfiles
  167. Xneeded) would be:
  168. X
  169. X    procmail VERBOSE=on
  170. X
  171. X(now type in a pseudo mail-message)
  172. X
  173. XIf all else fails, you can try uncommenting the "#define console" entry
  174. Xin the config.h file.  This will provide you with the most verbose procmail
  175. Xyou can make.  It is of course a good idea to comment out this line again
  176. Xafter your troubles have been solved.
  177. X
  178. XIf you run procmail by hand and pipe in some sample mail, then make
  179. Xsure that if you kill procmail, you use "kill pid" and NOT "kill -9 pid".
  180. XShould procmail seem to hang, check if any lockfiles are still present.
  181. XIf you kill procmail with "kill pid" it will clean up any lockfiles it created
  182. Xitself.
  183. X
  184. X                ---
  185. X
  186. X4. Setting up the environment
  187. X   --------------------------
  188. X
  189. XEvery user that wants to use procmail should have a .forward and a
  190. X.procmailrc file in his HOME directory.     For starters, you can look
  191. Xat the supplied example files in "examples".
  192. X(BTW, be sure to make .forward *world* readable).
  193. XMMDF users should note that they need a .maildelivery file *instead* of the
  194. X.forward file (see the procmail(1) man page for more information).
  195. X
  196. X                ---
  197. X
  198. X5. Extra options if you are a system administrator
  199. X   -----------------------------------------------
  200. X
  201. XIf you are a system administrator you can decide to install procmail
  202. Xglobally (i.e. as a more robust drop-in replacement for the local-
  203. Xmaildelivery-capabilities of /bin/mail), this has the advantage that users do
  204. Xnot need to have a .forward file anymore that calls up procmail.  Simply
  205. Xhaving a .procmailrc file in the HOME directory will suffice.  Operation is
  206. Xtransparent in this case (i.e. if no .procmailrc file is present in the HOME
  207. Xdirectory, mail will be delivered as usual and procmail behaves like a more
  208. Xreliable /bin/mail substitute).
  209. X
  210. XFor direct examples on how to do this, look at the examples/advanced file.
  211. X
  212. X*******************************************************************************
  213. XHIGHLY RECOMMENDED: install "procmail" suid root (and/or sgid maildaemon)
  214. X            install "lockfile" sgid maildaemon
  215. X
  216. XTo obtain specific instructions on the best installation, type "make recommend"
  217. X*******************************************************************************
  218. X
  219. X                ---
  220. X
  221. XFor more info about the program, see the man pages or the FAQ list.
  222. END_OF_FILE
  223. if test 8379 -ne `wc -c <'procmail/INSTALL'`; then
  224.     echo shar: \"'procmail/INSTALL'\" unpacked with wrong size!
  225. fi
  226. # end of 'procmail/INSTALL'
  227. fi
  228. if test -f 'procmail/mailinglist/INSTALL' -a "${1}" != "-c" ; then 
  229.   echo shar: Will not clobber existing file \"'procmail/mailinglist/INSTALL'\"
  230. else
  231. echo shar: Extracting \"'procmail/mailinglist/INSTALL'\" \(6110 characters\)
  232. sed "s/^X//" >'procmail/mailinglist/INSTALL' <<'END_OF_FILE'
  233. XDiscusses:
  234. X        1. Prerequisites
  235. X        2. Installing the scripts
  236. X        3. Sharing the scripts on multiple architectures
  237. X        4. If you don't have a sendmail compatible mailer
  238. X        5. Upgrading from previous versions of these scripts
  239. X
  240. X                ---
  241. X
  242. X1. Prerequisites
  243. X   -------------
  244. X
  245. XIn order to make sure that the mailinglist scripts work reliably for both
  246. Xremote and local mail, they have to be run under someone's account.
  247. XThe recommended procedure would be to create a new account and group named
  248. X"list" that is only going to be used to manage the mailinglist stuff.
  249. X
  250. XIf you are unable/unwilling to create a new user just for the mailinglist
  251. Xstuff, then the mailinglist scripts should be installed in a separate
  252. Xsubdirectory.  This user will still be able to receive regular mail.
  253. X
  254. XIn the mailinglist scripts I made use of the -f option of sendmail.  This
  255. Xoption makes sure that the sender address on the envelope (the From_ line)
  256. Xcontains the proper list address.  In order for this option to work, the
  257. Xuser using it (either "list" or the regular user the lists run under) must
  258. Xbe on the trusted-user-list of sendmail.  To enter the user "list" on the
  259. Xtrusted-user-list simply edit the sendmail.cf file and add a line reading:
  260. X
  261. XTlist
  262. X
  263. XRestarting sendmail is not necessary.
  264. X
  265. X                ---
  266. X
  267. X2. Installing the scripts
  268. X   ----------------------
  269. X
  270. XSuppose you have created this pseudo user "list" with a specified home
  271. Xdirectory of /home/list
  272. X
  273. XNow create /home/list by hand and make sure that you chown it to "list".
  274. X
  275. XNext, make sure that you are running as root (su root) and execute the
  276. X"install.sh" script present in this directory by typing something like:
  277. X
  278. X    sh install.sh /home/list
  279. X
  280. XThis script will then create two subdirectories (.bin and .etc) in
  281. X/home/list.  These directories will be filled with the files contained
  282. Xin the bin and etc subdirectories here.     It will also make sure that
  283. Xthe "multigram" program is compiled from the procmail*/src directory and
  284. Xcopied into /home/list/.bin.
  285. X
  286. XFurthermore install.sh will link /home/list/.etc/rc.main to
  287. X/home/list/.procmailrc.     This is of course superfluous (but nondestructive) if
  288. Xyou are still using this account to receive regular mail.
  289. X
  290. XDepending on your mail configuration, if procmail has not been integrated
  291. Xin the maildelivery system (see procmail*/examples/advanced for more
  292. Xinformation on that topic) you also have to create a .forward file with an
  293. Xappropriate content (see "man procmail", the NOTES section at the end).     This,
  294. Xhowever, is only necessary if you created a seperate "list" account.
  295. X
  296. X    Next, edit the /home/list/.etc/rc.init file.    Make sure that
  297. X    "domain" is set to the right value, and you can optionally specify a
  298. X    "listmaster";  also check if the PATH is correct and make sure
  299. X    that the procmail and formail are in the path.
  300. X
  301. XFor further instructions, you should read the "Manual" file, it has
  302. Xbeen copied to the /home/list/.etc directory as well, and can serve as a
  303. Xquick reference.
  304. X
  305. X                ---
  306. X
  307. X3. Sharing the scripts on multiple architectures
  308. X   ---------------------------------------------
  309. X
  310. XFor people that want to run the lists on a shared filesystem across different
  311. Xarchitectures there exists the possibility of using several .bin directories.
  312. XSimply use something like:
  313. X    sh install.sh /home/list .bin.sun4
  314. Xto install to a different .bin directory.  Repeat the complete procmail and
  315. Xmailinglist installation for every architecture, specifying a different .bin
  316. Xdirectory every time.
  317. X
  318. X                ---
  319. X
  320. X4. If you don't have a sendmail compatible mailer
  321. X   ----------------------------------------------
  322. X
  323. XAs is, these scripts are preconfigured to use sendmail (or a compatible
  324. Xmailer like smail) to actually transport the mails.  If your system only
  325. Xsupplies a /bin/rmail or /bin/mail to transport mails, then several of
  326. Xthe options used when invoking sendmail will not work.
  327. X
  328. XFor these cases you have to edit the /home/list/.etc/rc.init file.
  329. XLook for a SENDMAIL assignment.     Supplied with these scripts is a poor man's
  330. Xsendmail.  It was installed in the .bin directory belonging to the
  331. Xlist.  Make sure that the SENDMAIL assignment points at the sendmails script.
  332. XAnd, of course, don't forget to uncomment the SENDMAIL assignment and
  333. Xthe two sendmailOPT* assigments following it.
  334. X
  335. X                ---
  336. X
  337. X5. Upgrading from previous versions of these scripts
  338. X   -------------------------------------------------
  339. X
  340. XBefore you start the upgrade, create the file /home/list/.etc/rc.lock
  341. XNow do a ps and see if any procmail-list instances are currently
  342. Xrunning.  Wait till they are gone.  Now touch the rc.lock file once more.
  343. XYou know have 17 minutes to complete the upgrade.  If it should take
  344. Xlonger, touch the rc.lock file every so often.    As soon as the difference
  345. Xbetween its mtime and the current time exceeds 17 minutes, the flist
  346. Xprograms start delivering mail to the lists again.
  347. X
  348. XYou can simply use the install.sh script again to install directly over
  349. Xthe old installation IF you customised ONLY the master rc.init and rc.custom
  350. Xfiles.    Once you ran the install.sh script, you'll have to merge the changes
  351. Xyou made to the old rc.init file (still there) into the rc.init.new file.
  352. XThen cat (yes, use `cat', because you have to preserve the hardlinks) the
  353. Xrc.init.new file into the rc.init file.
  354. XThere are some new entries in the new rc.custom file template.    Since they
  355. Xare commented out (i.e. rc.init already provides defaults) their omission
  356. Xin the old rc.custom files should not cause any problems.
  357. X
  358. XIf you customised more than just the rc.init or rc.custom files, you'll
  359. Xhave to make diffs between the old versions of the scripts, then install
  360. Xthe new scripts and then apply back the diffs (probably by hand).
  361. XThe reason why parts of the old scripts cannot operate with the new scripts
  362. Xis because they expect several new environment variables to be set (like
  363. Xdigest selection or not).  The new rc.init sets them of course.
  364. X
  365. XYou can quickly verify which files are linked to other files by
  366. Xsimply typing something like:
  367. X
  368. X    showlink rc.init
  369. X
  370. XAfter you are finished, remove the rc.lock file again.    If it is older
  371. Xthan 17 minutes it is ignored anyway, but it's cleaner this way.
  372. END_OF_FILE
  373. if test 6110 -ne `wc -c <'procmail/mailinglist/INSTALL'`; then
  374.     echo shar: \"'procmail/mailinglist/INSTALL'\" unpacked with wrong size!
  375. fi
  376. # end of 'procmail/mailinglist/INSTALL'
  377. fi
  378. if test -f 'procmail/mailinglist/INTRO' -a "${1}" != "-c" ; then 
  379.   echo shar: Will not clobber existing file \"'procmail/mailinglist/INTRO'\"
  380. else
  381. echo shar: Extracting \"'procmail/mailinglist/INTRO'\" \(9350 characters\)
  382. sed "s/^X//" >'procmail/mailinglist/INTRO' <<'END_OF_FILE'
  383. X$Id: INTRO,v 1.5 1993/01/28 14:21:56 berg Exp $
  384. X
  385. X            How to set up mailing lists
  386. X            ---------------------------
  387. X
  388. X        Written by Stephen R. van den Berg.
  389. X                    berg@pool.informatik.rwth-aachen.de
  390. X                    berg@physik.tu-muenchen.de
  391. X
  392. XThis document mainly describes a sendmail environment, much of it applies
  393. Xto non-sendmail mail agents as well.
  394. X
  395. X
  396. XContents:
  397. X---------    1. Intro
  398. X        2. Bouncing mail
  399. X        3. The disadvantages
  400. X        4. How to circumvent these disadvantages
  401. X        5. Why use procmail to filter the mailinglist mail?
  402. X        6. How do I use procmail to filter the mailinglist mail?
  403. X
  404. X1. Intro
  405. X   -----
  406. X
  407. XThe simplest and most direct way to setup a mailinglist is by inserting a line
  408. Xin the /usr/lib/aliases file looking like:
  409. X
  410. Xmylist: fred,john, wilma, barney@bedrock, pebbles
  411. X
  412. XNow all the mail arriving at your machine for "mylist" (either local or
  413. Xmylist@your.domain) will be automatically forwarded to all the mentioned
  414. Xaddresses (fred, john, etc.).
  415. X
  416. XThe address mylist@your.domain is intended for submissions to the list that
  417. Xare supposed to be forwarded to all the subscribers.  For the administrative
  418. Xtasks like removals from the list, new subscriptions to the list, or address
  419. Xchanges of subscribers, it is common practice to create a second entry in the
  420. X/usr/lib/aliases file:
  421. X
  422. Xmylist-request: your_login_name@your.domain
  423. X
  424. X
  425. X2. Bouncing mail
  426. X   -------------
  427. X
  428. XIn order to deal with bouncing mail gracefully, an extra precaution should
  429. Xbe taken.  If for example mail to wilma bounces (user non-existent, mail
  430. Xfilesystem full, etc.), it will bounce back to the original sender.
  431. XNow, the only person that should be concerned with distribution failures
  432. Xshould be the mylist-request holder.  Therefore you should be using a
  433. Xsendmail special alias like:
  434. X
  435. Xowner-mylist: mylist-request@your.domain
  436. X
  437. XThis way local mail will bounce back to mylist-request@your.domain.
  438. X
  439. X
  440. X3. The disadvantages
  441. X   -----------------
  442. X
  443. XIf you are using the above methods, some obvious disadvantages come to mind
  444. Xhowever:
  445. X
  446. Xa. The subscriber list cannot exceed 1000 bytes (on many sendmails).
  447. Xb. The subscriber list cannot be changed on-the-fly (/usr/lib/aliases needs
  448. X   to be edited, and newaliases has to be run).
  449. Xc. People cannot be prevented from submitting messages like "Please remove
  450. X   me from this mailinglist" to mylist (and thereby annoying all subscribers).
  451. Xd. People cannot be guarded from themselves in case they insert
  452. X   "Return-Receipt-To:" fields in their headers (if they are particularly
  453. X   unlucky, they will receive an acknowledge mail from *every* subscriber's
  454. X   sendmail).
  455. Xe. People including "Errors-To:" or "Sender:" fields can cause the bounce
  456. X   messages to bypass owner-mylist anyway.
  457. Xf. There is no way of limiting the number of submitters, i.e. every person
  458. X   who knows the name of the mailing list and who can send mail to your.domain
  459. X   is able to submit messages to the list.  This means, for example, that you
  460. X   cannot limit a mailing list to local users (i.e. only local users can
  461. X   submit).
  462. Xg. You are unable to insert a "Reply-To: mylist@your.domain" in case you
  463. X   would want to (this makes replying to the list easier, too easy as some
  464. X   people say).
  465. X
  466. X
  467. X4. How to circumvent these disadvantages
  468. X   -------------------------------------
  469. X
  470. Xa. Can be circumvented by using nested aliases like:
  471. X    mylist: mylist1, mylist2
  472. X    mylist1: fred,john
  473. X    mylist2: wilma,barney@bedrock,pebbles
  474. X   This can however, become extremely messy to maintain.
  475. X
  476. Xb. This can be avoided if you use aliases like:
  477. X    mylist: :include:/path/to/the/memberfile
  478. X   The memberfile should contain:
  479. X    fred,john,wilma,barney@bedrock,pebbles
  480. X   This will also take care of the upper limit on aliases expansions and
  481. X   newaliases need not be run again every time you change the file.
  482. X
  483. Xc. Can only be taken care of by using a mailfilter like procmail.
  484. X
  485. Xd. Can only be taken care of by using a mailfilter like procmail.
  486. X
  487. Xe. Can only be taken care of by using a mailfilter like procmail.
  488. X
  489. Xf. Can only be taken care of by using a mailfilter like procmail.
  490. X
  491. Xg. Can only be taken care of by using a mailfilter like procmail.
  492. X
  493. X
  494. X5. Why use procmail to filter the mailinglist mail?
  495. X   ------------------------------------------------
  496. X
  497. XInstead of using a mailfilter you could also take care of most of the problems
  498. Xthree till seven by editing the sendmail.cf file.  I would strongly recommend
  499. Xagainst this approach however, since this will be too much of a customising
  500. Xoperation and surely will not be a trivial task (in all cases).     As a general
  501. Xrule: don't mess with a sendmail.cf file once it works :-).
  502. X
  503. XNow, you could, instead of procmail, simply use immediate VNIX commands
  504. Xlike grep, sed or awk to do the mail filtering.     Again, there are some obvious
  505. Xdisadvantages with this approach:
  506. X
  507. XA. In case any system resources go out (no more file descriptors, no more
  508. X   swap space, process table full, file system full (for temporary files))
  509. X   your awk or shell script will fail generously (i.e. several bad things
  510. X   could happen: mail munged, truncated, lost, hanging awk or sh programs,
  511. X   etc., you get the picture).
  512. X
  513. XB. All mail headers (including From: and Reply-To:) could very well be
  514. X   multi-line headers; it will be very difficult to make it understandable
  515. X   to awk that somehow the header line could continue on the next line
  516. X   (in case you want to remove a header, or do some complicated substitution).
  517. X
  518. XC. Another hairy problem will be determining the end of the header, of course
  519. X   that is solvable, but you have to make some extra precautions in your
  520. X   awk script to ensure that any substitutions/changes will not occur in
  521. X   the body of the message (further degrading performance and increasing the
  522. X   load on your machine).
  523. X
  524. XD. Starting programs directly from within aliases or .forward files can get
  525. X   extremely messy, since the environment the program starts in is
  526. X   potentially hostile.
  527. X
  528. XProcmail does not *directly* allow you to change any headers, but that
  529. Xfeature is not really necessary since you can tell procmail to send ONLY the
  530. Xheader through some filter of your choice.
  531. X
  532. XTo comment on the previously mentioned three disadvantages:
  533. X
  534. XA. Procmail takes care of that.     Should the filter have problems anyway,
  535. X   procmail will graciously notice that the filter was in some kind of
  536. X   trouble, and will try something else with the original unmunged mail
  537. X   (you can specify what it should do of course, obvious choices: try
  538. X   the same filter again, drop the mail in a file and send you a notice,
  539. X   forward the mail to you instead (unfiltered), etc.)
  540. X
  541. XB. In order to make consistent scanning of the header possible using the
  542. X   egrep regular expressions built in to procmail, procmail will internally
  543. X   concatenate any headers that were continued according to the RCF 822
  544. X   recommendations, in order for external filters to benefit from this, you
  545. X   would use the formail program to pre-filter the mail.
  546. X
  547. XC. Procmail can be told to send the header, the body or both through the
  548. X   filter, hence your filter need not watch out to avoid doing any
  549. X   substitutions in the body, and the filter can therefore be a lot simpler.
  550. X
  551. XD. Procmail makes no assumptions about the environment it is started in, it
  552. X   assumes that everything is hostile and fights its way back to the
  553. X   civilised world by initialising *everything* to sane and expected default
  554. X   values.  Thereby providing a warm bed for any program started from within
  555. X   procmail.
  556. X
  557. XBut procmail has some additional advantages as well:
  558. X
  559. X -- It will probably all go a bit faster, since only the header of the mail
  560. X    is being piped through the filter.    Also, procmail reads in the mail in
  561. X    16KB chunks, not line by line as sed does.
  562. X
  563. X -- You could use procmail to filter out any messages to the normal mailing
  564. X    list that should have gone to the mylist-request and remail them to
  565. X    mylist-request.
  566. X
  567. XWell, anyway, as you see, procmail does not give you everything you would want,
  568. Xbut this was intentional in accordance to the true VNIX spirit (modularity).
  569. XWhat procmail does provide is a *very* reliable hook (you might say it
  570. Xprovides an anchor :-) for any mail processing you might do.  For the more
  571. Xcomplex things you still have to use shell scripts or call other programs
  572. Xfrom within procmail, but then again, that saves you from learning any
  573. Xparticular syntax procmail would have had to do the same.
  574. X
  575. XAs it happens, the accompanying formail program is able to cater to most
  576. X(if not all) of your needs regarding mail munging.
  577. X
  578. X
  579. X6. How do I use procmail to filter the mailinglist mail?
  580. X   -----------------------------------------------------
  581. X
  582. XIn order to cater for most wishes regarding mailinglist setup, I took the
  583. Xliberty to write some rcfiles for procmail that can readily be used to create
  584. Xany number of mailinglists in a comfortable and simple way.
  585. X
  586. XSee the FEATURES file in this directory for more information on what
  587. Xthese mailinglist scripts will do for you.
  588. X
  589. XIf the scripts do not exactly do what you would have liked, you are invited to
  590. Xedit them to taste.  Perhaps you could send your changes to the procmail
  591. Xmailinglist if you feel that they could be useful to others.
  592. X
  593. XTo get started I suggest you read the INSTALL file in this directory.
  594. X
  595. XFor operating instructions you should read the Manual file in this directory.
  596. X
  597. X
  598. XP.S. Any suggestions/corrections/improvements on this document are welcome.
  599. END_OF_FILE
  600. if test 9350 -ne `wc -c <'procmail/mailinglist/INTRO'`; then
  601.     echo shar: \"'procmail/mailinglist/INTRO'\" unpacked with wrong size!
  602. fi
  603. # end of 'procmail/mailinglist/INTRO'
  604. fi
  605. if test -f 'procmail/mailinglist/bin/delink' -a "${1}" != "-c" ; then 
  606.   echo shar: Will not clobber existing file \"'procmail/mailinglist/bin/delink'\"
  607. else
  608. echo shar: Extracting \"'procmail/mailinglist/bin/delink'\" \(756 characters\)
  609. sed "s/^X//" >'procmail/mailinglist/bin/delink' <<'END_OF_FILE'
  610. X#! /bin/sh
  611. X: &&O= || exec /bin/sh $0 $argv:q # we're in a csh, feed myself to sh
  612. X#########################################################################
  613. X#    delink        Gracefully disconnects a hardlinked file    #
  614. X#                                    #
  615. X#    Created by S.R. van den Berg, The Netherlands            #
  616. X#########################################################################
  617. X#$Id: delink,v 1.4 1993/06/02 15:30:42 berg Exp $
  618. X
  619. Xecho=echo        # /bin/echo
  620. Xtest=test        # /bin/test
  621. Xrm=rm            # /bin/rm
  622. Xmv=mv            # /bin/mv
  623. Xcp=cp            # /bin/cp
  624. Xdirname=dirname        # /bin/dirname
  625. X
  626. X$test 0 = $# && $echo "Usage: delink filename ..." 1>&2 && exit 64
  627. X
  628. XTMPF=delink.$$
  629. X
  630. Xtrap "$rm -f \$TMPF; exit 1" 1 2 3 15
  631. X
  632. Xfor a in "$@"
  633. Xdo
  634. X  TMPF="`dirname \"$a\"`"/delink.$$
  635. X  $cp -p "$a" "$TMPF" && $mv -f "$TMPF" "$a"
  636. Xdone
  637. END_OF_FILE
  638. if test 756 -ne `wc -c <'procmail/mailinglist/bin/delink'`; then
  639.     echo shar: \"'procmail/mailinglist/bin/delink'\" unpacked with wrong size!
  640. fi
  641. chmod +x 'procmail/mailinglist/bin/delink'
  642. # end of 'procmail/mailinglist/bin/delink'
  643. fi
  644. if test -f 'procmail/src/goodies.c' -a "${1}" != "-c" ; then 
  645.   echo shar: Will not clobber existing file \"'procmail/src/goodies.c'\"
  646. else
  647. echo shar: Extracting \"'procmail/src/goodies.c'\" \(9686 characters\)
  648. sed "s/^X//" >'procmail/src/goodies.c' <<'END_OF_FILE'
  649. X/************************************************************************
  650. X *    Collection of library-worthy routines                *
  651. X *                                    *
  652. X *    Copyright (c) 1990-1992, S.R. van den Berg, The Netherlands    *
  653. X *    #include "README"                        *
  654. X ************************************************************************/
  655. X#ifdef RCS
  656. Xstatic /*const*/char rcsid[]=
  657. X "$Id: goodies.c,v 1.15 1993/06/21 14:24:17 berg Exp $";
  658. X#endif
  659. X#include "procmail.h"
  660. X#include "sublib.h"
  661. X#include "robust.h"
  662. X#include "shell.h"
  663. X#include "misc.h"
  664. X#include "pipes.h"
  665. X#include "common.h"
  666. X#include "cstdio.h"
  667. X#include "goodies.h"
  668. X
  669. Xlong Stdfilled;
  670. X#ifndef GOT_bin_test
  671. Xconst char test[]="test";
  672. X#endif
  673. Xconst char*Tmnate,*All_args;
  674. X
  675. X#define NOTHING_YET    (-1)     /* readparse understands a very complete    */
  676. X#define SKIPPING_SPACE    0     /* subset of the standard /bin/sh syntax    */
  677. X#define NORMAL_TEXT    1     /* that includes single-, double- and back- */
  678. X#define DOUBLE_QUOTED    2     /* quotes, backslashes and $subtitutions    */
  679. X#define SINGLE_QUOTED    3
  680. X
  681. X#define fgetc() (*fpgetc)()       /* some compilers previously choked on it */
  682. X
  683. X/* sarg==0 : normal parsing, split up arguments like in /bin/sh
  684. X * sarg==1 : environment assignment parsing, parse up till first whitespace
  685. X * sarg==2 : normal parsing, split up arguments by single spaces
  686. X */
  687. Xvoid readparse(p,fpgetc,sarg)register char*p;int(*const fpgetc)();
  688. X const int sarg;
  689. X{ static i;int got;char*startb;
  690. X  All_args=0;
  691. X  for(got=NOTHING_YET;;)            /* buf2 is used as scratch space */
  692. Xloop:
  693. X   { i=fgetc();
  694. X     if(buf+linebuf-3<p)        /* doesn't catch everything, just a hint */
  695. X      { nlog("Exceeded LINEBUF\n");p=buf+linebuf-3;goto ready;
  696. X      }
  697. Xnewchar:
  698. X     switch(i)
  699. X      { case EOF:    /* check sarg too to prevent warnings in the recipe- */
  700. X       if(sarg!=2&&got>NORMAL_TEXT)         /* condition expansion code */
  701. Xearly_eof:    nlog(unexpeof);
  702. Xready:       if(got!=SKIPPING_SPACE||sarg)  /* not terminated yet or sarg==2 ? */
  703. X          *p++='\0';
  704. X       Tmnate=p;return;
  705. X    case '\\':
  706. X       if(got==SINGLE_QUOTED)
  707. X          break;
  708. X       switch(i=fgetc())
  709. X        { case EOF:goto early_eof;              /* can't quote EOF */
  710. X          case '\n':continue;            /* concatenate lines */
  711. X          case '#':
  712. X         if(got>SKIPPING_SPACE) /* escaped comment at start of word? */
  713. X            goto noesc;            /* apparently not, literally */
  714. X          case ' ':case '\t':case '\'':
  715. X         if(got==DOUBLE_QUOTED)
  716. X            goto noesc;
  717. X          case '"':case '\\':case '$':case '`':goto nodelim;
  718. X        }
  719. X       if(got>NORMAL_TEXT)
  720. Xnoesc:          *p++='\\';        /* nothing to escape, just echo both */
  721. X       break;
  722. X    case '`':
  723. X       if(got==SINGLE_QUOTED)
  724. X          goto nodelim;
  725. X       for(startb=p;;)                   /* mark your position */
  726. X        { switch(i=fgetc())             /* copy till next backquote */
  727. X           { case '\\':
  728. X            switch(i=fgetc())
  729. X             { case EOF:nlog(unexpeof);goto forcebquote;
  730. X               case '\n':continue;
  731. X               case '"':
  732. X              if(got!=DOUBLE_QUOTED)
  733. X                 break;
  734. X               case '\\':case '$':case '`':goto escaped;
  735. X             }
  736. X            *p++='\\';break;
  737. X         case '"':
  738. X            if(got!=DOUBLE_QUOTED)     /* missing closing backquote? */
  739. X               break;
  740. Xforcebquote:     case EOF:case '`':
  741. X          { int osh=sh;
  742. X            *p='\0';
  743. X            if(!(sh=!!strpbrk(startb,tgetenv(shellmetas))))
  744. X             { const char*save=sgetcp,*sall_args=All_args;
  745. X               sgetcp=p=tstrdup(startb);readparse(startb,sgetc,0);
  746. X               if(!All_args)           /* only one can be remembered */
  747. X              All_args=sall_args;            /* this is a bug */
  748. X#ifndef GOT_bin_test
  749. X               if(!strcmp(test,startb))
  750. X              strcpy(startb,p),sh=1;       /* oops, `test' found */
  751. X#endif
  752. X               free(p);sgetcp=save;               /* chopped up */
  753. X             }            /* drop source buffer, read from program */
  754. X            startb=
  755. X             fromprog(p=startb,startb,(size_t)(buf-startb+linebuf-3));
  756. X            sh=osh;                       /* restore sh */
  757. X            if(got!=DOUBLE_QUOTED)
  758. X             { i=0;startb=p;goto simplsplit;          /* split it up */
  759. X             }
  760. X            if(i=='"'||got<=SKIPPING_SPACE)   /* missing closing ` ? */
  761. X               got=NORMAL_TEXT;                 /* or sarg!=0 ? */
  762. X            p=startb;goto loop;
  763. X          }
  764. X         case '\n':i=';';           /* newlines separate commands */
  765. X           }
  766. Xescaped:      *p++=i;
  767. X        }
  768. X    case '"':
  769. X       switch(got)
  770. X        { case DOUBLE_QUOTED:got=NORMAL_TEXT;continue;    /* closing " */
  771. X          case SINGLE_QUOTED:goto nodelim;
  772. X        }
  773. X       got=DOUBLE_QUOTED;continue;                /* opening " */
  774. X    case '\'':
  775. X       switch(got)
  776. X        { case DOUBLE_QUOTED:goto nodelim;
  777. X          case SINGLE_QUOTED:got=NORMAL_TEXT;continue;}    /* closing ' */
  778. X       got=SINGLE_QUOTED;continue;                /* opening ' */
  779. X    case '#':
  780. X       if(got>SKIPPING_SPACE)        /* comment at start of word? */
  781. X          break;
  782. X       while((i=fgetc())!=EOF&&i!='\n');            /* skip till EOL */
  783. X       goto ready;
  784. X    case '$':
  785. X       if(got==SINGLE_QUOTED)
  786. X          break;
  787. X       startb=buf2;
  788. X       switch(i=fgetc())
  789. X        { case EOF:*p++='$';goto ready;
  790. X          case '@':
  791. X         if(got!=DOUBLE_QUOTED)
  792. X            goto normchar;
  793. X         All_args=p;continue;
  794. X          case '{':                          /* ${name} */
  795. X         while(EOF!=(i=fgetc())&&alphanum(i))
  796. X            *startb++=i;
  797. X         *startb='\0';
  798. X         if(i!='}'||numeric(*buf2)&&buf2[1])
  799. X          { nlog("Bad substitution of");logqnl(buf2);continue;
  800. X          }
  801. X         i='\0';break;                      /* $$ =pid */
  802. X          case '$':ultstr(0,(unsigned long)thepid,p);goto ieofstr;
  803. X          case '?':strcpy(p,"-1");
  804. X         if(lexitcode>=0)  /* $? =exitcode from last started program */
  805. X            ultstr(0,(unsigned long)lexitcode,p);
  806. X         goto ieofstr; /* $# =number of extra command-line arguments */
  807. X          case '#':ultstr(0,(unsigned long)crestarg,p);goto ieofstr;
  808. X          case '-':strcpy(p,tgetenv(lastfolder));
  809. Xieofstr:     i='\0';goto eofstr;               /* $- =lastfolder */
  810. X          default:
  811. X         if(numeric(i))               /* $n positional argument */
  812. X          { *startb++=i;i='\0';goto finsb;
  813. X          }
  814. X         if(alphanum(i))                    /* $name */
  815. X          { do *startb++=i;
  816. X            while(EOF!=(i=fgetc())&&alphanum(i));
  817. X            if(i==EOF)
  818. X            i='\0';
  819. Xfinsb:            *startb='\0';break;
  820. X          }
  821. Xnormchar:     *p++='$';goto newchar;               /* not a substitution */
  822. X        }
  823. X       ;{ int j;
  824. X          startb=(unsigned)(j=(*buf2)-'0')>9?(char*)tgetenv(buf2):
  825. X           !j?(char*)argv0:j<=crestarg?(char*)restargv[j-1]:"";
  826. X        }
  827. X       if(got!=DOUBLE_QUOTED)
  828. Xsimplsplit:   for(;;startb++)          /* simply split it up in arguments */
  829. X           { switch(*startb)
  830. X          { case ' ':case '\t':case '\n':
  831. X               if(got<=SKIPPING_SPACE)
  832. X              continue;
  833. X               *p++=sarg?' ':'\0';got=SKIPPING_SPACE;continue;
  834. X            case '\0':goto eeofstr;
  835. X          }
  836. X         *p++= *startb;got=NORMAL_TEXT;
  837. X           }
  838. X       else
  839. X        { strcpy(p,startb);                   /* simply copy it */
  840. Xeofstr:          if(got<=SKIPPING_SPACE)        /* can only occur if sarg!=0 */
  841. X         got=NORMAL_TEXT;
  842. X          p=strchr(p,'\0');
  843. X        }
  844. Xeeofstr:   if(i)                 /* already read next character? */
  845. X          goto newchar;
  846. X       continue;
  847. X    case ' ':case '\t':
  848. X       switch(got)
  849. X        { case NORMAL_TEXT:
  850. X         if(sarg==1)
  851. X            goto ready;        /* already fetched a single argument */
  852. X         got=SKIPPING_SPACE;*p++=sarg?' ':'\0';     /* space or \0 sep. */
  853. X          case NOTHING_YET:case SKIPPING_SPACE:continue;   /* skip space */
  854. X        }
  855. X    case '\n':
  856. X       if(got<=NORMAL_TEXT)
  857. X          goto ready;                /* EOL means we're ready */
  858. X      }
  859. Xnodelim:
  860. X     *p++=i;                       /* ah, a normal character */
  861. X     if(got<=SKIPPING_SPACE)         /* should we bother to change mode? */
  862. X    got=NORMAL_TEXT;
  863. X   }
  864. X}
  865. X
  866. Xwaitfor(pid)const pid_t pid;              /* wait for a specific process */
  867. X{ int i;pid_t j;
  868. X  while(pid!=(j=wait(&i))||WIFSTOPPED(i))
  869. X     if(-1==j)
  870. X    return -1;
  871. X  return lexitcode=WIFEXITED(i)?WEXITSTATUS(i):-1;
  872. X}
  873. X
  874. Xstatic struct lienv{struct lienv*enext;char ename[255];}*myenv;
  875. Xstatic char**lastenv;
  876. X                  /* smart putenv, the way it was supposed to be */
  877. Xvoid sputenv(a)const char*const a;
  878. X{ static alloced;int i,remove;char*split,**preenv;struct lienv*curr,**last;
  879. X  yell("Assigning",a);remove=0;
  880. X  if(!(split=strchr(a,'=')))               /* assignment or removal? */
  881. X     remove=1,split=strchr(a,'\0');
  882. X  i=split-a;
  883. X  for(curr= *(last= &myenv);curr;curr= *(last= &curr->enext))    /* is it one */
  884. X     if(!strncmp(a,curr->ename,i)&&curr->ename[i]=='=')      /* I made earlier? */
  885. X      { split=curr->ename;*last=curr->enext;free(curr);
  886. X    for(preenv=environ;*preenv!=split;preenv++);
  887. X    goto wipenv;
  888. X      }
  889. X  for(preenv=environ;*preenv;preenv++)            /* is it in the standard */
  890. X     if(!strncmp(a,*preenv,i)&&(*preenv)[i]=='=')         /* environment? */
  891. Xwipenv:
  892. X      { while(*preenv=preenv[1])   /* wipe this entry out of the environment */
  893. X       preenv++;
  894. X    break;
  895. X      }
  896. X  i=(preenv-environ+2)*sizeof*environ;
  897. X  if(alloced)           /* have we ever alloced the environ array before? */
  898. X     environ=realloc(environ,i);
  899. X  else
  900. X     alloced=1,environ=tmemmove(malloc(i),environ,i-sizeof*environ);
  901. X  if(!remove)          /* if not remove, then add it to both environments */
  902. X   { for(preenv=environ;*preenv;preenv++);
  903. X     curr=malloc(ioffsetof(struct lienv,ename[0])+(i=strlen(a)+1));
  904. X     tmemmove(*(lastenv=preenv)=curr->ename,a,i);preenv[1]=0;curr->enext=myenv;
  905. X     myenv=curr;
  906. X   }
  907. X}
  908. X                /* between calling primeStdout() and retStdout() */
  909. Xvoid primeStdout P((void))        /* *no* environment changes are allowed! */
  910. X{ char*p;
  911. X  if((p=strchr(buf,'\0'))[-1]!='=')           /* does it end in an '='? */
  912. X     *p='=',p[1]='\0';                    /* make sure it does */
  913. X  sputenv(buf);Stdout=(char*)myenv;
  914. X  Stdfilled=ioffsetof(struct lienv,ename[0])+strlen(myenv->ename);
  915. X}
  916. X
  917. Xvoid retStdout(newmyenv)char*const newmyenv;    /* see note on primeStdout() */
  918. X{ if(newmyenv[Stdfilled-1]=='\n')           /* strip one trailing newline */
  919. X     Stdfilled--;
  920. X  newmyenv[Stdfilled]='\0';*lastenv=(myenv=(struct lienv*)newmyenv)->ename;
  921. X  Stdout=0;
  922. X}
  923. X
  924. Xvoid postStdout P((void))         /* throw it into the keyword parser */
  925. X{ const char*p;size_t i;
  926. X  p= *lastenv;tmemmove(buf,p,i=strchr(p,'=')-p);buf[i]='\0';asenv(p+i+1);
  927. X}
  928. END_OF_FILE
  929. if test 9686 -ne `wc -c <'procmail/src/goodies.c'`; then
  930.     echo shar: \"'procmail/src/goodies.c'\" unpacked with wrong size!
  931. fi
  932. # end of 'procmail/src/goodies.c'
  933. fi
  934. if test -f 'procmail/src/lockfile.c' -a "${1}" != "-c" ; then 
  935.   echo shar: Will not clobber existing file \"'procmail/src/lockfile.c'\"
  936. else
  937. echo shar: Extracting \"'procmail/src/lockfile.c'\" \(9418 characters\)
  938. sed "s/^X//" >'procmail/src/lockfile.c' <<'END_OF_FILE'
  939. X/************************************************************************
  940. X *    lockfile - The conditional semaphore-file creator        *
  941. X *                                    *
  942. X *    It has been designed to be able to be run sgid mail or        *
  943. X *    any gid you see fit (in case your mail spool area is *not*    *
  944. X *    world writeable, but group writeable), without creating        *
  945. X *    security holes.                            *
  946. X *                                    *
  947. X *    Seems to be relatively bug free.                *
  948. X *                                    *
  949. X *    Copyright (c) 1990-1992, S.R. van den Berg, The Netherlands    *
  950. X *    #include "README"                        *
  951. X ************************************************************************/
  952. X#ifdef RCS
  953. Xstatic /*const*/char rcsid[]=
  954. X "$Id: lockfile.c,v 1.15 1993/06/21 14:24:28 berg Exp $";
  955. X#endif
  956. Xstatic /*const*/char rcsdate[]="$Date: 1993/06/21 14:24:28 $";
  957. X#include "includes.h"
  958. X#include "sublib.h"
  959. X#include "exopen.h"
  960. X
  961. X#ifndef SYSTEM_MBOX
  962. X#define SYSTEM_MBOX    SYSTEM_MAILBOX
  963. X#endif
  964. X
  965. Xstatic volatile exitflag;
  966. Xpid_t thepid;
  967. Xstatic char systm_mbox[]=SYSTEM_MBOX;
  968. Xstatic const char dirsep[]=DIRSEP,lockext[]=DEFlockext,
  969. X nameprefix[]="lockfile: ",lgname[]="LOGNAME",home[]="HOME";
  970. X
  971. Xstatic void failure P((void))                      /* signal trap */
  972. X{ exitflag=2;                           /* merely sets a flag */
  973. X}
  974. X                    /* see locking.c for comment on xcreat() */
  975. Xstatic xcreat(name,tim)const char*const name;time_t*const tim;
  976. X{ char*p,*q;int j= -1,i;struct stat stbuf;
  977. X  for(q=(char*)name;p=strpbrk(q,dirsep);q=p+1);
  978. X  i=q-name;
  979. X  if(!(p=malloc(i+UNIQnamelen)))
  980. X     return exitflag=1;
  981. X  strncpy(p,name,i);
  982. X  if(unique(p,p+i,0,0))
  983. X     stat(p,&stbuf),*tim=stbuf.st_mtime,j=myrename(p,name);
  984. X  free(p);return j;
  985. X}
  986. X
  987. Xvoid elog(a)const char*const a;
  988. X{ write(STDERR,a,strlen(a));
  989. X}
  990. X
  991. Xvoid nlog(a)const char*const a;
  992. X{ elog(nameprefix);elog(a);  /* decent error messages should start with this */
  993. X}
  994. X
  995. Xstatic size_t parsecopy(dest,org,pass)char*const dest;const char*org;
  996. X const struct passwd*const pass; /* try and digest the mailbox-lockfile name */
  997. X{ size_t len;const char*chp;char*p;unsigned i;
  998. X  for(p=dest,len=STRLEN(lockext)+1;;)
  999. X   { switch(*org)
  1000. X      { case '$':                        /* we substitute */
  1001. X       if(!strncmp(++org,lgname,STRLEN(lgname)))
  1002. X          org+=STRLEN(lgname),chp=pass->pw_name;         /* $LOGNAME and */
  1003. X       else if(!strncmp(org,home,STRLEN(home)))
  1004. X          org+=STRLEN(home),chp=pass->pw_dir;            /* $HOME */
  1005. X       else
  1006. X          goto capac;                 /* no other fancy stuff */
  1007. X       if((i= *org)-'a'<='z'-'a'||i-'A'<='Z'-'A'||numeric(i)||i=='_')
  1008. X          goto capac;
  1009. X       if(p)
  1010. X          p+=strlen(strcpy(p,chp));                  /* paste it in */
  1011. X       len+=strlen(chp);continue;
  1012. X    default:
  1013. X       if(p)
  1014. X          *p++= *org;              /* simply copy everything else */
  1015. X       len++;org++;continue;      /* except suspicous looking characters */
  1016. X    case '\'':case '`':case '"':case '\\':case '{':goto capac;
  1017. X    case '\0':;
  1018. X      }
  1019. X     if(p)
  1020. X      { if(p==dest||!strchr(dirsep,*dest))         /* absolute path wanted */
  1021. Xcapac:     { nlog("Sorry, but turning this mess into a useable mailbox \
  1022. Xexceeds my humble\ncapacities");return 0;
  1023. X     }
  1024. X    strcpy(p,lockext);
  1025. X      }
  1026. X     return len;
  1027. X   }
  1028. X}
  1029. X
  1030. Xstatic PROGID;
  1031. X
  1032. Xmain(argc,argv)const char*const argv[];
  1033. X{ const char*const*p,*const*lastf;char*cp;uid_t uid;
  1034. X  int sleepsec,retries,invert,force,suspend,retval=EX_OK,virgin=1;
  1035. X  static const char usage[]="Usage: lockfile -nnn | -r nnn | -l nnn | -s nnn \
  1036. X| -! | -ml | -mu | file ...\n";
  1037. X  if(argc<=1)                   /* sanity check, any argument at all? */
  1038. X     goto usg;
  1039. X  sleepsec=DEFlocksleep;force=invert=(char*)progid-(char*)progid;retries= -1;
  1040. X  suspend=DEFsuspend;thepid=getpid();uid=getuid();signal(SIGPIPE,SIG_IGN);
  1041. Xagain:
  1042. X  signal(SIGHUP,(void(*)())failure);signal(SIGINT,(void(*)())failure);
  1043. X  signal(SIGQUIT,(void(*)())failure);signal(SIGTERM,(void(*)())failure);
  1044. X  for(lastf=p=argv;--argc;)
  1045. X     if(*(cp=(char*)*++p)=='-')
  1046. X    for(cp++;;)
  1047. X     { char*cp2=cp;int i;
  1048. X       switch(*cp++)
  1049. X        { case '!':invert^=1;continue;          /* invert the exitcode */
  1050. X          case 'r':case 'l':case 's':
  1051. X         if(!*cp&&(cp=(char*)*++p,!--argc)) /* concatenated/seperate */
  1052. X            goto eusg;
  1053. X         i=strtol(cp,&cp,10);
  1054. X         switch(*cp2)
  1055. X          { case 'r':retries=i;goto checkrdec;
  1056. X            case 'l':force=i;goto checkrdec;
  1057. X            default:
  1058. X               if(i<0)                /* suspend should be >=0 */
  1059. X              goto eusg;
  1060. X               suspend=i;goto checkrdec;
  1061. X          }
  1062. X          case HELPOPT1:case HELPOPT2:elog(usage);
  1063. X         elog(
  1064. X "\t-nnn\twait nnn seconds between locking attempts\
  1065. X\n\t-r nnn\tmake at most nnn retries before giving up on a lock\
  1066. X\n\t-l nnn\tset locktimeout to nnn seconds\
  1067. X\n\t-s nnn\tsuspend nnn seconds after a locktimeout occurred\
  1068. X\n\t-!\tinvert the exit code of lockfile\
  1069. X\n\t-ml\tlock your system mail-spool file\
  1070. X\n\t-mu\tunlock your system mail-spool file\n");goto xusg;
  1071. X          default:
  1072. X         if(sleepsec>=0)        /* is this still the first pass? */
  1073. X          { if((sleepsec=strtol(cp2,&cp,10))<0)
  1074. X               goto eusg;
  1075. Xcheckrdec:        if(cp2==cp)
  1076. Xeusg:             { elog(usage);            /* regular usage message */
  1077. Xxusg:               retval=EX_USAGE;goto nfailure;
  1078. X             }
  1079. X          }
  1080. X         else              /* no second pass, so leave sleepsec<0 */
  1081. X            strtol(cp2,&cp,10);           /* and discard the number */
  1082. X         continue;
  1083. X          case 'm':          /* take $LOGNAME as a hint, check if valid */
  1084. X           { struct passwd*pass;static char*ma;size_t alen;
  1085. X         if(*cp&&cp[1]||ma&&sleepsec>=0)         /* second pass? */
  1086. X            goto eusg;
  1087. X         if(!ma)            /* ma initialised last time? */
  1088. X          { if(!((ma=(char*)getenv(lgname))&&(pass=getpwnam(ma))&&
  1089. X             pass->pw_uid==uid||(pass=getpwuid(uid))))
  1090. X             { nlog("Can't determine your mailbox, who are you?\n");
  1091. X               goto nfailure;     /* panic, you're not in /etc/passwd */
  1092. X             }
  1093. X            if(!(alen=parsecopy((char*)0,systm_mbox,pass)))
  1094. X             { cp=systm_mbox;goto lfailure;      /* couldn't digest */
  1095. X             }                          /* mailbox */
  1096. X            if(!(ma=malloc(alen)))           /* ok, make some room */
  1097. X               goto outofmem;
  1098. X            parsecopy(ma,systm_mbox,pass);      /* and fill her up */
  1099. X          }
  1100. X         switch(*cp)
  1101. X          { default:goto eusg;            /* somebody goofed again */
  1102. X            case 'l':                 /* lock the mailbox */
  1103. X               if(sleepsec>=0)                  /* first pass? */
  1104. X            { cp=ma;goto stilv;            /* yes, lock it! */
  1105. X            }
  1106. X            case 'u':                   /* unlock the mailbox */
  1107. X               if(unlink(ma))
  1108. X            { nlog("Can't unlock \"");elog(ma);elog("\"");
  1109. X              if(*cp=='l')     /* they messed up, give them a hint */
  1110. X                 elog(" again,\n already dropped my privileges");
  1111. X              elog("\n");
  1112. X            }
  1113. X               else
  1114. X              virgin=0;
  1115. X          }
  1116. X           }
  1117. X          case '\0':;
  1118. X        }
  1119. X       break;
  1120. X     }
  1121. X     else if(sleepsec<0)      /* second pass, release everything we acquired */
  1122. X    unlink(cp);
  1123. X     else
  1124. X      { time_t t;int permanent;
  1125. X    setgid(getgid());              /* just to be on the safe side */
  1126. Xstilv:    virgin=0;permanent=nfsTRY;
  1127. X    while(0>xcreat(cp,&t))                     /* try and lock */
  1128. X     { struct stat stbuf;
  1129. X       if(exitflag)                        /* time to stop? */
  1130. X        { if(exitflag==1)             /* was it failure() or malloc() */
  1131. Xoutofmem:     retval=EX_OSERR,nlog("Out of memory");
  1132. X          else
  1133. X         retval=EX_TEMPFAIL,nlog("Signal received");
  1134. X          goto lfailure;
  1135. X        }
  1136. X       switch(errno)            /* why did the lock not succeed? */
  1137. X        { case EEXIST:              /* hmmm..., by force then? */
  1138. X         if(force&&!lstat(cp,&stbuf)&&force<t-stbuf.st_mtime)
  1139. X          { nlog(unlink(cp)?"Forced unlock denied on \"":
  1140. X             "Forcing lock on \"");
  1141. X            elog(cp);elog("\"\n");sleep(suspend);    /* important */
  1142. X          }
  1143. X         else                       /* no forcing now */
  1144. X          case ENOSPC:
  1145. X#ifdef EDQUOT
  1146. X          case EDQUOT:
  1147. X#endif
  1148. X            switch(retries)    /* await your turn like everyone else */
  1149. X             { case 0:nlog("Sorry");retval=EX_CANTCREAT;
  1150. X              goto lfailure;      /* patience exhausted, give up */
  1151. X               default:retries--;              /* count sheep */
  1152. X               case -1:sleep(sleepsec);             /* wait and see */
  1153. X             }
  1154. X         break;
  1155. X          case ENOENT:case ENOTDIR:case EIO:case EACCES:
  1156. X         if(!--permanent)     /* NFS sporadically generates these */
  1157. X          { sleep(sleepsec);continue;              /* unwarranted */
  1158. X          }                     /* so ignore them first */
  1159. X          default:             /* but, it seems to persist, so give up */
  1160. X         nlog("Try praying");retval=EX_UNAVAILABLE;
  1161. X#ifdef ENAMETOOLONG
  1162. X         goto lfailure;
  1163. X          case ENAMETOOLONG:
  1164. X         if(0<(permanent=strlen(cp)-1)&&      /* can we truncate it? */
  1165. X          !strchr(dirsep,cp[permanent-1]))
  1166. X          { nlog("Truncating \"");elog(cp);          /* then try it */
  1167. X            elog("\" and retrying lock\n");cp[permanent]='\0';break;
  1168. X          }                     /* otherwise, forget it */
  1169. X         nlog("Filename too long");retval=EX_UNAVAILABLE;
  1170. X#endif
  1171. Xlfailure:     elog(", giving up on \"");elog(cp);elog("\"\n");
  1172. Xnfailure:     sleepsec= -1;argc=lastf-argv+1;goto again; /* mark sleepsec */
  1173. X        }  /* for second pass, and adjust argc to the no. of args parsed */
  1174. X       permanent=nfsTRY;           /* refresh the NFS-error-ignore count */
  1175. X     }
  1176. X    lastf=p;                      /* last valid file */
  1177. X      }
  1178. X  if(retval==EX_OK&&virgin)         /* any errors?     did we do anything? */
  1179. Xusg:
  1180. X   { elog(usage);return EX_USAGE;
  1181. X   }
  1182. X  if(invert)
  1183. X     switch(retval)             /* we only invert the regular cases */
  1184. X      { case EX_OK:return EX_CANTCREAT;
  1185. X    case EX_CANTCREAT:return EX_OK;
  1186. X      }
  1187. X  return retval;                   /* all other exitcodes remain */
  1188. X}
  1189. X
  1190. Xvoid*tmalloc(len)const size_t len;                     /* stub */
  1191. X{ return malloc(len);
  1192. X}
  1193. X
  1194. Xropen(name,mode,mask)const char*const name;const int mode;const mode_t mask;
  1195. X{ return open(name,mode,mask);                         /* stub */
  1196. X}
  1197. X
  1198. Xrclose(fd)const int fd;                             /* stub */
  1199. X{ return close(fd);
  1200. X}
  1201. X
  1202. Xvoid writeerr(a)const char*const a;                     /* stub */
  1203. X{
  1204. X}
  1205. END_OF_FILE
  1206. if test 9418 -ne `wc -c <'procmail/src/lockfile.c'`; then
  1207.     echo shar: \"'procmail/src/lockfile.c'\" unpacked with wrong size!
  1208. fi
  1209. # end of 'procmail/src/lockfile.c'
  1210. fi
  1211. echo shar: End of archive 6 \(of 11\).
  1212. cp /dev/null ark6isdone
  1213. MISSING=""
  1214. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  1215.     if test ! -f ark${I}isdone ; then
  1216.     MISSING="${MISSING} ${I}"
  1217.     fi
  1218. done
  1219. if test "${MISSING}" = "" ; then
  1220.     echo You have unpacked all 11 archives.
  1221.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1222. else
  1223.     echo You still need to unpack the following archives:
  1224.     echo "        " ${MISSING}
  1225. fi
  1226. ##  End of shell archive.
  1227. exit 0
  1228. -- 
  1229. Sincerely,                                  berg@pool.informatik.rwth-aachen.de
  1230.            Stephen R. van den Berg (AKA BuGless).    berg@physik.tu-muenchen.de
  1231.  
  1232. "Always look on the bright side of life!"
  1233.  
  1234. exit 0 # Just in case...
  1235.