home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume16 / procmail / part01 next >
Encoding:
Internet Message Format  |  1991-02-15  |  53.9 KB

  1. From: berg@marvin.e17.physik.tu-muenchen.de (Stephen R. van den Berg)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i103:  procmail - mail processing package, Part01/01
  4. Message-ID: <1991Feb15.204604.11417@sparky.IMD.Sterling.COM>
  5. Date: 15 Feb 91 20:46:04 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 88b9049f 80f979f6 529d317b a1748a93
  8.  
  9. Submitted-by: Stephen R. van den Berg <berg@marvin.e17.physik.tu-muenchen.de>
  10. Posting-number: Volume 16, Issue 103
  11. Archive-name: procmail/part01
  12.  
  13. The Procmail mail processing package. (v1.10 1991-02-13)
  14.  
  15. Can be used to create mail-servers, mailing lists, sort your incoming mail
  16. (real convenient when subscribing to one or more mailing lists),
  17. preprocess your mail, or selectively forward certain incoming mail
  18. automatically to someone, etc...
  19.  
  20. Procmail was designed to deliver the mail under the worst conditions
  21. (file system full, process table full, missing support files,
  22. unavailable executables; it all doesn't matter).
  23. Should (in the unlikely event) procmail be unable to deliver your mail
  24. somewhere, the mail will bounce back to the sender.
  25.  
  26. Advantages: This package is small (boils down to one executable)
  27.             and therefore robust, but still doesn't lack any mayor
  28.             features you would want.
  29.  
  30. Cheers,
  31.        Stephen R. van den Berg  at RWTH-Aachen, Germany.
  32.  
  33. ---- Cut Here and feed the following to sh ----
  34. #!/bin/sh
  35. # This is Procmail, a shell archive (produced by shar 3.49)
  36. # To extract the files from this archive, save it to a file, remove
  37. # everything above the "!/bin/sh" line above, and type "sh file_name".
  38. #
  39. # made 02/13/1991 15:33 UTC by berg@marvin.e17.physik.tu-muenchen.de
  40. #
  41. # existing files will NOT be overwritten unless -c is specified
  42. #
  43. # This shar contains:
  44. # length  mode       name
  45. # ------ ---------- ------------------------------------------
  46. #   1086 -rw-r--r-- HISTORY
  47. #    814 -rw-r--r-- Makefile
  48. #    698 -rw-r--r-- Manifest
  49. #   3105 -rw-r--r-- README
  50. #     29 -rw-r--r-- forward
  51. #   1974 -rw-r--r-- lockfile.1
  52. #   2071 -rw-r--r-- lockfile.c
  53. #  12759 -rw-r--r-- procmail.1
  54. #  22067 -rw-r--r-- procmail.c
  55. #    310 -rw-r--r-- procmailrc
  56. #    364 -rw-r--r-- rmail
  57. #   1015 -rw-r--r-- sysexits.h
  58. #
  59. # ============= HISTORY ==============
  60. if test -f 'HISTORY' -a X"$1" != X"-c"; then
  61.     echo 'x - skipping HISTORY (File already exists)'
  62. else
  63. echo 'x - extracting HISTORY (Text)'
  64. sed 's/^X//' << 'SHAR_EOF' > 'HISTORY' &&
  65. X1990-12-07: v1.00
  66. X            First release (after 2 weeks of coding and testing)
  67. X1990-12-12: v1.01
  68. X            Added fsync to procmail.c
  69. X            Removed longjmp in lockfile.c out of the signal handler
  70. X                (not portable, so I'm told)
  71. X1991-02-04: v1.02
  72. X            Changes to procmail.c:
  73. X               Added physical-write-error check
  74. X               Altered egrep invocation (left out the -s flag, not supported
  75. X                  on all machines; this didn't change functionality though)
  76. X               Avoided the 'dirty' allocation of one more byte than needed by
  77. X                  rewriting the bogus_header_replace routine
  78. X               Made the finding bogus headers more robust
  79. X            Added sysV lines in Makefile
  80. X1991-02-13: v1.10
  81. X            Changes to procmail.c:
  82. X               Fixed slight error in parsing the recipe when 'h' and 'b' where
  83. X                  specified
  84. X               Started using the official exit codes
  85. X               Made sure that the procmail is not influenced by falsely
  86. X                  set environment variables like LOCKSLEEP
  87. SHAR_EOF
  88. chmod 0644 HISTORY ||
  89. echo 'restore of HISTORY failed'
  90. Wc_c="`wc -c < 'HISTORY'`"
  91. test 1086 -eq "$Wc_c" ||
  92.     echo 'HISTORY: original size 1086, current size' "$Wc_c"
  93. fi
  94. # ============= Makefile ==============
  95. if test -f 'Makefile' -a X"$1" != X"-c"; then
  96.     echo 'x - skipping Makefile (File already exists)'
  97. else
  98. echo 'x - extracting Makefile (Text)'
  99. sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
  100. XBASENAME = /global              # change to your home directory if need be
  101. XBINDIR   = ${BASENAME}/bin
  102. XMANDIR   = ${BASENAME}/man/man1
  103. X
  104. XOCFLAGS  = -O
  105. XOLDFLAGS = -s
  106. X
  107. X# Uncomment appropiately (for sysV and the like):
  108. XCFLAGS  = ${OCFLAGS} #-DSYSV -DNOfsync -DNO_ANSI_PROT -Dvoid=char
  109. XLDFLAGS = ${OLDFLAGS} #-lbsd 
  110. X
  111. XCC = cc
  112. XINSTALL= install -m 755
  113. XRM= rm -f
  114. X
  115. Xall:    procmail lockfile
  116. X
  117. Xprocmail: procmail.o
  118. X    ${CC} ${CFLAGS} -o procmail procmail.o ${LDFLAGS}
  119. X
  120. Xprocmail.o: procmail.c
  121. X    ${CC} ${CFLAGS} -c procmail.c
  122. X
  123. Xlockfile: lockfile.o
  124. X    ${CC} ${CFLAGS} -o lockfile lockfile.o ${LDFLAGS}
  125. X
  126. Xlockfile.o: lockfile.c
  127. X    ${CC} ${CFLAGS} -c lockfile.c
  128. X
  129. Xinstall: all
  130. X    ${INSTALL} procmail lockfile ${BINDIR}
  131. X    chmod 644 procmail.1 lockfile.1
  132. X    cp procmail.1 lockfile.1 ${MANDIR}
  133. X
  134. Xclean:
  135. X    ${RM} procmail.o lockfile.o procmail lockfile
  136. SHAR_EOF
  137. chmod 0644 Makefile ||
  138. echo 'restore of Makefile failed'
  139. Wc_c="`wc -c < 'Makefile'`"
  140. test 814 -eq "$Wc_c" ||
  141.     echo 'Makefile: original size 814, current size' "$Wc_c"
  142. fi
  143. # ============= Manifest ==============
  144. if test -f 'Manifest' -a X"$1" != X"-c"; then
  145.     echo 'x - skipping Manifest (File already exists)'
  146. else
  147. echo 'x - extracting Manifest (Text)'
  148. sed 's/^X//' << 'SHAR_EOF' > 'Manifest' &&
  149. XMakefile        We all know what that is.
  150. XREADME          Important, read it.
  151. XHISTORY         Recent and ancient changes (or bugs) documented.
  152. Xlockfile.1      Man page for lockfile.
  153. Xlockfile.c      You guessed it.
  154. XManifest        Right again.
  155. Xprocmail.1      Yes, the man page for procmail.
  156. Xprocmail.c      Yes, exactly.
  157. Xsysexits.h      Substitute for the machines that don't have it (is it ever
  158. X                needed?)
  159. Xprocmailrc      A sample .procmailrc file
  160. Xrmail           A sample shell script that demonstrates how to use
  161. X                lockfiles while reading the mail (to ensure mail integrity
  162. X                as soon as you exit the mail program)
  163. Xforward         A sample .forward file
  164. SHAR_EOF
  165. chmod 0644 Manifest ||
  166. echo 'restore of Manifest failed'
  167. Wc_c="`wc -c < 'Manifest'`"
  168. test 698 -eq "$Wc_c" ||
  169.     echo 'Manifest: original size 698, current size' "$Wc_c"
  170. fi
  171. # ============= README ==============
  172. if test -f 'README' -a X"$1" != X"-c"; then
  173.     echo 'x - skipping README (File already exists)'
  174. else
  175. echo 'x - extracting README (Text)'
  176. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  177. XSome legal stuff:
  178. X
  179. XUse this software package at your own risk.  The programmer can not
  180. Xbe held liable for any incurred damages due to the use of this software.
  181. X
  182. XYou are encouraged to distribute this package freely.  This package is
  183. Xhowever not to be not sold (minor transfer costs excepted) or included in
  184. Xany commercially sold software package (if you want to do this anyway,
  185. Xcontact me (address below), and we'll work something out).
  186. X
  187. XIf you distribute it, please leave the package in tact.  If you have some
  188. Ximportant changes that might be usefull to the rest of the world, contact
  189. Xme instead.
  190. X
  191. X----------------------
  192. X
  193. XThe Procmail mail processing package. (v1.10 1991-02-13)
  194. X
  195. XCan be used to create mail-servers, mailing lists, sort your incoming mail
  196. X(real convenient when subscribing to one or more mailing lists),
  197. Xpreprocess your mail, or selectively forward certain incoming mail
  198. Xautomatically to someone.
  199. X
  200. XTo install it, edit the Makefile accordingly (if it doesn't compile at first,
  201. Xcheck if some extra header files should be included (or left out) in order
  202. Xto make any used types/defines/declarations for the library compatible).
  203. X
  204. XBTW, the warnings you get about 'loop not entered at top': they're normal :-).
  205. XSome older compilers could complain about ambiguous assignments, if they
  206. Xassume normal assigns, you're safe.
  207. X
  208. XIf you run procmail by hand and pipe in some sample mail, then make
  209. Xsure that if you kill procmail, you use "kill pid" and NOT "kill -9 pid".
  210. XShould procmail seem to hang, check if the $LOCKFILE is still present.
  211. XIf you kill procmail with "kill pid" it will clean up the $LOCKFILE
  212. Xitself.
  213. X
  214. XIf you really want to, you can change some of the defines at the start
  215. Xof procmail.c to suit your needs.  They should be sufficient for most
  216. Xpeople though.
  217. X
  218. XEvery user that wants to use procmail should have a .forward and a
  219. X.procmailrc file in his HOME directory.  For starters, you can look
  220. Xat the supplied example "forward" and "procmailrc" files.
  221. X(BTW, be sure to make .forward *world* readable).
  222. X
  223. XFor more info about the program, see the man page.
  224. X
  225. X----------------------
  226. X
  227. XAlthough I can't guarantee that the procmail (or lockfile) program
  228. Xwill perform as required, I must say that I made the utmost effort
  229. Xto make procmail as robust as any program can be.
  230. X
  231. XProcmail was designed to deliver the mail under the worst conditions
  232. X(file system full, process table full, missing support files,
  233. Xunavailable executables; it all doesn't matter).
  234. XShould (in the unlikely event) procmail be unable to deliver your mail
  235. Xsomewhere, the mail will bounce back to the sender.
  236. X
  237. XHowever, as with any program, bugs can not be completely ruled out.
  238. XI tested the program extensively, and believe it should be relatively
  239. Xbug free (no known bug at the time).  Should, however, anyone
  240. Xfind any bugs (highly unlikely :-), I would be pleased (well, sort of :-)
  241. Xto hear about it.  Please send me the patches or bug report.
  242. XI'll look at them and will try to fix it in a future release.
  243. X
  244. XCheers,
  245. X       Stephen R. van den Berg  at RWTH-Aachen, Germany.
  246. X
  247. XInternet E-mail: berg@marvin.e17.physik.tu-muenchen.de
  248. SHAR_EOF
  249. chmod 0644 README ||
  250. echo 'restore of README failed'
  251. Wc_c="`wc -c < 'README'`"
  252. test 3105 -eq "$Wc_c" ||
  253.     echo 'README: original size 3105, current size' "$Wc_c"
  254. fi
  255. # ============= forward ==============
  256. if test -f 'forward' -a X"$1" != X"-c"; then
  257.     echo 'x - skipping forward (File already exists)'
  258. else
  259. echo 'x - extracting forward (Text)'
  260. sed 's/^X//' << 'SHAR_EOF' > 'forward' &&
  261. X"|exec /global/bin/procmail"
  262. SHAR_EOF
  263. chmod 0644 forward ||
  264. echo 'restore of forward failed'
  265. Wc_c="`wc -c < 'forward'`"
  266. test 29 -eq "$Wc_c" ||
  267.     echo 'forward: original size 29, current size' "$Wc_c"
  268. fi
  269. # ============= lockfile.1 ==============
  270. if test -f 'lockfile.1' -a X"$1" != X"-c"; then
  271.     echo 'x - skipping lockfile.1 (File already exists)'
  272. else
  273. echo 'x - extracting lockfile.1 (Text)'
  274. sed 's/^X//' << 'SHAR_EOF' > 'lockfile.1' &&
  275. X.\" @(#)lockfile.1 1.29 90/12/07 SMI;
  276. X.de Sh
  277. X.br
  278. X.ne 6
  279. X.SH \\$1
  280. X..
  281. X.de Ss
  282. X.br
  283. X.ne 6
  284. X.SS \\$1
  285. X..
  286. X.TH LOCKFILE 1 "07 December 1990"
  287. X.SH NAME
  288. Xlockfile \- conditional semaphore-file creator
  289. X.SH SYNOPSIS
  290. X.B lockfile
  291. X[
  292. X.BI \- sleeptime
  293. X] [
  294. X.BI \-r retries
  295. X] [
  296. X.B \-!
  297. X]
  298. X.I filename
  299. X\&.\|.\|.
  300. X.Sh "DESCRIPTION"
  301. X.B lockfile
  302. Xcan be used to create one or more
  303. X.I semaphore
  304. X.IR files .
  305. XIf
  306. X.B lockfile
  307. Xcan't create all the specified files (in the specified order), it waits
  308. X.I sleeptime
  309. X(defaults to 8) seconds and retries the last file that didn't succeed.
  310. XYou can specify the number of
  311. X.I retries
  312. Xto do until failure is returned.
  313. XIf the number of
  314. X.I retries
  315. Xis 0 (default)
  316. X.B lockfile
  317. Xwill retry forever.
  318. X.LP
  319. XIf the number of
  320. X.I retries
  321. Xexpires before all files have been created,
  322. X.B lockfile
  323. Xreturns failure and removes all the files it created up till that point.
  324. X.LP
  325. XThe return value of
  326. X.B lockfile
  327. Xcan be easily inverted by specifying
  328. X.B \-!
  329. Xas an argument (handy in shell scripts).
  330. X.LP
  331. XAll flags can be specified anywhere on the command line, they will be
  332. Xprocessed when encountered.  The command line is simply parsed from
  333. Xleft to right.
  334. X.LP
  335. XAll files created by
  336. X.B lockfile
  337. Xwill have access permission 0, and therefore will have to be removed
  338. Xwith
  339. X.B rm
  340. X.BR \-f .
  341. X.Sh "SEE ALSO"
  342. X.LP
  343. X.BR rm (1),
  344. X.BR mail (1),
  345. X.BR binmail (1),
  346. X.BR sendmail (8),
  347. X.BR procmail (1)
  348. X.Sh "BUGS & SPECIAL FEATURES"
  349. X.LP
  350. X.B lockfile
  351. Xis only a simple program and can't process concatenated options.
  352. X.LP
  353. XMultiple
  354. X.B \-!
  355. Xflags will not toggle the return status.
  356. X.Sh "NOTES"
  357. X.LP
  358. XSince flags can occur anywhere on the command line, any filename starting
  359. Xwith an '-' has to be preceded by another '-'.
  360. X.LP
  361. XThe number of
  362. X.I retries
  363. Xis global.  That is, it is not reset when a new file is being created.
  364. XIt can, however, be reset by specifying
  365. X.RI \-r newretries
  366. Xafter every file on the command line.
  367. X.Sh "AUTHOR"
  368. X.LP
  369. XStephen R. van den Berg at RWTH-Aachen, Germany
  370. X.RS
  371. Xberg@marvin.e17.physik.tu-muenchen.de
  372. X.RE
  373. SHAR_EOF
  374. chmod 0644 lockfile.1 ||
  375. echo 'restore of lockfile.1 failed'
  376. Wc_c="`wc -c < 'lockfile.1'`"
  377. test 1974 -eq "$Wc_c" ||
  378.     echo 'lockfile.1: original size 1974, current size' "$Wc_c"
  379. fi
  380. # ============= lockfile.c ==============
  381. if test -f 'lockfile.c' -a X"$1" != X"-c"; then
  382.     echo 'x - skipping lockfile.c (File already exists)'
  383. else
  384. echo 'x - extracting lockfile.c (Text)'
  385. sed 's/^X//' << 'SHAR_EOF' > 'lockfile.c' &&
  386. X/************************************************************************
  387. X *      lockfile.c      a conditional semaphore-file creator            *
  388. X *                                                                      *
  389. X *      Version 1.02 1990-12-07                                         *
  390. X *      Is relatively bug free.                                         *
  391. X *                                                                      *
  392. X *      Created by S.R.van den Berg, The Netherlands                    *
  393. X *      The sources can be freely copied for any use.                   *
  394. X *                                                                      *
  395. X *      If you have had to make major changes in order to get it        *
  396. X *      running on a different machine, please send me the patches.     *
  397. X *      That way I might include them in a future version.              *
  398. X ************************************************************************/
  399. X#include <stdio.h>
  400. X#include <fcntl.h>
  401. X#include <signal.h>
  402. X
  403. Xint exitflag;
  404. X
  405. Xvoid failure(){
  406. X exitflag=1;}
  407. X
  408. Xmain(argc,argv)char*argv[];{int sleepsec,retries,i,invert;char**p,*cp;
  409. X sleepsec=8;retries=invert=0;
  410. X if(argc<2){
  411. X   putse("Usage: lockfile [-nnn] [-rnnn] [-!] file ...\n");return 2;}
  412. Xagain:
  413. X p=argv+1;signal(SIGHUP,failure);signal(SIGINT,failure);
  414. X signal(SIGQUIT,failure);signal(SIGTERM,failure);
  415. X do
  416. X    if(*(cp=*p)=='-')
  417. X       switch(cp[1]){
  418. X       case'!':invert=1;break;
  419. X       case'r':retries=strtol(cp+2,NULL,10);break;
  420. X       case'-':cp++;goto filename;
  421. X       default:
  422. X          if(sleepsec>=0)
  423. X             sleepsec=strtol(cp+1,NULL,10);}
  424. X    else
  425. Xfilename:
  426. X      if(sleepsec<0)
  427. X         unlink(cp);
  428. X      else{
  429. X         while(0>(i=open(cp,O_WRONLY|O_CREAT|O_EXCL|O_SYNC,0))){
  430. X            if(exitflag||retries==1){
  431. X               sleepsec=-1;*p=0;goto again;}
  432. X            sleep(sleepsec);
  433. X            if(retries)
  434. X               retries--;}
  435. X         close(i);}
  436. X while(*++p);
  437. Xreturn invert^(sleepsec<0);}
  438. X
  439. X#define STDERR  2
  440. X
  441. Xputse(a)char*a;{char*b;
  442. X b=a-1;
  443. X while(*++b);
  444. X write(STDERR,a,b-a);}
  445. SHAR_EOF
  446. chmod 0644 lockfile.c ||
  447. echo 'restore of lockfile.c failed'
  448. Wc_c="`wc -c < 'lockfile.c'`"
  449. test 2071 -eq "$Wc_c" ||
  450.     echo 'lockfile.c: original size 2071, current size' "$Wc_c"
  451. fi
  452. # ============= procmail.1 ==============
  453. if test -f 'procmail.1' -a X"$1" != X"-c"; then
  454.     echo 'x - skipping procmail.1 (File already exists)'
  455. else
  456. echo 'x - extracting procmail.1 (Text)'
  457. sed 's/^X//' << 'SHAR_EOF' > 'procmail.1' &&
  458. X.\" @(#)procmail.1 1.29 91/02/13 SMI;
  459. X.de Sh
  460. X.br
  461. X.ne 6
  462. X.SH \\$1
  463. X..
  464. X.de Ss
  465. X.br
  466. X.ne 6
  467. X.SS \\$1
  468. X..
  469. X.de Tp
  470. X.br
  471. X.ne 6
  472. X.TP \\$1
  473. X..
  474. X.TH PROCMAIL 1 "13 February 1991"
  475. X.SH NAME
  476. Xprocmail \- autonomous mail processor
  477. X.SH SYNOPSIS
  478. X.B procmail
  479. X[
  480. X.IB environmentvariable = value
  481. X|
  482. X.I rcfilename
  483. X] 
  484. X\&.\|.\|.
  485. X.Sh "DESCRIPTION"
  486. X.LP
  487. XFor a quick start, see
  488. X.B NOTES
  489. Xat the end.
  490. X.LP
  491. X.B procmail
  492. Xfirst sets some environment variables to default values, then, if no
  493. Xarguments are specified, it reads the mail message from stdin until an
  494. XEOF, separates
  495. Xthe body from the header and starts to look for a file named
  496. X.B .procmailrc
  497. Xin your home directory.
  498. X.LP
  499. X.Ss "Defaults"
  500. X.Tp 22
  501. X.B USER, HOME and SHELL
  502. XYour (the recipient's) defaults
  503. X.Tp
  504. X.B SHELLMETA
  505. X"'`&#{}()[]*?|<>~;!\\
  506. X.Tp
  507. X.B SHELLFLAGS
  508. X-c
  509. X.Tp
  510. X.B MAILDIR
  511. X$HOME
  512. X.Tp
  513. X.BR DEFAULT
  514. X$MAILDIR/.mailbox
  515. X.Tp
  516. X.B ORGMAIL
  517. X/var/spool/mail/$USER
  518. X.Tp
  519. X.B GREP
  520. X/usr/bin/egrep
  521. X.Tp
  522. X.B SENDMAIL
  523. X/usr/lib/sendmail
  524. X.Tp
  525. X.B LOCKEXT
  526. X\&.lock
  527. X.Tp
  528. X.B LOCKSLEEP
  529. X8
  530. X.Ss "Environment"
  531. X.Tp 12
  532. X.B MAILDIR
  533. XDefault directory while
  534. X.B procmail
  535. Xis executing (that means that all paths are relative to $MAILDIR).
  536. X.Tp
  537. X.B DEFAULT
  538. XDefault mailbox file (if not told otherwise,
  539. X.B procmail
  540. Xwill dump mail in this file)
  541. X.Tp
  542. X.B LOGFILE
  543. XAll incoming messages will be logged here with their 'From' and 'Subject'
  544. Xlines in the header.  This file will also contain any error or diagnostic
  545. Xmessages from
  546. X.BR procmail .
  547. X(Normally none :-).  If this file is not specified it defaults to
  548. X.BR /dev/null.
  549. X.Tp
  550. X.B ORGMAIL
  551. XUsually the system mailbox (ORiGinal MAILbox).  If, for some obscure
  552. Xreason (like "filesystem full") the mail could not be delivered, then this
  553. Xfile will be the last resort.  If
  554. X.B procmail
  555. Xfails to save the mail in here (deep, deep trouble :-), then the mail
  556. Xwill bounce back to the sender.
  557. X.Tp
  558. X.B LOCKFILE
  559. XGlobal semaphore file.  If this file already exists,
  560. X.B procmail
  561. Xwill wait until it has gone before proceeding, and will create it itself
  562. X(cleaning it up when ready, of course).  If more than one lockfile are
  563. Xspecified, then the previous one will be removed before trying to create
  564. Xthe new one.
  565. X.Tp
  566. X.B LOCKEXT
  567. XDefault extension that is appended to a destination file to determine
  568. Xwhat local lockfile to use (only if turned on, on a per-recipe basis).
  569. X.Tp
  570. X.B LOCKSLEEP
  571. XNumber of seconds
  572. X.B procmail
  573. Xwill sleep before retrying on a lockfile (if it already existed).
  574. X.Tp
  575. X.B HOST
  576. XIf this is not the hostname of the machine, processing of the current
  577. Xrcfile will immediately cease.  If other rcfiles were specified on the
  578. Xcommand line, processing will continue with the next one.  If all rcfiles
  579. Xare exhausted, the program will terminate, but will not generate an error
  580. X(i.e. to the mailer it will seem that the mail has been delivered).
  581. X.Tp
  582. X.B UMASK
  583. XThe name says it all (if it doesn't, then forget about this one :-).  It
  584. Xis taken as an octal number.  If not specified, it defaults to 077.
  585. X.Tp
  586. X.B GREP
  587. XThe program that gets called for parsing regular expressions.
  588. X.br
  589. XIt is called as: $GREP -e "$*" [-i];
  590. X.Tp
  591. X.B SHELLMETA
  592. XIf any of the characters in
  593. X.B SHELLMETA
  594. Xappears in the line specifying a filter or program, the line will be feeded
  595. Xto
  596. X.B $SHELL
  597. Xinstead of being executed directly.
  598. X.Tp
  599. X.B SHELLFLAGS
  600. XAny invocation of
  601. X.B $SHELL
  602. Xwill be like:
  603. X.br
  604. X$SHELL $SHELLFLAGS "$*";
  605. X.Tp
  606. X.B SENDMAIL
  607. XIf you're not using the
  608. X.I forwarding facility
  609. Xdon't worry about this one.  It specifies the program being called to
  610. Xforward any mail.
  611. X.br
  612. XIt gets invoked as: $SENDMAIL $*;
  613. X.Sh "ARGUMENTS"
  614. X.LP
  615. XAny arguments containing an '=' are considered to be environment variable
  616. Xassignments, they will
  617. X.B all
  618. Xbe evaluated after the default values have been
  619. Xassigned and before the
  620. X.B first
  621. Xrcfile is parsed.
  622. X.LP
  623. XAny other arguments are presumed to be rcfiles; 
  624. X.B procmail
  625. Xwill start with the first one it finds on the command line.  The following
  626. Xones will only be parsed if the preceding ones have a not matching
  627. X.B HOST
  628. Xdirective entry.
  629. X.LP
  630. XIf no rcfiles are specified, it looks for $HOME/.sortmailrc.  If not even
  631. Xthat can be found processing will continue according to the default
  632. Xsettings of the environment variables and the ones specified on the command
  633. Xline.
  634. X.Sh "RCFILE FORMAT"
  635. X.LP
  636. XEnvironment variable assignments and recipes can be freely intermixed
  637. Xin the rcfile.  If any environment variable has a special meaning to
  638. X.BR procmail ,
  639. Xit will used appropiately the moment it is parsed. (i.e. you can
  640. Xchange the default directory whenever you want by specifying a new
  641. X.BR MAILDIR ,
  642. Xswitch lockfiles by specifying a new
  643. X.B LOCKFILE
  644. X(normal persons won't need this particular application though), change
  645. Xthe umask at any time, etc., the possibilities are endless :-).
  646. X.LP
  647. XValues being assigned to environment variables (in the rcfile) can not
  648. Xcontain any space, tab, newline or '#' characters.  Anything on a line
  649. Xfrom the first '#' till EOL is considered comment.
  650. X.Ss "Recipes"
  651. X.LP
  652. XA line starting with ':' marks the beginning of a recipe.  It has the
  653. Xfollowing format:
  654. X.LP
  655. X: [
  656. X.I number
  657. X] [
  658. X.I options
  659. X] [ : [
  660. X.I locallockfile
  661. X] ]
  662. X.LP
  663. XThe
  664. X.I number
  665. Xis optional
  666. X(defaults to 1) and specifies the number of conditionals following this
  667. Xline.  Conditionals are complete lines that are passed onto
  668. X.B $GREP
  669. X.BR literally ,
  670. Xconditionals are anded; if
  671. X.I number
  672. Xis zero, then the condition is always true and no conditionals are expected
  673. Xnext.
  674. X.LP
  675. X.I Options
  676. Xcan be any of the following (don't insert spaces in between, from the first
  677. Xcharacter that is not a valid option till EOL will be skipped without notice):
  678. X.Tp 5
  679. X.B H
  680. XFeed the header to $GREP (default)
  681. X.Tp
  682. X.B B
  683. XFeed the body to $GREP
  684. X.Tp
  685. X.B I
  686. XTell $GREP to ignore case
  687. X.Tp
  688. X.B h
  689. XFeed the header to the pipe (default)
  690. X.Tp
  691. X.B b
  692. XFeed the body to the pipe (default)
  693. X.Tp
  694. X.B f
  695. XConsider the pipe as a filter (ignored if a file)
  696. X.Tp
  697. X.B c
  698. XContinue processing rcfile even if this recipe matches (not needed if 'f'
  699. Xspecified)
  700. X.Tp
  701. X.B w
  702. XWait for the process to finish (and check if it was successfull, normally
  703. Xignored).  If you specify 'f' and it matches, and the original mailer
  704. Xwill be told that the mail has already been delivered.  If you want
  705. X.B procmail
  706. Xto stall telling the mailer that the mail has been delivered, until
  707. Xit really has been, you'll have to specify 'w' together with every 'f'.
  708. XIf you don't, the mailer will be told that the mail has been delivered
  709. Xsuccesfully as soon as the first 'f' without a 'w' has been processed.
  710. XThis option is also advisable if you specified any
  711. X.I locallockfile
  712. Xon this recipe.
  713. X.Tp
  714. X.B s
  715. XMake
  716. X.B procmail
  717. Xsecure.  If any fork fails in the current recipe, retry until it succeeds
  718. X(usefull when running on machines that occasionally have a full process tables,
  719. Xto ensure normal delivery in any case).  If a fork fails and 's' is
  720. Xnot specified, it simply is logged in $LOGFILE and parsing of the rcfile
  721. Xcontinues (eventually delivering to $DEFAULT if no more recipes match).
  722. X.Ss "Local lockfile"
  723. X.LP
  724. XIf you put a second ':' on the first recipe line, then
  725. X.B procmail
  726. Xwill use a
  727. X.I locallockfile
  728. X(for this recipe only).  You optionally can specify
  729. Xthe
  730. X.I locallockfile
  731. Xto use; if you don't however,
  732. X.B procmail
  733. Xwill use the filename specified as the destination (or the filename
  734. Xfollowing the first '>>') and will append $LOCKEXT to it.
  735. X.Ss "Recipe destination"
  736. X.LP
  737. XThe next line can start with the following characters:
  738. X.Tp
  739. X.B !
  740. XForwards to all the specified mail addresses (comments are 
  741. X.B not
  742. Xignored on
  743. Xthis line).
  744. X.Tp
  745. X.B |
  746. XStarts the specified program, possibly in $SHELL if any
  747. Xof the $METASHELL characters are found (that means comments are normally
  748. Xprocessed by the shell on
  749. X.B this
  750. Xline).
  751. X.LP
  752. XAnything else will be taken as a filename (relative to $MAILDIR).  After the
  753. Xfilename everything will be ignored till EOL.
  754. X.Sh "EXAMPLES"
  755. X.LP
  756. XSome example recipes are listed below:
  757. X.LP
  758. XSort out all mail to mailling list scuba-dive.
  759. X.RS
  760. X.LP
  761. X:
  762. X.PD 0
  763. X.LP
  764. X^TOscuba
  765. X.LP
  766. Xscubafile
  767. X.PD
  768. X.LP
  769. X.RE
  770. XForward all mail from peter about compilers to william (and keep a copy
  771. Xof it here in petcompil).
  772. X.RS
  773. X.LP
  774. X:2 bc
  775. X.PD 0
  776. X.LP
  777. X^From.*peter
  778. X.LP
  779. X^Subject:.*compilers
  780. X.LP
  781. X! william@somewhere.edu
  782. X.LP
  783. X:2
  784. X.LP
  785. X^From.*peter
  786. X.LP
  787. X^Subject:.*compilers
  788. X.LP
  789. Xpetcompil
  790. X.PD
  791. X.RE
  792. X.LP
  793. XAdd the headers of all messages to your private header collection (for
  794. Xstatistics or mail debugging); and use the lockfile "headc.lock".  In order
  795. Xto make sure the lockfile is not removed until the pipe has finished,
  796. Xyou have to specify option 'w'; otherwise the lockfile would be removed as
  797. Xsoon as the pipe had accepted the mail.
  798. X.RS
  799. X.LP
  800. X:0hwc:
  801. X.PD 0
  802. X.LP
  803. X| uncompress headc.Z; cat >>headc; compress headc
  804. X.RE
  805. X.PD
  806. X.LP
  807. XPrepend a linecount at the beginning of all multi part messages
  808. X(and don't allow
  809. X.B procmail
  810. Xto terminate early if the filter succeeds).  Use "templock" as lockfile.
  811. X.RS
  812. X.LP
  813. X:wbf:templock
  814. X.PD 0
  815. X.LP
  816. X^Subject:.*\\(.*(/|of).*\\)
  817. X.LP
  818. X|echo "wc output:";tee tempf|wc;cat tempf;rm tempf
  819. X.PD
  820. X.RE
  821. X.LP
  822. XDump all mail from at jobs into one file, filter out the interesting
  823. Xparts of the header first.
  824. X.LP
  825. X.RS
  826. X:2fh
  827. X.PD 0
  828. X.LP
  829. X^From root
  830. X.LP
  831. X^Subject: Output from "at" job
  832. X.LP
  833. X|echo "From at job";echo;egrep "^Date:"
  834. X.LP
  835. X:b
  836. X.LP
  837. X^From at job
  838. X.LP
  839. Xatjunk
  840. X.RE
  841. X.PD
  842. X.Sh "FILES"
  843. X.PD 0
  844. X.Tp 22
  845. X.B /etc/passwd
  846. Xto get the recipients USER, HOME and SHELL variable defaults
  847. X.Tp
  848. X.B /var/spool/mail/$USER
  849. Xdefault last resort to put mail
  850. X.Tp 
  851. X.B $HOME/.procmailrc
  852. Xdefault rc file
  853. X.Tp
  854. X.B $HOME/.mailbox
  855. Xdefault mailbox
  856. X.Tp
  857. X.B /var/spool/mail/$USER.lock
  858. Xlockfile for standard system mail directory (not used by
  859. X.B procmail
  860. Xunless you explicitly tell it to)
  861. X.Tp
  862. X.B /lib/sendmail
  863. Xdefault mail forwarder
  864. X.Tp
  865. X.B /usr/bin/egrep
  866. Xdefault regular expression parser
  867. X.PD
  868. X.Sh "SEE ALSO"
  869. X.LP
  870. X.BR sh (1),
  871. X.BR csh (1),
  872. X.BR mail (1),
  873. X.BR binmail (1),
  874. X.BR uucp (1C),
  875. X.BR aliases (5),
  876. X.BR sendmail (8),
  877. X.BR egrep (1V),
  878. X.BR lockfile (1)
  879. X.Sh "DIAGNOSTICS"
  880. X.Tp 23
  881. XError while writing to "x"
  882. Xnonexistent subdirectory, no write permission, or disk full
  883. X.Tp
  884. XFailed forking "x"
  885. Xnot possible if 's' flag specified on the recipe
  886. X.Tp
  887. XProgram failure of "x"
  888. Xsome pipe or program that was started by
  889. X.B procmail
  890. Xreturned a non-null value
  891. X.Tp
  892. XFailed to execute "x"
  893. Xprogram not in path, or not executable
  894. X.Tp
  895. XCouldn't unlink "x"
  896. Xlockfile was already gone, or write permission to the directory were the
  897. Xlockfile is has been denied
  898. X.Tp
  899. XOut of memory
  900. Xprobably a runaway filter that dumps junk into
  901. X.BR procmail,
  902. Xor the system could be out of swapspace
  903. X.Tp
  904. XLockfailure
  905. Xcan only occur if you specify some real weird (and illegal) lockfilenames
  906. X.PD
  907. X.Sh "BUGS & SPECIAL FEATURES"
  908. X.LP
  909. XIf you don't explicitly tell
  910. X.B procmail
  911. Xto wait (option 'w') for the pipe or program to finish, it won't wait
  912. Xand will terminate early (not knowing if the pipe or program returns
  913. Xsuccess).
  914. X.LP
  915. XThe only substitutions of environment variables that can be handled by
  916. X.B procmail
  917. Xitself are of the type $name.
  918. X.LP
  919. XA line buffer of 2048 bytes is used when processing the
  920. X.BR rcfile ,
  921. Xany environment variable expansions
  922. X.B have
  923. Xto fit within this limit.
  924. X.LP
  925. XRace conditions sometimes result in a failure to remove a lock file
  926. X(e.g. forwarding mail to yourself (on the same account) could (not
  927. Xnecessarily) be a problem).
  928. X.LP
  929. XIn the unlikely event that you absolutely need to kill
  930. X.B procmail
  931. Xbefore it has finished, then first try and use
  932. Xthe regular kill command (SIGTERM), otherwise some
  933. X.I lockfiles
  934. Xmight not get removed.
  935. X.LP
  936. XYou should create a shell script that uses
  937. X.BR lockfile (1)
  938. Xbefore invoking
  939. Xthe mail program on any mailbox file other than the system mailbox.
  940. X.Sh "NOTES"
  941. X.LP
  942. XAny program executed from within
  943. X.B procmail
  944. Xwill be searched for in the PATH variable (you have to specify it though).
  945. XIt is advisable however, to specify an absolute path for $GREP, because
  946. Xit get's executed fairly often.
  947. X.LP
  948. XIf the regular expression starts with "^TO" it will be substituted by
  949. X"^(To|Cc|Apparently-To):.*", which should catch all destination
  950. Xspecifications.
  951. X.LP
  952. XAny lines in the body of the message that look like postmarks are prepended
  953. Xwith '>' (disarms bogus mailheaders).  The regular expression that is used
  954. Xto search for these postmarks is:
  955. X.RS
  956. X\\n\\nFrom +[^\\t\\n ]+ +[^\\n\\t]
  957. X.RE
  958. X.LP
  959. XShould the uid
  960. X.B procmail
  961. Xis running under have no corresponding /etc/passwd entry, then HOME will
  962. Xdefault to /tmp, USER will default to #uid.
  963. X.LP
  964. XYour .forward (beware, it
  965. X.B has
  966. Xto be world readable) file should contain (include the quotes):
  967. X.LP
  968. X"|exec /global/bin/procmail"
  969. X.Ss "A sample small .procmailrc:"
  970. X.PD 0
  971. X.LP
  972. XPATH=/bin:/usr/bin:/global/bin:/usr/local/bin
  973. X.LP
  974. XMAILDIR=$HOME/mail      #you'd better make sure it exists
  975. X.LP
  976. XDEFAULT=$MAILDIR/mbox
  977. X.LP
  978. XLOGFILE=$MAILDIR/from
  979. X.LP
  980. XLOCKFILE=$HOME/.lockmail
  981. X.LP
  982. X:
  983. X.LP
  984. X^From.*berg
  985. X.LP
  986. Xfrom_me
  987. X.LP
  988. X:
  989. X.LP
  990. X^Subject:.*Flame
  991. X.LP
  992. X/dev/null
  993. X.PD
  994. X.Sh "AUTHOR"
  995. X.LP
  996. XStephen R. van den Berg at RWTH-Aachen, Germany
  997. X.RS
  998. Xberg@marvin.e17.physik.tu-muenchen.de
  999. X.RE
  1000. SHAR_EOF
  1001. chmod 0644 procmail.1 ||
  1002. echo 'restore of procmail.1 failed'
  1003. Wc_c="`wc -c < 'procmail.1'`"
  1004. test 12759 -eq "$Wc_c" ||
  1005.     echo 'procmail.1: original size 12759, current size' "$Wc_c"
  1006. fi
  1007. # ============= procmail.c ==============
  1008. if test -f 'procmail.c' -a X"$1" != X"-c"; then
  1009.     echo 'x - skipping procmail.c (File already exists)'
  1010. else
  1011. echo 'x - extracting procmail.c (Text)'
  1012. sed 's/^X//' << 'SHAR_EOF' > 'procmail.c' &&
  1013. X/************************************************************************
  1014. X *      procmail.c      an autonomous mail processor                    *
  1015. X *                                                                      *
  1016. X *      Version 1.10 1991-02-04                                         *
  1017. X *      Seems to be relatively bug free.                                *
  1018. X *                                                                      *
  1019. X *      Copyright (c) 1990-1991, S.R.van den Berg, The Netherlands      *
  1020. X *      The sources can be freely copied for non-commercial use.        *
  1021. X *                                                                      *
  1022. X *      Don't complain about the formatting, I know it's                *
  1023. X *      unconventional, but it's my standard format (I have my          *
  1024. X *      reasons).  If you don't like it, feed it through your           *
  1025. X *      favourite C beautifier.  The program has been tested on         *
  1026. X *      SUN's, but should work on almost every *NIX system that         *
  1027. X *      has a fork() and execvp() command.  The only things that        *
  1028. X *      might need some changes are the include files.                  *
  1029. X *      There might be one problem if your system doesn't know          *
  1030. X *      fsync(fd).  Define NOfsync in that case.                        *
  1031. X *                                                                      *
  1032. X *      If you have had to make major changes in order to get it        *
  1033. X *      running on a different machine, please send me the patches.     *
  1034. X *      That way I might include them in a future version.              *
  1035. X *                                                                      *
  1036. X *      Please note that this program essentially is supposed to be     *
  1037. X *      static, that means no extra features (IMHO no more are          *
  1038. X *      needed) are supposed to be added.                               *
  1039. X ************************************************************************/
  1040. X#ifdef  NOsync                  /* If you don't want syncs at all define */
  1041. X#define fsync(fd) 0             /* NOsync.  Only recommended if procmail */
  1042. X#define sync() 0                /* isn't used in a networked environment */
  1043. X#else
  1044. X# ifdef NOfsync                 /* If you don't have fsync, define NOfsync */
  1045. X# define fsync(fd) 0            /* sync will be used instead.  Is a bit    */
  1046. X# endif                         /* slower, but works nevertheless          */
  1047. X#endif
  1048. X
  1049. X#include <stdio.h>
  1050. X#ifndef NO_ANSI_PROT            /* define this if your headers are not ansi */
  1051. X# include <stdlib.h>
  1052. X#else
  1053. X  char*getenv();
  1054. X  typedef int pid_t;
  1055. X#endif
  1056. X#include <fcntl.h>
  1057. X#include <pwd.h>
  1058. X#include <sys/wait.h>
  1059. X#include <signal.h>
  1060. X#include <malloc.h>
  1061. X#include <string.h>
  1062. X#include <errno.h>
  1063. X#ifndef SYSV
  1064. X#include <sysexits.h>
  1065. X#else
  1066. X#include <bsd/sysexits.h>
  1067. X#endif
  1068. X#include "sysexits.h"
  1069. X#ifndef SEEK_SET
  1070. X#define SEEK_SET        0
  1071. X#endif
  1072. Xextern char**environ;
  1073. X#define STDIN   0
  1074. X#define STDOUT  1
  1075. X#define STDERR  2
  1076. Xtypedef unsigned t_buf; /* for malloc, realloc and memmove
  1077. X                          This type determines the maximum message length */
  1078. X
  1079. X#define BFSIZ           2048            /* max expanded line length */
  1080. X#define BLKSIZ          (1<<14)         /* blocksize while reading/writing */
  1081. X#define PROCMAILRC      ".procmailrc"
  1082. X#define SUSPENSION      64
  1083. X#define DEFlocksleep    8
  1084. X#define DEFlocksleeps   "8"
  1085. X#define TOkey           "^TO"
  1086. X#define TOkeylen        3
  1087. X#define TOsubstitute    "^(To|Cc|Apparently-To):.*"
  1088. X#define DEFshellmeta    "\"'`&#{}()[]*?|<>~;!\\"   /* never put '$' in here */
  1089. X#define DEFmaildir      "$HOME"
  1090. X#define DEFdefault      "$MAILDIR/.mailbox"
  1091. X#define DEForgmail      "/var/spool/mail/$USER"
  1092. X#define DEFgrep         "/usr/bin/egrep"
  1093. X#define DEFsendmail     "/usr/lib/sendmail"
  1094. X#define DEFlockext      ".lock"
  1095. X#define DEFshellflags   "-c"
  1096. X
  1097. Xchar buf[BFSIZ],buf2[BFSIZ],maildir[]="MAILDIR",defaultf[]="DEFAULT",
  1098. X logfile[]="LOGFILE",lockfile[]="LOCKFILE",grep[]="GREP",host[]="HOST",
  1099. X locksleep[]="LOCKSLEEP",orgmail[]="ORGMAIL",eumask[]="UMASK",
  1100. X shellmeta[]="SHELLMETA",shellflags[]="SHELLFLAGS",shell[]="SHELL",
  1101. X sendmail[]="SENDMAIL",lockext[]="LOCKEXT",devnull[]="/dev/null",
  1102. X newline[]="\n",binsh[]="/bin/sh",home[]="HOME",tmp[]="/tmp",user[]="USER",
  1103. X **gargv,*rcfile=PROCMAILRC,*globlock,*loclock,*tolock;
  1104. X#define PREAD   (poutfd[0])
  1105. X#define PWRITE  (poutfd[1])
  1106. X#define tscrc(a,b)      (0<fscanf(rc,a,b))
  1107. X#define scrc(a,b)       fscanf(rc,a,b)
  1108. Xint retval=EX_CANTCREAT,flaggerd=1,verrgrandchild,sh,pwait,secur,locking,
  1109. X nextexit,locknext;
  1110. Xpid_t mother;
  1111. XFILE*rc;
  1112. X
  1113. X#ifndef __STDC__
  1114. Xvoid*memmove(to,from,count)register void*to,*from;register t_buf count;{
  1115. X void*old;
  1116. X old=to;count++;--(char*)to;--(char*)from;
  1117. X if(to<=from){
  1118. X   goto jiasc;
  1119. X   do{
  1120. X      *++(char*)to=*++(char*)from;
  1121. Xjiasc:;}
  1122. X   while(--count);}
  1123. X else{
  1124. X   (char*)to+=count;(char*)from+=count;
  1125. X   goto jidesc;
  1126. X   do{
  1127. X      *--(char*)to=*--(char*)from;
  1128. Xjidesc:;}
  1129. X   while(--count);}
  1130. X return old;}
  1131. X#endif
  1132. X
  1133. Xpid_t sfork(){pid_t i;                 /* if secur is set, it doesn't return */
  1134. X while((i=fork())&&secur&&i==-1)       /* until the fork was successfull     */
  1135. X   sleep(SUSPENSION);
  1136. X return i;}
  1137. X
  1138. Xvoid*tmalloc(len)t_buf len;{void*p;
  1139. X if(p=malloc(len))
  1140. X   return p;
  1141. X nomemerr();}
  1142. X
  1143. Xvoid*trealloc(old,len)void*old;t_buf len;{
  1144. X if(old=realloc(old,len))
  1145. X   return old;
  1146. X nomemerr();}
  1147. X
  1148. Xvoid terminate(){
  1149. X if(locking){
  1150. X   nextexit=1;return;}
  1151. X sync();         /* sorry, but this is mail we're dealing with, safety first */
  1152. X unlock(&loclock);               /* local lock files are removed in any case */
  1153. X if(mother&&mother!=getpid())
  1154. X   if(retval!=EX_OK) /* tell mam we're in trouble, let her clean up the mess */
  1155. X      kill(mother,SIGQUIT);              /* don't try this at home, kids :-) */
  1156. X   else{
  1157. X      kill(mother,SIGHUP);goto allok;} /* You can go home mam, everything ok */
  1158. X else
  1159. Xallok:            /* global lockfile should be removed by the last surviving */
  1160. X   unlock(&globlock);   /* procmail */
  1161. X exit(retval);}
  1162. X
  1163. Xvoid flagger(){         /* hey, we received a SIGHUP */
  1164. X flaggerd=1;}
  1165. X
  1166. Xvoid errgrandchild(){   /* my grandchildren scream in despair */
  1167. X verrgrandchild=1;}
  1168. X
  1169. Xlong dump(s,source,len)int s;char*source;long len;{int i;long ol;
  1170. X if(s>=0){
  1171. X    ol=len;
  1172. X    while(i=rwrite(s,source,BLKSIZ<len?BLKSIZ:(int)len)){
  1173. X       if(i<0){
  1174. X          i=0;goto writefin;}
  1175. X       len-=i;source+=i;}
  1176. X    if(!len&&(ol<2||!(source[-1]=='\n'&&source[-2]=='\n')))
  1177. X       rwrite(s,newline,1);         /* message always ends with a newline */
  1178. Xwritefin:
  1179. X    if(fsync(s)&&errno!=EINVAL)
  1180. X       len++;           /* if there is a physical write error */
  1181. X    rclose(s);return len-i;}
  1182. X return len?len:-1;}    /* return an error even if nothing was to be sent */
  1183. X
  1184. Xlong pipin(line,source,len)char*line,*source;long len;{pid_t pid;
  1185. X int poutfd[2];
  1186. X pipe(poutfd);
  1187. X if(!(pid=sfork(line))){
  1188. X   rclose(PWRITE);redirect(PREAD);callnewprog(line);}
  1189. X rclose(PREAD);forkerr(pid,line);
  1190. X if(len=dump(PWRITE,source,len))
  1191. X   writeerr(line);
  1192. X if(pwait&&waitfor(pid)){
  1193. X   progerr(line);len=1;}
  1194. X return len;}
  1195. X
  1196. Xchar*readdyn(bf,filled)char*bf;long*filled;{int i;
  1197. X goto jumpin;
  1198. X do{
  1199. X   *filled+=i;
  1200. Xjumpin:
  1201. X   bf=trealloc(bf,(t_buf)*filled+BLKSIZ);}         /* dynamic adjust */
  1202. X while(0<(i=read(STDIN,bf+*filled,BLKSIZ)));
  1203. X if(!*filled)
  1204. X   return trealloc(bf,1);
  1205. X return trealloc(bf,(t_buf)*filled);}   /* minimize the buffer space */
  1206. X
  1207. Xchar*cat(a,b)char*a,*b;{
  1208. X return strcat(strcpy(buf,a),b);}
  1209. X
  1210. Xchar*findel(start,end)register char*start,*end;{/* find the first empty line */
  1211. X while(start<end)
  1212. X   if(*start++=='\n'&&start<end&&*start=='\n')
  1213. X      return start+1;
  1214. X return end;}
  1215. X
  1216. Xmain(argc,argv)char*argv[];{static char flags[10];int i;
  1217. X char*themail,*thebody,*chp,*startchar,*chp2;long tobesent,filled,rcoffset;
  1218. X mother=getpid();setbuf(stdin,(void*)0);umask(077);
  1219. X sprintf(buf,"%u",i=getuid());setpwent();
  1220. X {struct passwd*pass;
  1221. X if(pass=getpwuid(i)){                  /* find user defaults in /etc/passwd */
  1222. X   setdef(home,pass->pw_dir);chdir(pass->pw_dir);
  1223. X   setdef(user,pass->pw_name?pass->pw_name:buf);setdef(shell,pass->pw_shell);}
  1224. X else{                   /* user could not be found, set reasonable defaults */
  1225. X   setdef(home,tmp);chdir(tmp);setdef(user,buf);setdef(shell,binsh);}}
  1226. X endpwent();setdef(shellmeta,DEFshellmeta);setdef(shellflags,DEFshellflags);
  1227. X setdef(maildir,DEFmaildir);setdef(defaultf,DEFdefault);
  1228. X setdef(orgmail,DEForgmail);setdef(grep,DEFgrep);setdef(sendmail,DEFsendmail);
  1229. X setdef(lockext,DEFlockext);setdef(locksleep,DEFlocksleeps);
  1230. X chdir(getenv(maildir));fdreopena(devnull,STDERR);fdreopena(devnull,STDOUT);
  1231. X gargv=argv+1;nextrcfile();
  1232. X thebody=themail=tmalloc((t_buf)(argc=1));filled=rcoffset=0;
  1233. Xchangedmail:
  1234. X themail=readdyn(themail,&filled);      /* read in the mail */
  1235. Xonlyhead:
  1236. X startchar=filled+(thebody=themail);
  1237. X while(thebody<startchar&&*thebody++=='\n');        /* skip leading garbage */
  1238. X thebody=findel(thebody,startchar);     /* find the end of the header       */
  1239. X chp=thebody;
  1240. X do{                                    /* search for bogus headers         */
  1241. X   if(startchar-chp<8)                  /* we're looking for:               */
  1242. X      break;                            /* "\n\nFrom +[^\t\n ]+ +[^\n\t]"   */
  1243. X   if(0>=sscanf(chp,"From%1[ ]",buf))   /* thats the regular expression     */
  1244. X      continue;                         /* that defines the start of a mail */
  1245. X   chp2=chp;chp+=5;                     /* message.                         */
  1246. X#define SKIPWHILE(x)    while(x){ if(++chp>=startchar) break;}
  1247. X   SKIPWHILE(*chp==' ')
  1248. X   SKIPWHILE((i=*chp)&&i!=' '&&i!='\t'&&i!='\n')
  1249. X   SKIPWHILE(*chp==' ')
  1250. X   if((i=*chp)&&i!='\n'&&i!='\t'){      /* insert '>' before bogus header */
  1251. X      i=startchar[-1];memmove(chp2+1,chp2,(t_buf)(startchar-chp2)-1);
  1252. X      *chp2='>';themail=trealloc(chp2=themail,++filled);
  1253. X#define ADJUST(x)       ((x)=themail+((x)-chp2))
  1254. X      ADJUST(thebody);ADJUST(startchar);ADJUST(chp);*startchar++=i;}}
  1255. X while(startchar>(chp=findel(chp,startchar)));
  1256. X waitflagger();         /* if we're a child, wait for the parental guidance */
  1257. Xchangerc:
  1258. X rc=fopen(strcat(cat(getenv(home),"/"),rcfile),"r");
  1259. X fseek(rc,rcoffset,SEEK_SET);signal(SIGINT,terminate);
  1260. X signal(SIGQUIT,terminate);signal(SIGTERM,terminate);signal(SIGHUP,SIG_IGN);
  1261. Xgoon:
  1262. X while(unlock(&loclock),!feof(rc)||argv[argc]){
  1263. X   while(chp=argv[argc]){       /* interpret command line specs first */
  1264. X      argc++;strcpy(buf2,chp);
  1265. X      if(chp=strchr(buf2,'=')){
  1266. X         chp++;goto argenv;}}
  1267. X   if(tscrc(" %1[:]",flags)){   /* check for a recipe */
  1268. X      skipblanks();i=sh=1;
  1269. X      if(tscrc("%[0-9]",buf2)){
  1270. X         sscanf(buf2,"%d",&sh);skipblanks();}
  1271. X      *flags='\0';scrc("%9[HBIhbfcws]",flags);skipblanks();
  1272. X      if(tolock)                /* clear temporary buffer for lockfile name */
  1273. X         free(tolock);
  1274. X      tolock=0;
  1275. X      if((locknext=(tscrc("%1[:]",buf)))&&
  1276. X         (skipblanks(),tscrc("%[^ \t\n#]",buf)))
  1277. X         tolock=strdup(buf);
  1278. X      startchar=themail;tobesent=thebody-themail;
  1279. X      if(strchr(flags,'B'))     /* what needs to be piped into grep? */
  1280. X         if(strchr(flags,'H'))
  1281. X            tobesent=filled;
  1282. X         else{
  1283. X            startchar=thebody;tobesent=filled-tobesent;}
  1284. X      while(sh--){                              /* any conditions (left) */
  1285. X         skiptoeol();scrc("%[^\n]",buf2);
  1286. X         if(!strncmp(buf2,TOkey,TOkeylen))
  1287. X            cat(TOsubstitute,buf2+TOkeylen);
  1288. X         else
  1289. X            strcpy(buf,buf2);
  1290. X         if(i)                                  /* check out all conditions */
  1291. X            i=!grepin(buf,startchar,tobesent,!strchr(flags,'I'));}
  1292. X      startchar=themail;tobesent=filled;        /* body, header or both? */
  1293. X      if(strchr(flags,'h')){
  1294. X         if(!strchr(flags,'b'))
  1295. X            tobesent=thebody-themail;}
  1296. X      else if(strchr(flags,'b'))
  1297. X         tobesent-=(startchar=thebody)-themail;
  1298. X      chp=buf+strlen(cat(getenv(sendmail)," "));sh=0;
  1299. X      pwait=!!strchr(flags,'w');secur=!!strchr(flags,'s');
  1300. X      if(tscrc(" ! %[^\n]",chp)){               /* forward the mail */
  1301. X         if(i)
  1302. X            goto forward;}
  1303. X      else if(tscrc("| %[^\n]",buf2)){          /* pipe the mail */
  1304. X         if(i){
  1305. X            if(sh=!!strpbrk(buf2,getenv(shellmeta)))
  1306. X               strcpy(buf,buf2);
  1307. X            else
  1308. X               parse();
  1309. X            chp=buf;*buf2='\0';
  1310. X            while(i=*chp)     /* find the implicit lockfile name ('>>name') */
  1311. X              if(chp++,i=='>'&&*chp=='>'){
  1312. X                 while((i=*++chp)==' '||i=='\t');
  1313. X                 sscanf(chp,"%[^ \t\n#'\");|<>]",buf2);break;}
  1314. X            lcllock();
  1315. X            if(strchr(flags,'f')){
  1316. X               if(startchar==themail&&tobesent!=filled){     /* if only 'h' */
  1317. X                  char*dest;long dfilled=0;
  1318. X                  if(pipthrough(buf,startchar,tobesent))
  1319. X                     goto goon;
  1320. X                  dest=readdyn(tmalloc(1),&dfilled);filled-=tobesent;
  1321. X                  if(tobesent<dfilled)  /* adjust buffer size (only bigger) */
  1322. X                     themail=trealloc(themail,(t_buf)(dfilled+filled));
  1323. X                  memmove(themail+dfilled,themail+tobesent,(t_buf)filled);
  1324. X                  memmove(themail,dest,(t_buf)dfilled);free(dest);
  1325. X                  themail=trealloc(themail,(t_buf)(filled+=dfilled));
  1326. X                  goto onlyhead;}         /* and determine the header again */
  1327. X               rcoffset=ftell(rc);   /* needed because we have to fclose it */
  1328. X               if(pipthrough(buf,startchar,tobesent))
  1329. X                  goto goon;
  1330. X               filled=startchar-themail;goto changedmail;}
  1331. Xforward:    if(!pipin(buf,startchar,tobesent)&&!strchr(flags,'c'))
  1332. X               goto mailed;}}
  1333. X      else{                     /* append the mail to a file */
  1334. X         scrc("%s",buf2);skipcomment();
  1335. X         if(i){
  1336. X            parse();strcpy(buf2,buf);lcllock();
  1337. X            if(!dump(opena(buf),startchar,tobesent)&&!strchr(flags,'c'))
  1338. X               goto mailed;}}}
  1339. X   else if(tscrc("%[A-Z_a-z0-9] = ",buf)){ /* then it must be an assignment */
  1340. X      *(chp=buf+strlen(buf))='=';*++chp='\0';scrc("%[^ \t\n#]",chp);
  1341. X      skipcomment();strcpy(buf2,buf);
  1342. Xargenv:
  1343. X      parse();putenv(strdup(buf));chp[-1]='\0';
  1344. X      if(!strcmp(buf,maildir))
  1345. X         chdir(chp);
  1346. X      else if(!strcmp(buf,logfile))
  1347. X         fdreopena(chp,STDERR);
  1348. X      else if(!strcmp(buf,lockfile))
  1349. X         lockit(chp,&globlock);
  1350. X      else if(!strcmp(buf,eumask)){
  1351. X         sscanf(chp,"%o",&i);umask(i);}
  1352. X      else if(!strcmp(buf,host)){
  1353. X         *buf2='\0';gethostname(buf2,BFSIZ);
  1354. X         if(strcmp(chp,buf2)){
  1355. X            if(nextrcfile()){
  1356. X               fclose(rc);rcoffset=0;goto changerc;}
  1357. X            retval=EX_OK;terminate();}}}
  1358. X   else if(!skipcomment()){                    /* either comment or garbage */
  1359. X      scrc("%[^\n] ",buf);log("Skipped: \"");log(buf);logqnl();}}
  1360. X if(dump(opena(chp=getenv(defaultf)),themail,filled)){  /* default maildest */
  1361. X   writeerr(chp);          /* if it fails, don't panic, try the last resort */
  1362. X   if(dump(opena(chp=getenv(orgmail)),themail,filled))
  1363. X      writeerr(chp);goto mailerr;}                     /* now you can panic */
  1364. Xmailed:
  1365. X retval=EX_OK;                   /* we're home free, mail delivered */
  1366. Xmailerr:
  1367. X unlock(&loclock);               /* any local lock file still around? */
  1368. X do{
  1369. X   chp=buf-1;
  1370. X   while(themail<thebody&&chp<buf+BFSIZ-1&&(*++chp=*themail++)!='\n');
  1371. X   if(chp<buf)
  1372. X      chp++;
  1373. X   *chp='\0';
  1374. X   if(0<sscanf(buf,"From%*1[^:]%[^\n]",buf2)){
  1375. X      log("From ");goto foundsorf;}
  1376. X   else if(0<sscanf(buf,"Subject:%[^\n]",buf2)){
  1377. X      log(" Subject:");
  1378. Xfoundsorf:
  1379. X      log(buf2);log(newline);}}  /* log it's arrival */
  1380. X while(themail<thebody);
  1381. X terminate();}
  1382. X
  1383. Xsetdef(name,contents)char*name,*contents;{
  1384. X strcat(strcat(strcpy(buf2,name),"="),contents);parse();putenv(strdup(buf));}
  1385. X
  1386. Xskipblanks(){
  1387. X fscanf(rc,"%*[ \t]");}
  1388. X
  1389. Xskiptoeol(){
  1390. X fscanf(rc,"%*[^\n]");return fgetc(rc);}
  1391. X
  1392. Xskipcomment(){char i[2];        /* no comment :-) */
  1393. X if(tscrc("%1[\n]",i))
  1394. X   return 1;
  1395. X skipblanks();return scrc("%1[#]",i)?skiptoeol():feof(rc);}
  1396. X
  1397. Xpipthrough(line,source,len)char*line,*source;long len;{pid_t pidf,pid;
  1398. X int pinfd[2],poutfd[2];
  1399. X#define PWR2 (pinfd[1])
  1400. X#define PRD2 (pinfd[0])
  1401. X pipe(poutfd);pipe(pinfd);
  1402. X if(!(pidf=sfork())){           /* the filter is started here */
  1403. X   rclose(PWRITE);redirect(PREAD);rclose(STDOUT);dup(PWR2);rclose(PWR2);
  1404. X   rclose(PRD2);callnewprog(line);}
  1405. X rclose(PREAD);rclose(PWR2);
  1406. X if(forkerr(pidf,line)){
  1407. X   rclose(PRD2);return 1;}
  1408. X flaggerd=0;signal(SIGHUP,flagger);
  1409. X if(!(pid=sfork())){        /* this process will read back the filtered mail */
  1410. X   rclose(PWRITE);signal(SIGHUP,flagger);kill(getppid(),SIGHUP);redirect(PRD2);
  1411. X   if(!pwait&&mother){         /* if the wait chain ends here, notify mother */
  1412. X      kill(mother,SIGHUP);mother=0;}  /* everything ok mam, go ahead and die */
  1413. X   return 0;}           /* we will go ahead however (with or without mother) */
  1414. X rclose(PRD2);
  1415. X if(forkerr(pid,"procmail")){    /* An ingenious signal communication system */
  1416. X   kill(pidf,SIGTERM);return 1;} /* will ensure that NO lock file and        */
  1417. X if(dump(PWRITE,source,len)){    /* NO mail get's lost.                      */
  1418. X   kill(pidf,SIGTERM);kill(pid,SIGTERM);writeerr(line);return 1;}
  1419. X waitflagger();verrgrandchild=flaggerd=0;signal(SIGQUIT,errgrandchild);
  1420. X if(pwait){
  1421. X   if(waitfor(pidf)){       /* if the pipe fails, we will continue ourselves */
  1422. X      progerr(line);kill(pid,SIGTERM);return 1;}
  1423. X   for(kill(pid,SIGHUP),loclock=0;;sleep(SUSPENSION)){
  1424. X      if(flaggerd)
  1425. X         break;
  1426. X      if(verrgrandchild){    /* Check if one of my grandchildren has paniced */
  1427. X         signal(SIGQUIT,terminate);return 1;}}}
  1428. X else
  1429. X   kill(pid,SIGHUP);      /* if we don't wait, signal that we're bailing out */
  1430. X exit(EX_OK);}                           /* go ahead child, you have control */
  1431. X
  1432. Xwaitflagger(){
  1433. X while(!flaggerd)
  1434. X   sleep(SUSPENSION);}
  1435. X
  1436. Xgrepin(expr,source,len,casesens)char*expr,*source;long len;{pid_t pid;
  1437. X int poutfd[2];static char*newargv[5]={0,"-e"};
  1438. X newargv[3]=casesens?(char*)0:"-i";*newargv=getenv(grep);newargv[2]=expr;
  1439. X pipe(poutfd);
  1440. X if(!(pid=sfork())){
  1441. X   rclose(PWRITE);redirect(PREAD);shexec(newargv);}
  1442. X rclose(PREAD);dump(PWRITE,source,len);
  1443. X if(!forkerr(pid,*newargv))
  1444. X    return waitfor(pid);
  1445. X return 127;}
  1446. X
  1447. Xwaitfor(pid)pid_t pid;{int i;
  1448. X while(pid!=wait(&i)||(i&127)==127);
  1449. X return i>>8&255;}
  1450. X
  1451. Xredirect(pip){
  1452. X getstdinpipe(pip);fclose(rc);}
  1453. X
  1454. Xgetstdinpipe(pip){
  1455. X rclose(STDIN);dup(pip);rclose(pip);}
  1456. X
  1457. Xcallnewprog(newname)char*newname;{int argc;char*endp,**newargv;
  1458. X register char*p;
  1459. X p=newname;
  1460. X if(sh){char*newargv[4];        /* should we start a shell? */
  1461. X   newargv[3]=0;newargv[2]=p;newargv[1]=getenv(shellflags);
  1462. X   *newargv=getenv(shell);shexec(newargv);}
  1463. X argc=2;
  1464. X while(*p){  /* If no shell, we'll have to chop up the arguments ourselves */
  1465. X   if(*p==' '||*p=='\t'){
  1466. X      argc++;*p='\0';
  1467. X      while(*++p==' '||*p=='\t')
  1468. X         *p='\0';
  1469. X      continue;}
  1470. X   p++;}
  1471. X endp=p;*(newargv=tmalloc(argc*sizeof*newargv))=p=newname;argc=1;
  1472. X for(;;){
  1473. X   while(*p)
  1474. X      p++;
  1475. X   while(!*p){
  1476. X      if(p==endp){
  1477. X         newargv[argc]=0;shexec(newargv);}
  1478. X      p++;}
  1479. X   newargv[argc++]=p;}}
  1480. X
  1481. Xparse(){int i;char*org,*dest,*bd;   /* Implicitly copies from buf2 to buf */
  1482. X dest=buf;org=buf2;
  1483. X while(i=*org++)
  1484. X   if(i!='$')
  1485. X      *dest++=i;
  1486. X   else{                        /* substitute the thing... */
  1487. X      bd=buf2;
  1488. X      while((i=*org)>='A'&&i<='Z'||i>='a'&&i<='z'||i>='0'&&i<='9'||i=='_'){
  1489. X         *bd++=i;org++;}
  1490. X      *bd='\0';
  1491. X      if(bd=getenv(buf2)){
  1492. X         strcpy(dest,bd);
  1493. X         while(*dest)
  1494. X            dest++;}}
  1495. X *dest='\0';}
  1496. X
  1497. Xwriteerr(line)char*line;{
  1498. X log("Error while writing to \"");log(line);logqnl();}
  1499. X
  1500. Xforkerr(pid,a)pid_t pid;char*a;{
  1501. X if(pid==-1){
  1502. X   log("Failed forking \"");log(a);logqnl();return 1;}
  1503. X return 0;}
  1504. X
  1505. Xprogerr(line)char*line;{
  1506. X log("Program failure of \"");log(line);logqnl();}
  1507. X
  1508. Xlog(a)char*a;{char*b;
  1509. X b=a-1;
  1510. X while(*++b);
  1511. X rwrite(STDERR,a,b-a);}
  1512. X
  1513. Xopena(a)char*a;{
  1514. Xreturn open(a,O_WRONLY|O_APPEND|O_CREAT,0666);}
  1515. X
  1516. Xfdreopena(a,fd)char*a;{  /* Currently only works for 0,1,2 */
  1517. X rclose(fd);return opena(a);}
  1518. X
  1519. Xshexec(argv)char**argv;{int i;char**newargv,**p;
  1520. X execvp(*argv,argv);    /* if this one fails, we retry it as a shell script */
  1521. X for(p=argv,i=1;i++,*p++;);
  1522. X newargv=tmalloc(i*sizeof*p);
  1523. X for(*(p=newargv)=binsh;*++p=*++argv;);
  1524. X execve(*newargv,newargv,environ);      /* no shell script? -> trouble */
  1525. X log("Failed to execute \"");log(*argv);logqnl();exit(EX_UNAVAILABLE);}
  1526. X
  1527. Xunlock(lockp)char**lockp;{
  1528. X locking=1;
  1529. X if(*lockp){
  1530. X   if(unlink(*lockp)){
  1531. X      log("Couldn't unlink \"");log(*lockp);logqnl();}
  1532. X   free(*lockp);*lockp=0;}
  1533. X locking=0;}
  1534. X
  1535. Xnomemerr(){
  1536. X log("Out of memory\nbuffer 0: \"");log(buf);log("\"\nbuffer 1: \"");
  1537. X log(buf2);logqnl();retval=EX_OSERR;terminate();}
  1538. X
  1539. Xlogqnl(){
  1540. X log("\"\n");}
  1541. X
  1542. Xnextrcfile(){char*p;   /* find the next rcfile specified on the command line */
  1543. X while(p=*gargv){
  1544. X   gargv++;
  1545. X   if(!strchr(p,'=')){
  1546. X      rcfile=p;return 1;}}
  1547. X return 0;}
  1548. X
  1549. Xrclose(fd){int i;               /* a sysV secure close (signal immune) */
  1550. X while((i=close(fd))&&errno==EINTR);
  1551. X return i;}
  1552. X
  1553. Xrwrite(fd,a,len)void*a;{int i;  /* a sysV secure write (signal immune) */
  1554. X while(0>(i=write(fd,a,len))&&errno==EINTR);
  1555. X return i;}
  1556. X
  1557. Xlockit(name,lockp)char*name,**lockp;{int i;
  1558. X unlock(lockp);                 /* unlock any previous lockfile FIRST      */
  1559. X for(locking=1;;){              /* to prevent deadlocks (I hate deadlocks) */
  1560. X   if(0<=(i=open(name,O_WRONLY|O_CREAT|O_EXCL|O_SYNC,0))){
  1561. X      rclose(i);*lockp=strdup(name);
  1562. Xterm: locking=0;
  1563. X      if(nextexit)
  1564. X         terminate();
  1565. X      return;}
  1566. X   if(errno==ENAMETOOLONG){     /* if too long, make it shorter and retry */
  1567. X      if(0<(i=strlen(name)-1)){
  1568. X         name[i]='\0';continue;}
  1569. X      log("Lockfailure\n");return;}
  1570. X   i=DEFlocksleep;sscanf(getenv(locksleep),"%i",&i);sleep(i);
  1571. X   if(nextexit)
  1572. X      goto term;}}
  1573. X
  1574. Xlcllock(){                      /* lock a local file (if need be) */
  1575. X if(locknext)
  1576. X   if(tolock)
  1577. X      lockit(tolock,&loclock);
  1578. X   else
  1579. X      lockit(strcat(buf2,getenv(lockext)),&loclock);}
  1580. X
  1581. X/* That's all folks */
  1582. SHAR_EOF
  1583. chmod 0644 procmail.c ||
  1584. echo 'restore of procmail.c failed'
  1585. Wc_c="`wc -c < 'procmail.c'`"
  1586. test 22067 -eq "$Wc_c" ||
  1587.     echo 'procmail.c: original size 22067, current size' "$Wc_c"
  1588. fi
  1589. # ============= procmailrc ==============
  1590. if test -f 'procmailrc' -a X"$1" != X"-c"; then
  1591.     echo 'x - skipping procmailrc (File already exists)'
  1592. else
  1593. echo 'x - extracting procmailrc (Text)'
  1594. sed 's/^X//' << 'SHAR_EOF' > 'procmailrc' &&
  1595. XPATH=$HOME/bin:/usr/bin:/global/bin:/usr/ucb:/bin
  1596. XMAILDIR=$HOME/mail      # You'd better make sure it exists
  1597. XDEFAULT=$MAILDIR/mbox
  1598. XLOGFILE=$MAILDIR/from
  1599. XLOCKFILE=$HOME/.lockmail
  1600. X
  1601. X::
  1602. X^From.*thf
  1603. Xtodd
  1604. X
  1605. X:2fh
  1606. X^From root
  1607. X^Subject: Output from "at" job
  1608. X|echo "From at job";echo;egrep "^Date:"
  1609. X:b
  1610. X^From at job
  1611. Xatjunk
  1612. X
  1613. SHAR_EOF
  1614. chmod 0644 procmailrc ||
  1615. echo 'restore of procmailrc failed'
  1616. Wc_c="`wc -c < 'procmailrc'`"
  1617. test 310 -eq "$Wc_c" ||
  1618.     echo 'procmailrc: original size 310, current size' "$Wc_c"
  1619. fi
  1620. # ============= rmail ==============
  1621. if test -f 'rmail' -a X"$1" != X"-c"; then
  1622.     echo 'x - skipping rmail (File already exists)'
  1623. else
  1624. echo 'x - extracting rmail (Text)'
  1625. sed 's/^X//' << 'SHAR_EOF' > 'rmail' &&
  1626. X#!/bin/sh
  1627. X#
  1628. X# specify the mailbox file you want to read on the command line
  1629. X#
  1630. Xcd $HOME/mail
  1631. XLOCKFILE=$HOME/.lockmail
  1632. Xif lockfile -! -r1 $LOCKFILE
  1633. Xthen
  1634. X echo Mail is currently arriving, please wait...
  1635. X while
  1636. X   lockfile -! -4 -r2 $LOCKFILE
  1637. X do
  1638. X echo Mail is still arriving...
  1639. X done
  1640. Xfi
  1641. X#
  1642. X# Call you favourite mailer here.
  1643. X#
  1644. X/usr/ucb/mail -f $*
  1645. X#
  1646. X#
  1647. X#
  1648. Xrm -f $LOCKFILE
  1649. SHAR_EOF
  1650. chmod 0644 rmail ||
  1651. echo 'restore of rmail failed'
  1652. Wc_c="`wc -c < 'rmail'`"
  1653. test 364 -eq "$Wc_c" ||
  1654.     echo 'rmail: original size 364, current size' "$Wc_c"
  1655. fi
  1656. # ============= sysexits.h ==============
  1657. if test -f 'sysexits.h' -a X"$1" != X"-c"; then
  1658.     echo 'x - skipping sysexits.h (File already exists)'
  1659. else
  1660. echo 'x - extracting sysexits.h (Text)'
  1661. sed 's/^X//' << 'SHAR_EOF' > 'sysexits.h' &&
  1662. X#ifndef EX_OK
  1663. X# define EX_OK          0       /* successful termination */
  1664. X
  1665. X# define EX__BASE       64      /* base value for error messages */
  1666. X
  1667. X# define EX_USAGE       64      /* command line usage error */
  1668. X# define EX_DATAERR     65      /* data format error */
  1669. X# define EX_NOINPUT     66      /* cannot open input */
  1670. X# define EX_NOUSER      67      /* addressee unknown */
  1671. X# define EX_NOHOST      68      /* host name unknown */
  1672. X# define EX_UNAVAILABLE 69      /* service unavailable */
  1673. X# define EX_SOFTWARE    70      /* internal software error */
  1674. X# define EX_OSERR       71      /* system error (e.g., can't fork) */
  1675. X# define EX_OSFILE      72      /* critical OS file missing */
  1676. X# define EX_CANTCREAT   73      /* can't create (user) output file */
  1677. X# define EX_IOERR       74      /* input/output error */
  1678. X# define EX_TEMPFAIL    75      /* temp failure; user is invited to retry */
  1679. X# define EX_PROTOCOL    76      /* remote error in protocol */
  1680. X# define EX_NOPERM      77      /* permission denied */
  1681. X#endif
  1682. SHAR_EOF
  1683. chmod 0644 sysexits.h ||
  1684. echo 'restore of sysexits.h failed'
  1685. Wc_c="`wc -c < 'sysexits.h'`"
  1686. test 1015 -eq "$Wc_c" ||
  1687.     echo 'sysexits.h: original size 1015, current size' "$Wc_c"
  1688. fi
  1689. exit 0
  1690.  
  1691.  
  1692. exit 0 # Just in case...
  1693. -- 
  1694. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1695. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1696. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1697. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1698.