home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / procmail / part03 < prev    next >
Encoding:
Text File  |  1992-05-12  |  53.3 KB  |  1,466 lines

  1. Newsgroups: comp.sources.misc
  2. From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  3. Subject:  v29i092:  procmail - mail processing program v2.70, Part03/05
  4. Message-ID: <1992May11.151604.29066@sparky.imd.sterling.com>
  5. X-Md4-Signature: a3ac9653f966d6d489efdf66a918d847
  6. Date: Mon, 11 May 1992 15:16:04 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  10. Posting-number: Volume 29, Issue 92
  11. Archive-name: procmail/part03
  12. Environment: UNIX, sendmail, smail, MMDF
  13. Supersedes: procmail: Volume 28, Issue 01-05
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 3 (of 5)."
  22. # Contents:  procmail/autoconf procmail/config.h
  23. #   procmail/examples/advanced procmail/examples/mailinglist
  24. #   procmail/regexp.c procmail/strpbrk.h
  25. # Wrapped by berg@drunol on Thu Apr 30 13:42:57 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'procmail/autoconf' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'procmail/autoconf'\"
  29. else
  30. echo shar: Extracting \"'procmail/autoconf'\" \(7670 characters\)
  31. sed "s/^X//" >'procmail/autoconf' <<'END_OF_FILE'
  32. X
  33. X#$Id: autoconf,v 2.20 1992/04/29 16:38:45 berg Exp $
  34. X
  35. XSHELL=$4 || exec $4 autoconf $* # we're in a csh, feed myself to sh
  36. X
  37. X# All possible entries in autoconf.h:
  38. X
  39. X#    #define UNISTD_H_MISSING
  40. X#    #define STDDEF_H_MISSING
  41. X#    #define STDLIB_H_MISSING
  42. X#    #define SYS_WAIT_H_MISSING
  43. X#    #define SYS_UTSNAME_H_MISSING
  44. X#    #define STRING_H_MISSING
  45. X#    #define SYSEXITS_H_MISSING
  46. X#    #define SYS_FILE_H_MISSING
  47. X#    #define const
  48. X#    #define volatile
  49. X#    #define void char
  50. X#    typedef int mode_t;
  51. X#    typedef int pid_t;
  52. X#    typedef int uid_t;
  53. X#    typedef int gid_t;
  54. X#    typedef unsigned size_t;
  55. X#    typedef long time_t;
  56. X#    #define NOmemmove
  57. X#    #define NObcopy
  58. X#    #define NOstrcspn
  59. X#    #define NOstrpbrk
  60. X#    #define NOrename
  61. X#    #define strchr(s,c) index(s,c)
  62. X#    #define endpwent()
  63. X#    #define endgrent()
  64. X#    #define strtol(str,ptr,base) ((long)atoi(str))
  65. X#    #define WMACROS_NON_POSIX
  66. X#    #define oBRAIN_DAMAGE
  67. X#    #define SMALLHEAP
  68. X#    #define SYSTEM_MAILBOX "/usr/spool/mail/$USER"
  69. X#    #define SENDMAIL "/usr/lib/sendmail"
  70. X
  71. X# A conforming ANSI compiler and POSIX library should only produce six
  72. X# entries in autoconf.h: SYS_FILE_H_MISSING, endpwent(), endgrent(), rename(),
  73. X# SYSTEM_MAILBOX, SENDMAIL (and perhaps SMALLHEAP)
  74. X# Anything else indicates failure of your installation to comply with either
  75. X# the ANSI or POSIX standards (but procmail should be installable anyway).
  76. X
  77. XPATH=:$PATH
  78. XACONF=$3
  79. XMAKE="$2"
  80. XRM="$5"
  81. XUSRINC=$6
  82. XDEVNULL=/dev/null
  83. Xexport SHELL PATH
  84. Xif test -f $ACONF
  85. Xthen
  86. X trap "exit 1" 1 2 3 15
  87. Xelse
  88. X trap "$RM $ACONF; exit 1" 1 2 3 15
  89. Xfi
  90. X
  91. Xif test -n "$LD_LIBRARY_PATH"
  92. Xthen
  93. X echo '***************************** WARNING *********************************'
  94. X echo '* You seem to have set the LD_LIBRARY_PATH variable, this might cause *'
  95. X echo '* some trouble during the execution of this autoconf script.  If you  *'
  96. X echo '* encounter errors about "_autotst not found" or any other         *'
  97. X echo '* irregularities, stop the make, do a: "make clean",             *'
  98. X echo '* clear LD_LIBRARY_PATH from the environment, and start over.         *'
  99. X echo '***************************** WARNING *********************************'
  100. Xfi
  101. X
  102. Xcat >grepfor <<HERE
  103. Xfgrep -e "\$1" _autotst.rrr >$DEVNULL && echo "\$2" >>$ACONF
  104. XHERE
  105. Xchmod 0755 grepfor
  106. X
  107. Xcat >$ACONF <<HERE
  108. X/* This file was automagically generated by autoconf */
  109. X
  110. XHERE
  111. X
  112. Xtest -f $USRINC/unistd.h || echo "#define UNISTD_H_MISSING" >>$ACONF
  113. Xtest -f $USRINC/stddef.h || echo "#define STDDEF_H_MISSING" >>$ACONF
  114. Xtest -f $USRINC/stdlib.h || echo "#define STDLIB_H_MISSING" >>$ACONF
  115. Xtest -f $USRINC/sys/wait.h || echo "#define SYS_WAIT_H_MISSING" >>$ACONF
  116. Xtest -f $USRINC/sys/utsname.h || echo "#define SYS_UTSNAME_H_MISSING" >>$ACONF
  117. Xtest -f $USRINC/string.h || echo "#define STRING_H_MISSING" >>$ACONF
  118. Xtest -f $USRINC/sysexits.h || echo "#define SYSEXITS_H_MISSING" >>$ACONF
  119. Xtest -f $USRINC/sys/file.h || echo "#define SYS_FILE_H_MISSING" >>$ACONF
  120. X
  121. X# WARNING: in ./include/stdlib.h the const keyword is already used!
  122. X#       hence the const test has to precede all others.
  123. X
  124. Xcat >_autotst.c <<HERE
  125. Xmain()
  126. X{ char*const*p;char*q;
  127. X  p= &q;return 0;
  128. X}
  129. XHERE
  130. X
  131. Xecho 'Testing for const'
  132. Xif ${MAKE} _autotst.$1 >_autotst.rrr 2>&1 && test -f _autotst.$1
  133. Xthen
  134. X grepfor const '#define const'
  135. Xelse
  136. X echo '#define const' >>$ACONF
  137. Xfi
  138. X${RM} _autotst.$1
  139. X
  140. Xcat >_autotst.c <<HERE
  141. Xmain(){volatile int i;return(i=0);}
  142. XHERE
  143. X
  144. Xecho 'Testing for volatile'
  145. Xif ${MAKE} _autotst.$1 >$DEVNULL 2>&1 && test -f _autotst.$1
  146. Xthen
  147. X:
  148. Xelse
  149. X echo '#define volatile' >>$ACONF
  150. Xfi
  151. X${RM} _autotst.$1
  152. X
  153. Xcat >_autotst.c <<HERE
  154. X#include "includes.h"
  155. Xvoid*vvoid;
  156. Xmain(){int i;char*p="t";
  157. X {size_t vsize_t;i=vsize_t=1;}
  158. X {pid_t vpid_t;i=vpid_t=1;}
  159. X {time_t vtime_t;i=vtime_t=1;}
  160. X {mode_t vmode_t;i=vmode_t=1;}
  161. X {uid_t vuid_t;i=vuid_t=1;}
  162. X {gid_t vgid_t;i=vgid_t=1;}
  163. X vvoid=p;
  164. X return !vvoid;}
  165. XHERE
  166. X
  167. Xecho 'Testing for void*,size_t,pid_t,time_t,mode_t,uid_t,gid_t'
  168. X${MAKE} _autotst.$1 >_autotst.rrr 2>&1
  169. X${RM} _autotst.$1
  170. X
  171. Xgrepfor void '#define void char'
  172. Xgrepfor size_t 'typedef unsigned size_t;'
  173. Xgrepfor pid_t 'typedef int pid_t;'
  174. Xgrepfor time_t 'typedef long time_t;'
  175. Xgrepfor mode_t 'typedef int mode_t;'
  176. Xgrepfor uid_t 'typedef int uid_t;'
  177. Xgrepfor gid_t 'typedef int gid_t;'
  178. X
  179. Xcat >_autotst.c <<HERE
  180. X#include "includes.h"
  181. Xmain(){int i;i=1;
  182. X i+=WIFEXITED(i);
  183. X i+=WIFSTOPPED(i);
  184. X i+=WEXITSTATUS(i);
  185. X return i;}
  186. XHERE
  187. X
  188. Xecho 'Testing for WIFEXITED(), WIFSTOPPED() & WEXITSTATUS()'
  189. Xif ${MAKE} _autotst.$1 >_autotst.rrr 2>&1
  190. Xthen
  191. X   grepfor struct '#define WMACROS_NON_POSIX' ||
  192. X    grepfor union '#define WMACROS_NON_POSIX'
  193. Xelse
  194. X   echo '#define WMACROS_NON_POSIX' >>$ACONF
  195. Xfi
  196. X${RM} _autotst.$1
  197. X
  198. Xcat >_autotst.c <<HERE
  199. X#include "includes.h"
  200. Xmain(){char a[2];
  201. X endpwent();endgrent();memmove(a,"0",1);bcopy("0",a,1);strcspn(a,"0");
  202. X strtol("0",(char**)0,10);strchr("0",'0');strpbrk(a,"0");rename(a,"0");
  203. X return 0;}
  204. XHERE
  205. X
  206. Xecho 'Testing for memmove, strchr, strpbrk, strcspn & strtol'
  207. X${MAKE} _autotst.$1 >$DEVNULL 2>&1
  208. X${MAKE} _autotst >_autotst.rrr 2>&1
  209. X${RM} _autotst _autotst.$1
  210. X
  211. Xgrepfor strcspn '#define NOstrcspn'
  212. Xgrepfor strpbrk '#define NOstrpbrk'
  213. Xgrepfor rename '#define NOrename'
  214. Xgrepfor strchr '#define strchr(s,c) index(s,c)'
  215. Xgrepfor setpwent '#define setpwent()'
  216. Xgrepfor endpwent '#define endpwent()'
  217. Xgrepfor endgrent '#define endgrent()'
  218. Xgrepfor strtol '#define strtol(str,ptr,base) ((long)atoi(str))'
  219. Xgrepfor memmove '#define NOmemmove' &&
  220. Xif fgrep -e bcopy _autotst.rrr >$DEVNULL
  221. Xthen
  222. X echo '#define NObcopy' >>$ACONF
  223. X
  224. X echo 'Testing for brain damage'
  225. X cat >_autotst.c <<HERE
  226. X#include "includes.h"
  227. Xstruct tests{int a,b;};
  228. Xmain(){
  229. X return offsetof(struct tests,b);}
  230. XHERE
  231. X if ${MAKE} _autotst.$1 >$DEVNULL 2>&1
  232. X then
  233. X    :
  234. X else
  235. X    echo 'Yep, it is'            # ISC chokes on its own offsetof()
  236. X    echo '#define oBRAIN_DAMAGE' >>$ACONF
  237. X fi
  238. X ${RM} _autotst.$1
  239. X
  240. Xelse
  241. X
  242. X cat >_autotst.c <<HERE
  243. X#include "includes.h"
  244. X#define M256    256
  245. X#define F33    33
  246. Xmain(){int j=0,i=M256-1;static char a[M256];
  247. X do a[i]=i;while(i--);
  248. X bcopy(a+F33,a,M256-F33);bcopy(a,a+F33,M256-F33);i=F33-1;
  249. X do j|=a[i]!=(char)(i+F33);while(i--);i=M256-1;
  250. X do j|=a[i]!=(char)i;while(--i!=F33-1);return!j;}
  251. XHERE
  252. X
  253. X echo 'Testing for bcopy handling overlaps'
  254. X ${MAKE} _autotst >$DEVNULL 2>&1
  255. X
  256. X if _autotst
  257. X then
  258. X   echo 'Sorry, incompetent bcopy'
  259. X   echo '#define NObcopy' >>$ACONF
  260. X fi
  261. X ${RM} _autotst
  262. Xfi
  263. X
  264. Xcat >_autotst.c <<HERE
  265. X#include "includes.h"
  266. Xmain(){unsigned long s=(size_t)~0;int i;
  267. X for(i=1;s>>=1;++i);
  268. X if(i<=16)
  269. X    puts("#define SMALLHEAP");
  270. X return 0;}
  271. XHERE
  272. X
  273. Xecho 'Determining the most applicable block size'
  274. X
  275. X${MAKE} _autotst >$DEVNULL 2>&1
  276. X_autotst >>$ACONF
  277. X${RM} _autotst
  278. X
  279. Xif test -d /usr/spool/mail
  280. Xthen
  281. X echo '#define SYSTEM_MAILBOX "/usr/spool/mail/$USER"' >>$ACONF
  282. Xelif test -d /usr/mail
  283. Xthen
  284. X echo '#define SYSTEM_MAILBOX "/usr/mail/$USER"' >>$ACONF
  285. Xelse
  286. X echo '#define SYSTEM_MAILBOX "$HOME/.mail"' >>$ACONF
  287. X echo Could not find the system-mailbox directory, supplied substitute
  288. Xfi
  289. X
  290. Xcat >lookfor <<HERE
  291. Xfor a in /usr/lib /lib /usr/etc /etc /usr/bin /bin /usr/local/bin /usr/lbin \
  292. X /usr/local/lib /usr/local /usr/.lib
  293. Xdo
  294. X if test -f "\$a/\$1"
  295. X then
  296. X    echo "#define SENDMAIL \"\$a/\$1\"" >>$ACONF
  297. X    exit 0
  298. X fi
  299. Xdone
  300. Xexit 1
  301. XHERE
  302. Xchmod 0755 lookfor
  303. X
  304. Xif lookfor sendmail || lookfor smail
  305. Xthen
  306. X:
  307. Xelse
  308. X echo 'Could not find any mailer.  It should be a mailer accepting at least'
  309. X echo "one plain destination address as it's only argument (any sendmail"
  310. X echo 'compatible mailer will do), and the mail-to-be-sent on stdin.'
  311. X echo 'What is your mailer called?  (You can override this in config.h)'
  312. X read a
  313. X echo "#define SENDMAIL \"$a\"" >>$ACONF
  314. Xfi
  315. X
  316. X${RM} _autotst* lookfor grepfor
  317. X
  318. Xecho -----------------------------autoconf.h-----------------------------------
  319. Xcat $ACONF >&2
  320. Xecho --------------------------------------------------------------------------
  321. END_OF_FILE
  322. if test 7670 -ne `wc -c <'procmail/autoconf'`; then
  323.     echo shar: \"'procmail/autoconf'\" unpacked with wrong size!
  324. fi
  325. # end of 'procmail/autoconf'
  326. fi
  327. if test -f 'procmail/config.h' -a "${1}" != "-c" ; then 
  328.   echo shar: Will not clobber existing file \"'procmail/config.h'\"
  329. else
  330. echo shar: Extracting \"'procmail/config.h'\" \(7789 characters\)
  331. sed "s/^X//" >'procmail/config.h' <<'END_OF_FILE'
  332. X/*$Id: config.h,v 2.19 1992/04/29 15:54:33 berg Rel $*/
  333. X
  334. X/*#define KERNEL_LOCKS    /* uncomment if you want to use kernel locks on file
  335. X               descriptors (not recommended if your system uses a
  336. X    buggy lockd across a net, or if your mailer uses tmp files in updating
  337. X    mailboxes and moves them into place); only advisable if your mailreader
  338. X    can't be convinced to use "dotfile"-locks */
  339. X
  340. X/*#define sMAILBOX_SEPARATOR    "\1\1\1\1\n"    /* sTART- and eNDing separ.  */
  341. X#define eMAILBOX_SEPARATOR    "\2\1\1\1\n"    /* uncomment if your mail
  342. X                           system uses nonstandard
  343. X    mail separators (non sendmail or smail compatible mailers like MMDF),
  344. X    if yours is even different, uncomment and change the value of course */
  345. X
  346. X/* KEEPENV and PRESTENV should be defined as a comma-separated null-terminated
  347. X   list of strings */
  348. X
  349. X/* every environment variable appearing in KEEPENV will not be thrown away
  350. X * upon startup of procmail, e.g. you could define KEEPENV as follows:
  351. X * #define KEEPENV    {"TZ","LANG",0}
  352. X */
  353. X#define KEEPENV        {0}
  354. X
  355. X/* every environment variable appearing in PRESTENV will be set or wiped
  356. X * out of the environment (variables without an '=' sign will be thrown
  357. X * out), e.g. you could define PRESTENV as follows:
  358. X * #define PRESTENV    {"IFS","PATH=$HOME/bin:/bin:/usr/bin",0}
  359. X * any side effects (like setting the umask after an assignment to UMASK) will
  360. X * *not* take place
  361. X */
  362. X#define PRESTENV    {"IFS","LD_LIBRARY_PATH",0}
  363. X
  364. X/*****************************************************************
  365. X * Only edit below this line if you have edited this file before *
  366. X *****************************************************************/
  367. X
  368. X/*#define NO_USER_TO_LOWERCASE_HACK    /* uncomment if your getpwnam() is
  369. X                       case insensitive or if procmail
  370. X    will always be supplied with the correct case in the explicit
  371. X    delivery mode argument */
  372. X
  373. X/*#define NO_NFS_ATIME_HACK    /* uncomment if you're definitely not using
  374. X                   NFS mounted filesystems and can't afford
  375. X    procmail to sleep for 1 sec. before writing a mailbox */
  376. X
  377. X/* every user & group appearing in TRUSTED_IDS is allowed to use the -f option
  378. X   if the list is empty (just a terminating 0), everyone can use it
  379. X   TRUSTED_IDS should be defined as a comma-separated null-terminated
  380. X   list of strings */
  381. X
  382. X#define TRUSTED_IDS    {"root","daemon","uucp","mail","x400",0}
  383. X
  384. X/*#define SYSTEM_MBOX    "$HOME/.mbox"    /* uncomment and/or change if the
  385. X                       preset default mailbox is *not*
  386. X    either /usr/spool/mail/$USER or /usr/mail/$USER (it will supersede
  387. X    the value of SYSTEM_MAILBOX) */
  388. X
  389. X/*#define DEFsendmail    "/bin/mail"    /* uncomment and/or change if the
  390. X                       preset default SENDMAIL is not
  391. X    suitable */
  392. X
  393. X/*#define console    "/dev/console"    /* uncomment if you want procmail to
  394. X                       use the console (or any other
  395. X    terminal) to print any error messages that could not be dumped in the
  396. X    "logfile".  (Only recommended for debugging purposes, if you have
  397. X    trouble creating a "logfile") */
  398. X
  399. X/************************************************************************
  400. X * Only edit below this line if you *think* you know what you are doing *
  401. X ************************************************************************/
  402. X
  403. X#define NOBODY_uid    0xfffe          /* default uid when no valid recipient */
  404. X#define NOBODY_gid    0xfffe          /* default gid when no valid recipient */
  405. X#define ROOT_uid    0
  406. X
  407. X#define INIT_UMASK    (S_IRWXG|S_IRWXO)               /* == 077 */
  408. X#define NORMperm    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
  409. X         /* == 0666, normal mode bits used to create files, before umask */
  410. X#define LOCKperm    0      /* mode bits used while creating lockfiles */
  411. X#define MAX_LOCK_SIZE    0      /* lockfiles are expected not to be longer */
  412. X#ifndef SMALLHEAP
  413. X#define DEFlinebuf    2048         /* default max expanded line length */
  414. X#define BLKSIZ        16384          /* blocksize while reading/writing */
  415. X#define STDBUF        1024             /* blocksize for emulated stdio */
  416. X#else           /* and some lower defaults for the unfortunate amongst us */
  417. X#define DEFlinebuf    512
  418. X#define BLKSIZ        1024
  419. X#define STDBUF        128
  420. X#endif /* SMALLHEAP */
  421. X#define HOSTNAMElen    9      /* nr of significant chararacters for HOST */
  422. X#define BOGUSprefix    "BOGUS."         /* prepended to bogus mailboxes */
  423. X#define PROCMAILRC    ".procmailrc"
  424. X#define DEFsuspend    16         /* multi-purpose 'idle loop' period */
  425. X#define DEFlocksleep    8
  426. X#define TOkey        "^TO"
  427. X#define TOsubstitute    "^(To|Cc|Apparently-To):.*"
  428. X#define DEFshellmetas    "&|<>~;?*[]="            /* never put '$' in here */
  429. X#define DEFmaildir    "$HOME"
  430. X#define DEFdefault    "$ORGMAIL"
  431. X#define DEFdefaultlock    "LOCKFILE=$DEFAULT$LOCKEXT"
  432. X#define DEFmsgprefix    "msg."
  433. X#define DEFlockext    ".lock"
  434. X#define DEFshellflags    "-c"
  435. X#define DEFlocktimeout    3600                 /* defaults to one hour */
  436. X#define DEFtimeout    (DEFlocktimeout-60)       /* 60 seconds to clean up */
  437. X#define DEFnoresretry    4      /* default nr of retries if no resources left */
  438. X
  439. X#define BinSh        "/bin/sh"
  440. X#define Tmp        "/tmp"
  441. X#define DEBUGPREFIX    ':'             /* debug prefix for LOGFILE */
  442. X#define DevNull        "/dev/null"
  443. X#define DIRSEP        "/"         /* directory separator symbols, the */
  444. X                   /* last one should be the most common one */
  445. X
  446. X#define EOFName        " \t\n#`'\");"
  447. X
  448. X#define VERSIONOPT    'v'            /* option to display version */
  449. X#define PRESERVOPT    'p'                 /* preserve environment */
  450. X#define TEMPFAILOPT    't'              /* return EX_TEMPFAIL on error */
  451. X#define FROMWHOPT    'f'               /* set name on From_ line */
  452. X#define ALTFROMWHOPT    'r'        /* alternate and obsolete form of -f */
  453. X#define DELIVEROPT    'd'          /* deliver mail to named recipient */
  454. X#define PROCMAIL_USAGE    \
  455. X "Usage: procmail [-vpt] [-f fromwhom] [parameter=value | rcfile] ...\
  456. X\n   Or: procmail [-vpt] [-f fromwhom] -d recipient ...\n"
  457. X
  458. X#define MINlinebuf    128    /* minimal LINEBUF length (don't change this) */
  459. X#define FROM_EXPR    "\nFrom "
  460. X#define FROM        "From "
  461. X#define NSUBJECT    "^Subject:.*$"
  462. X#define MAXSUBJECTSHOW    78
  463. X#define FOLDER        "  Folder: "
  464. X#define LENtSTOP    9 /* tab stop at which message length will be logged */
  465. X
  466. X#define TABCHAR        "\t"
  467. X#define TABWIDTH    8
  468. X
  469. X#define RECFLAGS    "HBDAahbfcwWi"
  470. X#define HEAD_GREP     0
  471. X#define BODY_GREP      1
  472. X#define DISTINGUISH_CASE   2
  473. X#define ALSO_NEXT_RECIPE    3
  474. X#define ALSO_N_IF_SUCC         4
  475. X#define PASS_HEAD          5
  476. X#define PASS_BODY           6
  477. X#define FILTER            7
  478. X#define CONTINUE         8
  479. X#define WAIT_EXIT          9
  480. X#define WAIT_EXIT_QUIET           10
  481. X#define IGNORE_WRITERR            11
  482. X
  483. X#define UNIQ_PREFIX    '_'      /* prepended to temporary unique filenames */
  484. X#define ESCAP        '>'
  485. X
  486. X        /* some formail-specific configuration options: */
  487. X
  488. X#define UNKNOWN        "foo@bar"      /* formail default originator name */
  489. X#define OLD_PREFIX    "Old-"             /* formail field-Old-prefix */
  490. X
  491. X#define FM_SKIP        '+'              /* skip the first nnn messages */
  492. X#define FM_TOTAL    '-'        /* only spit out a total of nnn messages */
  493. X#define FM_BOGUS    'b'             /* leave bogus Froms intact */
  494. X#define FM_FORCE    'f'   /* force formail to accept an arbitrary format */
  495. X#define FM_REPLY    'r'            /* generate an auto-reply header */
  496. X#define FM_KEEPB    'k'           /* keep the header, when replying */
  497. X#define FM_TRUST    't'    /* trust the sender to supply a valid header */
  498. X#define FM_SPLIT    's'                      /* split it up */
  499. X#define FM_NOWAIT    'n'              /* don't wait for the programs */
  500. X#define FM_EVERY    'e'    /* don't require empty lines leading headers */
  501. X#define FM_MINFIELDS    'm'    /* the number of fields that have to be found */
  502. X#define DEFminfields    2        /* before a header is recognised as such */
  503. X#define FM_DIGEST    'd'                 /* split up digests */
  504. X#define FM_QUIET    'q'            /* ignore write errors on stdout */
  505. X#define FM_EXTRACT    'x'               /* extract field contents */
  506. X#define FM_ADD_IFNOT    'a'         /* add a field if not already there */
  507. X#define FM_REN_INSERT    'i'            /* rename and insert a field */
  508. X#define FM_DEL_INSERT    'I'            /* delete and insert a field */
  509. X#define FM_USAGE    "Usage: \
  510. Xformail [+nn] [-nn] [-bfrktnedq] [-m nn] [-xaiI field] [-s prog arg ...]\n"
  511. END_OF_FILE
  512. if test 7789 -ne `wc -c <'procmail/config.h'`; then
  513.     echo shar: \"'procmail/config.h'\" unpacked with wrong size!
  514. fi
  515. # end of 'procmail/config.h'
  516. fi
  517. if test -f 'procmail/examples/advanced' -a "${1}" != "-c" ; then 
  518.   echo shar: Will not clobber existing file \"'procmail/examples/advanced'\"
  519. else
  520. echo shar: Extracting \"'procmail/examples/advanced'\" \(11463 characters\)
  521. sed "s/^X//" >'procmail/examples/advanced' <<'END_OF_FILE'
  522. XDiscusses:
  523. X        1. One home directory, several machine architectures
  524. X        2. Procmail as an integrated local mail delivery agent
  525. X        2a.Special directions for sites with sendmail
  526. X        2b.Special directions for sites with smail
  527. X        3. Security considerations (when installing procmail suid root)
  528. X        4. How to generate autoreplies
  529. X        4a.`Vacation' functionality
  530. X        5. Some exorbitant examples of rcfile formats
  531. X        6. Some advanced examples of the use of the 'A' flag
  532. X
  533. X                ---
  534. X
  535. X1. One home directory, several machine architectures
  536. X   -------------------------------------------------
  537. X
  538. XFor users that have the very same home directory on machines with differing
  539. Xarchitectures (i.e. you need different executables), and they
  540. Xhave to explicitly use (i.e. the system administrator did not arrange,
  541. Xfor example, /usr/local/bin/procmail to have exactly the right contents
  542. Xdepending on from which machine it is called) two executables of procmail,
  543. XI have the following suggestion to use as a .forward file (examples are for
  544. Xsparc and sun3 architectures):
  545. X
  546. X"|IFS=' ';if /usr/bin/sparc;then exec /home/berg/bin.sun4/procmail;else exec /home/berg/bin.sun3/procmail;fi #YOUR_LOGIN_NAME"
  547. X
  548. Xor alternatively:
  549. X
  550. X"|IFS=' ';exec /home/berg/bin.`/usr/bin/arch`/procmail #YOUR_LOGIN_NAME"
  551. X
  552. XPlease note, in the .forward file there can NOT be any newlines between
  553. Xthe doublequotes, i.e. the former example *has* to be typed in as one long
  554. Xline.
  555. X
  556. XIf, on the other hand, you have to log in to every machine to read mail
  557. Xarrived for you on that machine, a different solution might be more
  558. Xappropriate; in that case put something like the following two lines in your
  559. X.forward file:
  560. X
  561. XYOUR_LOGIN_NAME@your.favourite.machine
  562. X"|IFS=' ';if test .`/bin/uname -n` = .your.favourite.machine; then /exec /home/berg/bin/procmail; else exit 0; fi #YOUR_LOGIN_NAME"
  563. X
  564. XThe leading dots are important.     Check what `/bin/uname -n` returns on
  565. Xyour.favourite.machine, and substitute that for your.favourite.machine in the
  566. Xsample .forward file.  If your system does not have /bin/uname, /bin/hostname
  567. Xwill do too.
  568. X
  569. X                ---
  570. X
  571. X2. Procmail as an integrated local mail delivery agent
  572. X   ---------------------------------------------------
  573. X
  574. XCompletely integrating procmail in the mail delivery means that mail is
  575. Xdelivered as normal, unless a .procmailrc file is present in the home
  576. Xdirectory of the recipient.  This will be completely independent of the
  577. Xfact if a .forward file is present.  This will not break anything, it
  578. Xjust makes the use of procmail easier because people are not required to
  579. Xstart up procmail from within their .forward files.  Creation of a .procmailrc
  580. Xfile will suffice.
  581. X
  582. XThe generic way to accomplish this (works with sendmail, smail and any other
  583. Xmail system that uses a local mail delivery program that takes the mail-
  584. Xto-be-delivered on stdin and the recipient(s) on the command line, with or
  585. Xwithout the "-d" option) is this:
  586. X
  587. XMove your current local mail delivery agent (e.g. /bin/mail, /bin/lmail,
  588. X/usr/lib/mail/mail.local, etc.) out of the way, and create a (symbolic or hard)
  589. Xlink from there to procmail, as in "ln /usr/local/bin/procmail /bin/lmail".
  590. X
  591. XIn addition to needing root priviliges upon startup, on some systems procmail
  592. Xneeds to be sgid to daemon or mail.  One way to check is by looking at the
  593. Xcurrent mail delivery agent (usually /bin/mail) and to mimic its permissions,
  594. Xowner and group.  If you're not quite sure, just type "make recommend" and some
  595. Xsuitable recommendations will be made for your particular environment.
  596. X
  597. XThe same might apply to the "lockfile" program, in order for it to be able to
  598. Xcreate and unlink lockfiles in the mail spool directory it might need to be
  599. Xsgid to daemon or mail, not to worry however, "lockfile" will not enable users
  600. Xto abuse the sgid/suid-ness.
  601. X
  602. X                ---
  603. X
  604. X2a.Special directions for sites with sendmail
  605. X   ------------------------------------------
  606. X
  607. XHere you have two options:
  608. X i. Procmail *not* being suid root
  609. X ii.Procmail suid root (actually preferred and recommended)
  610. X
  611. X)Ad i.
  612. XThe following line should take the place of the standard
  613. XMlocal rule in your sendmail.cf (this way sendmail will start up procmail with
  614. Xroot priv, procmail will immediately setuid itself to the recipient's uid):
  615. X
  616. XMlocal, P=/usr/local/bin/procmail, F=lsSDFMuhP, S=10, R=20, A=procmail -d $u
  617. X
  618. X)Ad ii.
  619. XIf your sendmail does not allow starting programs with root privs (the
  620. X'S' flag), you can instead make procmail suid root (this is actually the
  621. Xpreferred way to go, it closes a security hole which actually sendmail should
  622. Xhave closed).  This will not create a security hole, procmail will normally
  623. Xsetuid immediately to the real uid (effectively losing root privs), or will
  624. Ximmediately setuid to the recipient's uid (and be completely loyal to the
  625. Xrecipient's absent or present .procmailrc file).  Actually installing procmail
  626. Xsuid root is a slightly more flexible approach (not at all more dangerous).
  627. X
  628. XIf using the suid root version of procmail, you only need to insert the
  629. Xfollowing line in your sendmail.cf:
  630. X
  631. XMlocal, P=/usr/local/bin/procmail, F=lsDFMuhP, S=10, R=20, A=procmail -d $u
  632. X
  633. XSo, to summarise, if you install procmail not-suid-root you should use the
  634. Xfirst rule (with the 'S' flag), and if you install it suid-root you should
  635. Xuse the second rule (without the 'S' flag).  If you install procmail
  636. Xnot-suid-root you cannot use the second rule, since procmail will not be
  637. Xable to change uid to the recipient, and therefore it cannot read/write
  638. Xthe recipient's files (including any .procmailrc).  The alternative would
  639. Xbe that procmail already has the recipient's uid upon startup, this is not
  640. Xpossible in sendmail without changing some configuration options.
  641. X
  642. XAs for the remaining flags "S=10, R=20", if your system uses others or
  643. Xnone on the current Mlocal rule, use those instead of "S=10, R=20".
  644. X
  645. X                ---
  646. X
  647. X2b.Special directions for sites with smail
  648. X   ---------------------------------------
  649. X
  650. XFor smail 2.x users there are two options:
  651. X i. Move the current local-mail-delivery program (probably /bin/lmail) out of
  652. X    the way, make a symbolic or hard link from procmail to the name of that
  653. X    program (e.g. "ln /usr/local/bin/procmail /bin/lmail")
  654. X ii.Make sure the following macro is defined in src/defs.h:
  655. X    #define LMAIL(frm,sys) "/usr/local/bin/procmail -d"
  656. X
  657. XFor smail 3.x users there are also two options:
  658. X i. The same solution as for smail 2.x (however, method ii is preferred)
  659. X ii.Replace any existing "local"-entry in the /usr/lib/smail/transports file
  660. X    (create one, if need be) with the following two lines:
  661. X
  662. Xlocal: return_path, local, from, driver=pipe;
  663. X    cmd="/usr/local/bin/procmail -d $($user$)"
  664. X
  665. XFor any ideas on suid/sgid modes which *might* be needed, see the previous
  666. Xparagraph (2).
  667. X
  668. X                ---
  669. X
  670. X3. Security considerations (when installing procmail suid root)
  671. X   -------------------------------------------------------------
  672. X
  673. XIf in EXPLICIT DELIVERY mode (typically when called from within sendmail)
  674. Xprocmail will ALWAYS change UID and gid to the RECIPIENT's defaults as soon as
  675. Xit starts reading the recipient's $HOME/.procmailrc file.
  676. X
  677. XIf NOT in explicit delivery mode (typically when called from within the
  678. Xrecipient's $HOME/.forward file) procmail will ALWAYS change UID and gid to
  679. Xthe real uid and gid of the INVOKER (effectively losing any suid or sgid
  680. Xpriviliges).
  681. X
  682. XThese two precautions should effectively eliminate any security holes because
  683. Xprocmail will always have the uid of the person whose commands it is executing.
  684. X
  685. XTo summarise, procmail will only behave better if made suid/sgid something, in
  686. Xfact, making procmail suid/sgid something will *improve* security on systems
  687. Xwhich have dynamically linked libraries.
  688. X
  689. X                ---
  690. X
  691. X4. How to generate autoreplies
  692. X   ---------------------------
  693. X
  694. XUsing a recipe like the following, you can generate autoreplies to mail
  695. Xreceived by you:
  696. X
  697. X: 2 h c
  698. X!^From +[^ ]*(postmaster|Mailer)
  699. X!^From +YOUR_LOGIN_NAME
  700. X| (formail -r ; echo "Mail received.") | $SENDMAIL -t
  701. X
  702. XAs you can see, I made sure that neither bouncing mail (from postmaster or the
  703. Xmailer-daemon), nor mail coming from yourself will be autoreplied.  If this
  704. Xprecaution would not be taken, disaster could result ("ringing" mail).
  705. XThe abovementioned recipe should be inserted before all other recipes in
  706. Xyour rcfile, however, it is advisable to put it *after* any recipes that
  707. Xprocess mailinglist subscriptions;  it generally is not a good idea to
  708. Xgenerate autoreplies to mailinglists.
  709. X
  710. X                ---
  711. X
  712. X4a.`Vacation' functionality
  713. X   ------------------------
  714. X
  715. XSHELL=/bin/sh            # for other shells, this might need adjustment
  716. XALREADYSENT=$MAILDIR/vacation            # the vacation database
  717. X
  718. X: 2 hWc:                # the lockfile is important
  719. X!^From +[^ ]*(postmaster|Mailer)
  720. X!^From +YOUR_LOGIN_NAME
  721. X| FROM="`formail -rx To:`" ;\
  722. X  if fgrep -e "$FROM" <$ALREADYSENT ;\
  723. X  then exit 1 ;\
  724. X  else echo "$FROM" >>$ALREADYSENT ;\
  725. X  fi
  726. X
  727. X    :ahc
  728. X    | (formail -r ; echo "Mail received.") | $SENDMAIL -t
  729. X
  730. XThis example is based on the same principles as before (sort out bounced mail
  731. Xand mail coming from oneself).    In addition to that however, it maintains a
  732. Xvacation database by extracting the name of the sender and appending it
  733. Xto $ALREADYSENT if the name is *not* already in there.    If the name was new,
  734. Xan autoreply will be sent (using the "a" flag functionality, see the man
  735. Xpage of procmail for more info).  To reliably extract the name of the sender,
  736. XI let formail generate an autoreply header (thereby making it figure out the
  737. Xmost appropriate sender address), and then telling it to extract the value
  738. Xof the "To:" field.
  739. X
  740. X                ---
  741. X
  742. X5. Some exorbitant examples of rcfile formats
  743. X   ------------------------------------------
  744. X
  745. X# Now follows an example of what you can do in a procmailrc file
  746. XHELLO=oneword
  747. XHELLO="two words"
  748. XHELLO='two words'    HELLO  =    one\
  749. Xword
  750. XHELLO=two\ words
  751. XHELLO=two\ `echo words`
  752. XHELLO=            # empty
  753. XHELLO            # This will wipe "HELLO" from the environment
  754. XHELLO     =    "three words"\ yes
  755. XHELLO    =    "$HELLO `cat somefile`    "    # Trailing blanks
  756. XHELLO = "wheeee`date`${HELLO} this works too"     HELLO = 'But so does this!'
  757. X
  758. X# As you can see, every trick in the book of /bin/sh programming can be used
  759. X# (and more).
  760. X
  761. XLOCALLOCKFILE = llf
  762. X
  763. X  ::$LOCALLOCKFILE
  764. Xgrep for this
  765. X |$HELLO        # calls up a program named "But" with 3 arguments
  766. X
  767. X:: "test ing"        # lockfilename with a space in it
  768. Xgrep for this
  769. X  |$HELLO
  770. X
  771. X:
  772. Xor for this
  773. X|"$HELLO"        # tries to call up a program named "But so does this!"
  774. X
  775. X:
  776. Xand this
  777. X|$HELLO \
  778. Xthere        # action lines can be continued
  779. X
  780. X                ---
  781. X
  782. X6. Some advanced examples of the use of the 'A' flag
  783. X   -------------------------------------------------
  784. X
  785. X:c        # Specify the 'c' otherwise we never arrive at the next recipe
  786. X^From Myfriend
  787. Xevery_message_from_my_friend        # Mailbox for everything he/she writes
  788. X
  789. X:Ac            # Note the 'c' again
  790. X! my_other_friend      # Forward everything Myfriend writes to my_other_friend
  791. X
  792. X:1Ac
  793. X^Subject:.*jokes
  794. X! my_third_friend    # Forward everything Myfriend writes about jokes
  795. X            # to my_third_friend
  796. X
  797. X:2A
  798. X^Subject:.*parties
  799. X!beach
  800. X! my_third_friend    # Forward everything Myfriend writes about parties,
  801. X            # except beach parties, to my_third_friend
  802. X
  803. X:A            # Provide a mail sink, in order to fake procmail into
  804. X/dev/null        # believing that the mail was absorbed/delivered,
  805. X            # even if the mail was about beach parties :-).
  806. X        # This is not the best solution though, better would be to
  807. X        # rearrange these last five recipes so that the current
  808. X        # number one or two is last, the current number five can be
  809. X        # omitted then.
  810. X
  811. X                ---
  812. END_OF_FILE
  813. if test 11463 -ne `wc -c <'procmail/examples/advanced'`; then
  814.     echo shar: \"'procmail/examples/advanced'\" unpacked with wrong size!
  815. fi
  816. # end of 'procmail/examples/advanced'
  817. fi
  818. if test -f 'procmail/examples/mailinglist' -a "${1}" != "-c" ; then 
  819.   echo shar: Will not clobber existing file \"'procmail/examples/mailinglist'\"
  820. else
  821. echo shar: Extracting \"'procmail/examples/mailinglist'\" \(11170 characters\)
  822. sed "s/^X//" >'procmail/examples/mailinglist' <<'END_OF_FILE'
  823. X$Id: mailinglist,v 2.6 1992/04/09 16:17:41 berg Rel $
  824. X
  825. X            How to set up mailing lists
  826. X            ---------------------------
  827. X
  828. X        Written by Stephen R. van den Berg.
  829. X                    berg@messua.informatik.rwth-aachen.de
  830. X                    berg@physik.tu-muenchen.de
  831. X
  832. XThis document mainly describes a sendmail environment, much of it applies
  833. Xto non-sendmail mail agents as well.
  834. X
  835. X
  836. XContents:
  837. X---------    1. Intro
  838. X        2. Bouncing mail
  839. X        3. The disadvantages
  840. X        4. How to circumvent these disadvantages
  841. X        5. Why use procmail to filter the mailinglist mail?
  842. X        6. How do I use procmail to filter the mailinglist mail?
  843. X        7. Now, what does the above all do?
  844. X        8. The result of this exercise
  845. X
  846. X1. Intro
  847. X   -----
  848. X
  849. XThe simplest and most direct way to do it is by insert a line in
  850. Xthe /usr/lib/aliases file looking like:
  851. X
  852. Xmylist: fred,john, wilma, barney@bedrock, pebbles
  853. X
  854. XNow all the mail arriving at your machine for "mylist" (either local or
  855. Xmylist@your.domain) will be automatically forwarded to all the mentioned
  856. Xaddresses (fred, john, etc.).
  857. X
  858. XThe address mylist@your.domain is intended for submissions to the list that
  859. Xare supposed to be forwarded to all the subscribers.  For the administrative
  860. Xtasks like removals from the list, new subscribtions to the list, or address
  861. Xchanges of subscribers one should create a second entry in the /usr/lib/aliases
  862. Xfile:
  863. X
  864. Xmylist-request: your_login_name@your.domain
  865. X
  866. X
  867. X2. Bouncing mail
  868. X   -------------
  869. X
  870. XIn order to deal with bouncing mail gracefully, an extra precaution should
  871. Xbe taken.  If for example mail to wilma bounces (user non-existent, mail
  872. Xfilesystem full, etc.), it will bounce back to the original sender.
  873. XNow, the only person that should be concerned with distribution failures
  874. Xshould be the mylist-request holder.  Therefore you should be using a
  875. Xsendmail special alias like:
  876. X
  877. Xowner-mylist: mylist-request@your.domain
  878. X
  879. XThis way local mail will bounce back to mylist-request@your.domain.
  880. X
  881. X
  882. X3. The disadvantages
  883. X   -----------------
  884. X
  885. XIf you are using the above methods, some obvious disadvantages come to mind
  886. Xhowever:
  887. X
  888. Xa. The subscriber list cannot exceed 1000 bytes (on most sendmails).
  889. Xb. The subscriber list cannot be changed on-the-fly (/usr/lib/aliases needs
  890. X   to be edited, and newaliases has to be run).
  891. Xc. People cannot be prevented from submitting messages like "Please remove
  892. X   me from this mailinglist" to mylist (and thereby annoying all subscribers).
  893. Xd. People cannot be guarded from themselves in case they insert
  894. X   "Return-Receipt-To:" fields in their headers (if they are particularly
  895. X   unlucky, they will receive an acknowledge mail from *every* subscriber's
  896. X   sendmail).
  897. Xe. People including "Errors-To:" or "Sender:" fields can cause the bounce
  898. X   messages to bypass owner-mylist anyway.
  899. Xf. There is no way of limiting the number of submitters, i.e. every person
  900. X   who knows the name of the mailing list and who can send mail to your.domain
  901. X   is able to submit messages to the list.  This means, for example, that you
  902. X   cannot limit a mailing list to local users (i.e. only local users can
  903. X   submit).
  904. Xg. You are unable to insert a "Reply-To: mylist@your.domain" in case you
  905. X   would want to (this makes replying to the list easier).
  906. X
  907. X
  908. X4. How to circumvent these disadvantages
  909. X  -------------------------------------
  910. X
  911. Xa. Can be circumvented by using nested aliases like:
  912. X    mylist: mylist1, mylist2
  913. X    mylist1: fred,john
  914. X    mylist2: wilma,barney@bedrock,pebbles
  915. X   This can however, become extremely messy to maintain.
  916. X
  917. Xb. This can partly be avoided if you use aliases like:
  918. X    mylist: :include:/path/to/the/memberfile
  919. X   The memberfile should contain:
  920. X    fred,john,wilma,barney@bedrock,pebbles
  921. X   You cannot avoid using newaliases however, and it *will* get extremely messy
  922. X   if you have to start using nested aliases.
  923. X
  924. Xc. Can only be taken care of by using a mailfilter like procmail.
  925. X
  926. Xd. Can only be taken care of by using a mailfilter like procmail.
  927. X
  928. Xe. Can only be taken care of by using a mailfilter like procmail.
  929. X
  930. Xf. Can only be taken care of by using a mailfilter like procmail.
  931. X
  932. Xh. Can only be taken care of by using a mailfilter like procmail.
  933. X
  934. X
  935. X5. Why use procmail to filter the mailinglist mail?
  936. X   ------------------------------------------------
  937. X
  938. XInstead of using a mailfilter you could also take care of most of the problems
  939. Xthree till seven by editing the sendmail.cf file.  I would strongly recommend
  940. Xagainst this approach however, since this will be too much of a customising
  941. Xoperation and surely will not be a trivial task (in all cases).     As a general
  942. Xrule: don't mess with a sendmail.cf file once it is working :-).
  943. X
  944. XNow, you could, instead of procmail, simply use immediate VNIX commands
  945. Xlike grep, sed, awk to do the mail filtering.  Again, there are some obvious
  946. Xdisadvantages with this approach:
  947. X
  948. XA. In case any system resources go out (no more file descriptors, no more
  949. X   swap space, process table full, file system full (for temporary files))
  950. X   your awk or shell script will fail generously (i.e. several bad things
  951. X   could happen: mail munged, truncated, lost, hanging awk or sh programs,
  952. X   etc., you get the picture).
  953. X
  954. XB. All mail headers (including From: and Reply-To:) could very well be
  955. X   multi-line headers; it will be very difficult to make it understandable
  956. X   to awk that somehow the header line could continue on the next line
  957. X   (in case you want to remove a header, or do some complicated substitution).
  958. X
  959. XC. Another hairy problem will be determining the end of the header, of course
  960. X   that is solvable, but you have to make some extra precautions in your
  961. X   awk script to ensure that any substitutions/changes will not occur in
  962. X   the body of the message.
  963. X
  964. XProcmail does not *directly* allow you to change any headers, but that
  965. Xfeature is not really necessary since you can tell procmail to send ONLY the
  966. Xheader through some filter of your choice.
  967. X
  968. XTo comment on the previously mentioned three disadvantages:
  969. X
  970. XA. procmail takes care of that.     Should the filter have problems anyway,
  971. X   procmail will graciously notice that the filter was in some kind of
  972. X   trouble, and will try something else with the original unmunged mail
  973. X   (you can specify what it should do of course, obvious choices: try
  974. X   the same filter again, drop the mail in a file and send you a notice,
  975. X   forward the mail to you instead (unfiltered), etc.)
  976. X
  977. XB. procmail will concatenate any headers that were continued according to
  978. X   the RCF 822 recommendations, i.e. your filters will see one line per header.
  979. X
  980. XC. procmail can be told to send the header, the body or both through the
  981. X   filter, hence your filter need not watch out to avoid doing any
  982. X   substitutions in the body, and the filter can therefore be a lot simpler.
  983. X
  984. XProcmail has some additional advantages too:
  985. X
  986. X -- It will probably all go a bit faster, since only the header of the mail
  987. X    is being piped through the filter.    Also, procmail reads in the mail in
  988. X    16KB chunks, not line by line as sed does.
  989. X
  990. X -- You could use procmail to filter out any messages to the normal mailing
  991. X    list that should have gone to the mylist-request and remail them to
  992. X    mylist-request.
  993. X
  994. XWell, anyway, as you see, procmail does not give you everything you would want,
  995. Xbut this was intentional in accordance to the true VNIX spirit (modularity).
  996. XWhat procmail does provide is a *very* reliable hook (you might say it
  997. Xprovides an anchor :-) for any mail processing you might do.  For the more
  998. Xcomplex things you still have to use shell scripts or call other programs
  999. Xfrom within procmail, but then again, that saves you from learning any
  1000. Xparticular syntax procmail would have had to do the same.
  1001. X
  1002. XAs it happens, the accompanying formail program is able to cater to most
  1003. X(if not all) of your needs regarding mail munging.
  1004. X
  1005. XIf, on the other hand, you want to do more complex things like moderated
  1006. Xmailing lists with several moderators, etc., if would suggest you take
  1007. Xa look at the more complex/specialised mail-server packages like:
  1008. Xlistserv available on cs.bu.edu, author: tasos@cs.bu.edu
  1009. XOf course, most of what these packages can do, can be done with procmail as
  1010. Xwell; it is just that you might be forced to write some additional shell
  1011. Xscripts/programs to accomplish the same.
  1012. X
  1013. X
  1014. X6. How do I use procmail to filter the mailinglist mail?
  1015. X   -----------------------------------------------------
  1016. X
  1017. XFirst you have to create these two entries in your /usr/lib/aliases file of
  1018. Xmachine "your.domain" (the mylist: line should be typed in as one long line):
  1019. X
  1020. Xmylist: "|IFS=' ';exec /usr/local/bin/procmail /some/path/listrc subscribers=/some/path/memberlist list=mylist@your.domain listreq=mylist-request@your.domain"
  1021. Xmylist-request: your_login_name@your.domain
  1022. Xowner-mylist: mylist-request
  1023. X
  1024. XCreate a file named /some/path/memberlist which contains the names of the
  1025. Xsubscribers separated by whitespace (blanks, tabs or newlines) like:
  1026. X
  1027. X fred john  wilma  barney@bedrock  pebbles
  1028. X
  1029. XThe /some/path/listrc file should look like the sample listrc file
  1030. Xsupplied in this directory.  This listrc file need only be present once,
  1031. Xit will cater for all the mailinglists you'd like to create.
  1032. X
  1033. X
  1034. X7. Now, what does the above all do?
  1035. X   --------------------------------
  1036. X
  1037. XIf mail arrives at mylist, first of all procmail will be started using
  1038. X/some/path/listrc as the rcfile.  Then it will grep the header to check if
  1039. Xit could be a bounced message after all (from postmaster or mailer-daemon),
  1040. Xor if it probably is a request message.     If neither applies, procmail will
  1041. Xfilter just the header of the message through formail.
  1042. X
  1043. Xformail will remove any "Return-Receipt-To:" fields, and will provide plain
  1044. Xsubstitutes for "Errors-To:" and "Sender:".  Then it will look for
  1045. Xany "Reply-To:" fields which are already in the header and rewrite them
  1046. Xas "Old-Reply-To:";  after having done this it will add your "Reply-To:"
  1047. Xfield.    BTW, the "Return-Receipt-To:" and "Errors-To:" fields are not
  1048. Xrecommended by the RFC-822, they are however commonly supported by most
  1049. Xsendmails;  if they are not supported however, they won't hurt, they will
  1050. Xsimply be ignored.
  1051. X
  1052. XThen, the mail is piped into $SENDMAIL which receives, as command line
  1053. Xarguments, the addresses of all subscribers.  The option -f will only
  1054. Xtake effect if sendmail is running under daemon privileges; this only
  1055. Xoccurs if the sender of the mail is *not* a local user; if the sender
  1056. Xis a local user, then sendmail (and procmail) runs as the local user.
  1057. X
  1058. X*********************************** WARNING **********************************
  1059. X*                                         *
  1060. X* For this reason it might be wise to allow writing of the memberlist file   *
  1061. X* only (to a list maintainer), keep the listrc file under *root supervision* *
  1062. X* (i.e. owned by a very reliable person (e.g. root), world readable, but NOT *
  1063. X* world writeable).                                 *
  1064. X*                                         *
  1065. X******************************************************************************
  1066. X
  1067. X
  1068. X8. The result of this exercise
  1069. X   ---------------------------
  1070. X
  1071. XAs you can see, we have addressed and solved every single one of the original
  1072. Xseven problems (well, ok, except problem f, that one is left as an excercise
  1073. Xto the reader; shouldn't be too difficult).
  1074. X
  1075. X
  1076. XP.S. Any suggestions/corrections/improvements on this document are welcome.
  1077. END_OF_FILE
  1078. if test 11170 -ne `wc -c <'procmail/examples/mailinglist'`; then
  1079.     echo shar: \"'procmail/examples/mailinglist'\" unpacked with wrong size!
  1080. fi
  1081. # end of 'procmail/examples/mailinglist'
  1082. fi
  1083. if test -f 'procmail/regexp.c' -a "${1}" != "-c" ; then 
  1084.   echo shar: Will not clobber existing file \"'procmail/regexp.c'\"
  1085. else
  1086. echo shar: Extracting \"'procmail/regexp.c'\" \(10571 characters\)
  1087. sed "s/^X//" >'procmail/regexp.c' <<'END_OF_FILE'
  1088. X/************************************************************************
  1089. X *    Custom regular expression library, *fully* egrep compatible    *
  1090. X *                                    *
  1091. X *    Seems to be relatively bug free.                *
  1092. X *                                    *
  1093. X *    Copyright (c) 1991-1992, S.R. van den Berg, The Netherlands    *
  1094. X *    The sources can be freely copied for non-commercial use.    *
  1095. X *    #include "README"                        *
  1096. X *                                    *
  1097. X ************************************************************************/
  1098. X#ifdef RCS
  1099. Xstatic char rcsid[]="$Id: regexp.c,v 2.13 1992/03/06 12:38:31 berg Rel $";
  1100. X#endif
  1101. X#include "config.h"
  1102. X#include "procmail.h"
  1103. X#include "shell.h"
  1104. X
  1105. X#define R_BEG_GROUP    '('
  1106. X#define R_OR        '|'
  1107. X#define R_END_GROUP    ')'
  1108. X#define R_0_OR_MORE    '*'
  1109. X#define R_0_OR_1    '?'
  1110. X#define R_1_OR_MORE    '+'
  1111. X#define R_DOT        '.'
  1112. X#define R_SOL        '^'
  1113. X#define R_EOL        '$'
  1114. X#define R_BEG_CLASS    '['
  1115. X#define R_NOT_CLASS    '^'
  1116. X#define R_RANGE        '-'
  1117. X#define R_END_CLASS    ']'
  1118. X#define R_ESCAPE    '\\'
  1119. X
  1120. X#define BITS_P_CHAR        8
  1121. X#define OPB            (1<<BITS_P_CHAR)
  1122. X#define OPC_EPS            OPB
  1123. X#define OPC_CLASS        (OPB+1)
  1124. X#define OPC_DOT            (OPB+2)
  1125. X#define OPC_FIN            (OPB+3)
  1126. X
  1127. X#define bit_type        unsigned
  1128. X#define bit_bits        (sizeof(bit_type)*8)
  1129. X#define bit_index(which)    ((unsigned)(which)/bit_bits)
  1130. X#define bit_mask(which)        ((unsigned)1<<(unsigned)(which)%bit_bits)
  1131. X#define bit_toggle(name,which)    (name[bit_index(which)]^=bit_mask(which))
  1132. X#define bit_test(name,which)    (!!(name[bit_index(which)]&bit_mask(which)))
  1133. X#define bit_set(name,which,value)    \
  1134. X (value?(name[bit_index(which)]|=bit_mask(which)):\
  1135. X (name[bit_index(which)]&=~bit_mask(which)))
  1136. X#define bit_field(name,size)    bit_type name[((size)+bit_bits-1)/bit_bits]
  1137. X
  1138. X#define SZ(x)        (sizeof(struct x))
  1139. X#define Ceps        (struct eps*)
  1140. X#define epso(to,add)    (Ceps((char*)(to)+(add)))
  1141. X#define ii        (aleps.topc)
  1142. X#define jjp        (aleps.tnext)
  1143. X
  1144. X/* the spawn and stack members are reused in the normal opcodes as pc fields */
  1145. Xstatic struct eps{unsigned opc;struct eps*stack,*spawn,*next;}*r;
  1146. Xstatic struct{unsigned topc;struct eps*tnext;}aleps;
  1147. Xstatic uchar*p;
  1148. Xstatic ignore_case;
  1149. X
  1150. Xstruct chclass {unsigned opc_;struct eps*stack_,*spawn_,*next_;
  1151. X bit_field(c,OPB);};
  1152. X
  1153. Xstatic puteps(spot,to,aswell)struct eps*const spot;    /* epsilon transition */
  1154. X const struct eps*const to,*const aswell;
  1155. X{ spot->opc=OPC_EPS;spot->next=to!=spot?Ceps to:Ceps aswell;
  1156. X  spot->spawn=aswell!=spot?Ceps aswell:Ceps to;spot->stack=0;
  1157. X}
  1158. X
  1159. Xstatic putneps(spot,to)struct eps*const spot;const struct eps*const to;
  1160. X{ puteps(spot,to,spot+1);
  1161. X}
  1162. X
  1163. X#define rAc    (((struct chclass*)r)->c)
  1164. X
  1165. Xstatic bseti(i,j)unsigned i;const int j;
  1166. X{ bit_set(rAc,i,j);               /* mark 'i' as being in the class */
  1167. X  if(ignore_case)                  /* mark the other case too */
  1168. X   { if(i-'A'<26)                        /* uppercase */
  1169. X    i+='a'-'A';
  1170. X     else if(i-'a'<26)                        /* lowercase */
  1171. X    i-='a'-'A';
  1172. X     else return;                          /* no case */
  1173. X     bit_set(rAc,i,j);
  1174. X   }
  1175. X}
  1176. X
  1177. Xstatic por();
  1178. X
  1179. Xstatic psimp(e)const struct eps*const e;
  1180. X{ switch(*p)
  1181. X   { case R_BEG_GROUP:++p;por(e);return;      /* not so simple after all */
  1182. X     case R_BEG_CLASS:                       /* a simple class */
  1183. X      { unsigned i,j=R_NOT_CLASS==*++p;
  1184. X    if(e)
  1185. X     { r->opc=OPC_CLASS;r->next=Ceps e;r->spawn=r->stack=0;
  1186. X       i=maxindex(rAc);
  1187. X       do rAc[i]=j?~0:0;                 /* preset the bit field */
  1188. X       while(i--);
  1189. X     }
  1190. X    if(j)                      /* skip the 'not' modifier */
  1191. X     { ++p;
  1192. X       if(e)
  1193. X          bit_toggle(rAc,'\n');
  1194. X     }
  1195. X    if(*p==R_END_CLASS)      /* right at the start, cannot mean the end */
  1196. X     { ++p;
  1197. X       if(e)
  1198. X          i=R_END_CLASS,bit_toggle(rAc,R_END_CLASS);
  1199. X     }
  1200. X    else if(*p==R_RANGE)                /* take it literally */
  1201. X     { ++p;
  1202. X       if(e)
  1203. X          i=R_RANGE,bit_toggle(rAc,R_RANGE);
  1204. X     }
  1205. X    for(;;++p)
  1206. X     { switch(*p)
  1207. X        { case R_END_CLASS:++p;
  1208. X          case '\0':r=epso(r,SZ(chclass));return;
  1209. X          case R_RANGE:
  1210. X         switch(*++p)
  1211. X          { default:
  1212. X               if(e)
  1213. X              while(++i<*p)            /* mark all in the range */
  1214. X                 bseti(i,!j);
  1215. X               break;
  1216. X            case '\0':case R_END_CLASS:--p;        /* literally */
  1217. X          }
  1218. X        }
  1219. X       if(e)
  1220. X          bseti(i= *p,!j);              /* a normal character, mark it */
  1221. X     }
  1222. X      }
  1223. X     case '\0':return;
  1224. X     case R_DOT:             /* matches everything but a newline */
  1225. X    if(e)
  1226. X     { r->opc=OPC_DOT;goto fine;
  1227. X     }
  1228. X    goto fine2;
  1229. X     case R_EOL:case R_SOL:              /* match a newline (in effect) */
  1230. X    if(e)
  1231. X     { r->opc='\n';goto fine;
  1232. X     }
  1233. X    goto fine2;
  1234. X     case R_ESCAPE:                      /* quote something */
  1235. X    if(!*++p)                     /* nothing to quote */
  1236. X       --p;
  1237. X   }
  1238. X  if(e)                              /* a regular character */
  1239. X   { r->opc=ignore_case&&(unsigned)*p-'A'<26?*p+'a'-'A':*p;
  1240. Xfine:
  1241. X     r->next=Ceps e;r->spawn=r->stack=0;
  1242. X   }
  1243. Xfine2:
  1244. X  ++p;++r;
  1245. X}
  1246. X
  1247. X#define EOS(x)    (jjp?jjp:(x))
  1248. X
  1249. Xstatic pnorm(e)const struct eps*const e;
  1250. X{ void*pold;struct eps*rold;
  1251. X  for(;;)
  1252. X   { pold=p;rold=r;psimp(Ceps 0);ii= *p;            /* skip it first */
  1253. X     jjp=p[1]==R_OR||p[1]==R_END_GROUP||!p[1]?Ceps e:Ceps 0;
  1254. X     if(e)
  1255. X    p=pold,pold=r;
  1256. X     switch(ii)               /* check for any of the postfix operators */
  1257. X      { case R_0_OR_MORE:++r;
  1258. X       if(e)              /* first an epsilon, then the rest */
  1259. X          putneps(rold,EOS(r)),r=rold+1,psimp(rold);
  1260. X       goto incagoon;
  1261. X    case R_1_OR_MORE:                   /* first the rest */
  1262. X       if(e)                      /* and then an epsilon */
  1263. X          puteps(r,rold,EOS(r+1)),r=rold,psimp(Ceps pold);
  1264. X       ++r;goto incagoon;
  1265. X    case R_0_OR_1:++r;
  1266. X       if(e)              /* first an epsilon, then the rest */
  1267. X          putneps(rold,r=EOS(r)),pold=r,r=rold+1,psimp(Ceps pold);
  1268. Xincagoon:  switch(*++p)            /* at the end of this group already? */
  1269. X        { case R_OR:case R_END_GROUP:case '\0':return;
  1270. X        }
  1271. X       continue;                 /* regular end of the group */
  1272. X    case R_OR:case R_END_GROUP:case '\0':
  1273. X       if(e)
  1274. X          r=rold,psimp(e);
  1275. X       return;
  1276. X      }
  1277. X     if(e)            /* no fancy postfix operators, plain vanilla */
  1278. X    r=rold,psimp(Ceps pold);
  1279. X   }
  1280. X}
  1281. X
  1282. Xstatic por(e)const struct eps*const e;
  1283. X{ uchar*pold;struct eps*rold;
  1284. X  for(;;)
  1285. X     for(pold=p;;)
  1286. X      { rold=r;
  1287. X    switch(*p)
  1288. X     { default:pnorm(Ceps 0);r=rold;continue;     /* still in this group */
  1289. X       case '\0':case R_END_GROUP:           /* found the end of the group */
  1290. X          if(p==pold)                 /* empty 'or' group */
  1291. X           { if(e)
  1292. X            puteps(r,e,e);           /* misused epsilon as branch, */
  1293. X         ++r;        /* let the optimiser (fillout()) take it out */
  1294. X           }
  1295. X          else
  1296. X         p=pold,pnorm(e);            /* normal last group */
  1297. X          if(*p)
  1298. X         ++p;
  1299. X          return;
  1300. X       case R_OR:++r;
  1301. X          if(p==pold)                 /* empty 'or' group */
  1302. X           { if(e)
  1303. X            putneps(rold,e);              /* special epsilon */
  1304. X           }
  1305. X          else
  1306. X           { p=pold;pnorm(e);          /* normal 'or' group, first an */
  1307. X         if(e)                   /* epsilon, then the rest */
  1308. X            putneps(rold,r);
  1309. X           }
  1310. X          ++p;
  1311. X     }
  1312. X    break;
  1313. X      }
  1314. X}
  1315. X
  1316. Xstatic findandrep(old,newv)register struct eps**const old;
  1317. X struct eps*const newv;
  1318. X{ register struct eps*i,*t= *old;               /* save the value */
  1319. X  for(i=r;i->opc!=OPC_FIN;)         /* change all pointers from *old to new */
  1320. X   { if(i->next==t)
  1321. X    i->next=newv;
  1322. X     if(i->spawn==t)
  1323. X    i->spawn=newv;
  1324. X     switch(i->opc)
  1325. X      { case OPC_CLASS:i=epso(i,SZ(chclass));break;
  1326. X    default:++i;
  1327. X      }
  1328. X   }
  1329. X  *old=t;
  1330. X}
  1331. X
  1332. X#define drs(m)    (*(struct eps**)((char*)*stack+(ioffsetof(struct eps,m)^ofs)))
  1333. X
  1334. Xstatic cstack(stack,ofs)struct eps**const stack;
  1335. X{ if(drs(next)->stack==Ceps p)
  1336. X   { findandrep(*stack,drs(next));*stack=drs(spawn);return 1;
  1337. X   }
  1338. X  return 0;
  1339. X}
  1340. X    /* break up any closed epsilon circles, otherwise they can't be executed */
  1341. Xstatic fillout(stack)struct eps**const stack;
  1342. X{ if((*stack)->opc!=OPC_EPS||(*stack)->stack)
  1343. X     return 0;
  1344. X  (*stack)->stack=Ceps p;                /* mark this one as used */
  1345. X#define RECURS(nxt)    \
  1346. X  do\
  1347. X     if(cstack(stack,ioffsetof(struct eps,nxt)^ioffsetof(struct eps,next)))\
  1348. X    return 1;\
  1349. X  while(fillout(&(*stack)->nxt))
  1350. X  RECURS(next);RECURS(spawn);return 0;                  /* recurse */
  1351. X}
  1352. X
  1353. Xvoid*bregcomp(a,ign_case)char const*a;
  1354. X{ struct eps*st;size_t i;      /* first a trial run, determine memory needed */
  1355. X  p=(uchar*)a;ignore_case=ign_case;r=Ceps&aleps+1;por(Ceps 0);
  1356. X  st=malloc((i=(char*)r-(char*)&aleps)+ioffsetof(struct eps,stack)+sizeof r);
  1357. X  putneps(st,r=st+1);p=(uchar*)a;por(Ceps((char*)st+i));   /* really compile */
  1358. X  r->opc=OPC_FIN;r->stack=0;                  /* tack on the end */
  1359. X  for(r=st;;)                 /* simplify the compiled code (i.e. */
  1360. X     switch(st->opc)              /* take out cyclic epsilon references) */
  1361. X      { case OPC_FIN:return r;                     /* finished */
  1362. X    case OPC_CLASS:st=epso(st,SZ(chclass));break;             /* skip */
  1363. X    case OPC_EPS:p=(uchar*)st;fillout(&st);               /* check tree */
  1364. X    default:++st;                         /* skip too */
  1365. X      }
  1366. X}
  1367. X
  1368. X#define XOR1        \
  1369. X (ioffsetof(struct eps,spawn)^ioffsetof(struct eps,stack))
  1370. X#define PC(this,t)    (*(struct eps**)((char*)(this)+(t)))
  1371. X
  1372. Xchar*bregexec(code,text,len,ign_case)struct eps*code;const uchar*text;
  1373. X size_t len;
  1374. X{ register struct eps*reg,*t,*stack,*other,*thiss;unsigned i,th1,ot1;
  1375. X  if(code[1].opc==OPC_EPS)
  1376. X     ++code;           /* two epsilons at the start would be superfluous */
  1377. X  (thiss=code)->stack=0;th1=ioffsetof(struct eps,spawn);
  1378. X  ot1=ioffsetof(struct eps,stack);--text;++len;
  1379. X  i='\n';goto setups;          /* make sure any beginning-of-line-hooks catch */
  1380. X  do
  1381. X   { i= *++text;             /* get the next real-text character */
  1382. Xlastrun:                     /* switch this & other pc-stack */
  1383. X     th1^=XOR1;ot1^=XOR1;thiss=other;
  1384. Xsetups:
  1385. X     reg=(other=stack=code)->next;goto nostack;
  1386. X     do                     /* pop next entry off this pc-stack */
  1387. X      { reg=(t=thiss)->next;thiss=PC(t,th1);PC(t,th1)=0;goto nostack;
  1388. X    do                /* pop next entry off the work-stack */
  1389. X     { stack=(t=stack)->stack;t->stack=0;reg=t->spawn;
  1390. Xnostack:   switch(reg->opc-OPB)        /* push spawned branch on the work-stack */
  1391. X        { default:
  1392. X         if(ign_case&&i-'A'<26)
  1393. X            i+='a'-'A';             /* transmogrify it to lowercase */
  1394. X         if(i==reg->opc)          /* regular character match */
  1395. X            goto yep;
  1396. X         break;
  1397. X          case OPC_EPS-OPB:reg->stack=stack;reg=(stack=reg)->next;
  1398. X         goto nostack;
  1399. X          case OPC_FIN-OPB:           /* hurray!  complete regexp match */
  1400. X         return(char*)text;        /* return one past the match */
  1401. X          case OPC_CLASS-OPB:
  1402. X         if(bit_test(((struct chclass*)reg)->c,i))
  1403. X            goto yep;                   /* character in class */
  1404. X         break;
  1405. X          case OPC_DOT-OPB:                     /* dot-wildcard */
  1406. X         if(i!='\n')
  1407. Xyep:            if(!PC(reg,ot1))             /* state not yet pushed */
  1408. X               PC(reg,ot1)=other,other=reg;    /* push location onto */
  1409. X        }                           /* other pc-stack */
  1410. X     }
  1411. X    while(stack);                  /* the work-stack is not empty */
  1412. X      }
  1413. X     while(thiss!=code);               /* this pc-stack is not empty */
  1414. X   }
  1415. X  while(--len);                         /* still text to search */
  1416. X  if(ign_case!=2)                          /* out of text */
  1417. X   { ign_case=2;len=1;++text;goto lastrun;     /* check if we just matched */
  1418. X   }
  1419. X  return 0;                             /* no match */
  1420. X}
  1421. END_OF_FILE
  1422. if test 10571 -ne `wc -c <'procmail/regexp.c'`; then
  1423.     echo shar: \"'procmail/regexp.c'\" unpacked with wrong size!
  1424. fi
  1425. # end of 'procmail/regexp.c'
  1426. fi
  1427. if test -f 'procmail/strpbrk.h' -a "${1}" != "-c" ; then 
  1428.   echo shar: Will not clobber existing file \"'procmail/strpbrk.h'\"
  1429. else
  1430. echo shar: Extracting \"'procmail/strpbrk.h'\" \(96 characters\)
  1431. sed "s/^X//" >'procmail/strpbrk.h' <<'END_OF_FILE'
  1432. X/*$Id: strpbrk.h,v 1.1 1992/04/16 12:57:55 berg Rel $*/
  1433. X#ifdef NOstrpbrk
  1434. Xchar*strpbrk();
  1435. X#endif
  1436. END_OF_FILE
  1437. if test 96 -ne `wc -c <'procmail/strpbrk.h'`; then
  1438.     echo shar: \"'procmail/strpbrk.h'\" unpacked with wrong size!
  1439. fi
  1440. # end of 'procmail/strpbrk.h'
  1441. fi
  1442. echo shar: End of archive 3 \(of 5\).
  1443. cp /dev/null ark3isdone
  1444. MISSING=""
  1445. for I in 1 2 3 4 5 ; do
  1446.     if test ! -f ark${I}isdone ; then
  1447.     MISSING="${MISSING} ${I}"
  1448.     fi
  1449. done
  1450. if test "${MISSING}" = "" ; then
  1451.     echo You have unpacked all 5 archives.
  1452.     rm -f ark[1-9]isdone
  1453. else
  1454.     echo You still need to unpack the following archives:
  1455.     echo "        " ${MISSING}
  1456. fi
  1457. ##  End of shell archive.
  1458. exit 0
  1459. -- 
  1460. Sincerely,                                  berg@pool.informatik.rwth-aachen.de
  1461.            Stephen R. van den Berg (AKA BuGless).    berg@physik.tu-muenchen.de
  1462.  
  1463. "I have a *cunning* plan!"
  1464.  
  1465. exit 0 # Just in case...
  1466.