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

  1. Newsgroups: comp.sources.misc
  2. From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  3. Subject:  v29i093:  procmail - mail processing program v2.70, Part04/05
  4. Message-ID: <1992May11.151639.29141@sparky.imd.sterling.com>
  5. X-Md4-Signature: b0fd81307060d9fbdb8c81a6d3817fbd
  6. Date: Mon, 11 May 1992 15:16:39 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 93
  11. Archive-name: procmail/part04
  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 4 (of 5)."
  22. # Contents:  procmail/examples/1rmail procmail/goodies.c
  23. #   procmail/man/procmail.man procmail/man/procmailrc.man
  24. #   procmail/retint.c
  25. # Wrapped by berg@drunol on Thu Apr 30 13:42:58 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'procmail/examples/1rmail' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'procmail/examples/1rmail'\"
  29. else
  30. echo shar: Extracting \"'procmail/examples/1rmail'\" \(400 characters\)
  31. sed "s/^X//" >'procmail/examples/1rmail' <<'END_OF_FILE'
  32. X#!/bin/sh
  33. X#
  34. X# specify the mailbox file you want to read on the command line
  35. X#
  36. XMAILDIR=$HOME/Mail
  37. Xcd $MAILDIR
  38. XLOCKFILE=$HOME/.lockmail
  39. Xif lockfile -! -r1 $LOCKFILE
  40. Xthen
  41. X echo Mail is currently arriving, please wait...
  42. X while
  43. X   lockfile -! -4 -r2 $LOCKFILE
  44. X do
  45. X echo Mail is still arriving...
  46. X done
  47. Xfi
  48. Xtrap "rm -f $LOCKFILE;exit 0" 0 1 2 3 15
  49. X#
  50. X# Call you favourite mailer here.
  51. X#
  52. X/usr/ucb/mail -f $*
  53. END_OF_FILE
  54. if test 400 -ne `wc -c <'procmail/examples/1rmail'`; then
  55.     echo shar: \"'procmail/examples/1rmail'\" unpacked with wrong size!
  56. fi
  57. # end of 'procmail/examples/1rmail'
  58. fi
  59. if test -f 'procmail/goodies.c' -a "${1}" != "-c" ; then 
  60.   echo shar: Will not clobber existing file \"'procmail/goodies.c'\"
  61. else
  62. echo shar: Extracting \"'procmail/goodies.c'\" \(9144 characters\)
  63. sed "s/^X//" >'procmail/goodies.c' <<'END_OF_FILE'
  64. X/************************************************************************
  65. X *    Collection of library-worthy routines                *
  66. X *                                    *
  67. X *    Copyright (c) 1990-1992, S.R. van den Berg, The Netherlands    *
  68. X *    The sources can be freely copied for non-commercial use.    *
  69. X *    #include "README"                        *
  70. X *                                    *
  71. X ************************************************************************/
  72. X#ifdef RCS
  73. Xstatic char rcsid[]="$Id: goodies.c,v 2.16 1992/04/09 16:16:41 berg Rel $";
  74. X#endif
  75. X#include "config.h"
  76. X#include "procmail.h"
  77. X#include "shell.h"
  78. X
  79. X#define NOTHING_YET    (-1)    /* readparse understands a very complete    */
  80. X#define SKIPPING_SPACE    0    /* subset of the standard /bin/sh syntax    */
  81. X#define NORMAL_TEXT    1    /* that includes single-, double- and back- */
  82. X#define DOUBLE_QUOTED    2    /* quotes, backslashes and $subtitutions    */
  83. X#define SINGLE_QUOTED    3
  84. X
  85. X/* sarg==0 : normal parsing, split up arguments like in /bin/sh
  86. X * sarg==1 : environment assignment parsing, parse up till first whitespace
  87. X * sarg==2 : normal parsing, split up arguments by single spaces
  88. X */
  89. Xreadparse(p,fgetc,sarg)register char*p;int(*const fgetc)();const int sarg;
  90. X{ static i;int got;char*startb;
  91. X  for(got=NOTHING_YET;;)            /* buf2 is used as scratch space */
  92. Xloop:
  93. X   { i=fgetc();
  94. X     if(buf+linebuf-3<p)        /* doesn't catch everything, just a hint */
  95. X      { log("Exceeded LINEBUF\n");p=buf+linebuf-3;goto ready;
  96. X      }
  97. Xnewchar:
  98. X     switch(i)
  99. X      { case EOF:    /* check sarg too to prevent warnings in the recipe- */
  100. X       if(sarg!=2&&got>NORMAL_TEXT)         /* condition expansion code */
  101. Xearly_eof:    log(unexpeof);
  102. Xready:       if(got!=SKIPPING_SPACE||sarg)  /* not terminated yet or sarg==2 ? */
  103. X          *p++='\0';
  104. X       *p=TMNATE;return;
  105. X    case '\\':
  106. X       if(got==SINGLE_QUOTED)
  107. X          break;
  108. X       switch(i=fgetc())
  109. X        { case EOF:goto early_eof;              /* can't quote EOF */
  110. X          case '\n':continue;            /* concatenate lines */
  111. X          case '#':
  112. X         if(got>SKIPPING_SPACE) /* escaped comment at start of word? */
  113. X            goto noesc;            /* apparently not, literally */
  114. X          case ' ':case '\t':case '\'':
  115. X         if(got==DOUBLE_QUOTED)
  116. X            goto noesc;
  117. X          case '"':case '\\':case '$':case '`':goto nodelim;
  118. X        }
  119. X       if(got>NORMAL_TEXT)
  120. Xnoesc:          *p++='\\';        /* nothing to escape, just echo both */
  121. X       break;
  122. X    case '`':
  123. X       if(got==SINGLE_QUOTED)
  124. X          goto nodelim;
  125. X       for(startb=p;;)                   /* mark your position */
  126. X        { switch(i=fgetc())             /* copy till next backquote */
  127. X           { case '\\':
  128. X            switch(i=fgetc())
  129. X             { case EOF:log(unexpeof);goto forcebquote;
  130. X               case '\n':continue;
  131. X               case '"':
  132. X              if(got!=DOUBLE_QUOTED)
  133. X                 break;
  134. X               case '\\':case '$':case '`':goto escaped;
  135. X             }
  136. X            *p++='\\';break;
  137. X         case '"':
  138. X            if(got!=DOUBLE_QUOTED)    /* missing closing backquote? */
  139. X               break;
  140. Xforcebquote:     case EOF:case '`':
  141. X          { int osh=sh;
  142. X            *p='\0';
  143. X            if(!(sh=!!strpbrk(startb,tgetenv(shellmetas))))
  144. X             { const char*save=sgetcp;
  145. X               sgetcp=p=tstrdup(startb);readparse(startb,sgetc,0);
  146. X               free(p);sgetcp=save;               /* chopped up */
  147. X             }            /* drop source buffer, read from program */
  148. X            startb=fromprog(p=startb,startb);sh=osh;   /* restore sh */
  149. X            if(!sarg&&got!=DOUBLE_QUOTED)
  150. X             { i=0;startb=p;goto simplsplit;          /* split it up */
  151. X             }
  152. X            if(i=='"'||got<=SKIPPING_SPACE)   /* missing closing ` ? */
  153. X               got=NORMAL_TEXT;                 /* or sarg!=0 ? */
  154. X            p=startb;goto loop;
  155. X          }
  156. X         case '\n':i=';';           /* newlines separate commands */
  157. X           }
  158. Xescaped:      *p++=i;
  159. X        }
  160. X    case '"':
  161. X       switch(got)
  162. X        { case DOUBLE_QUOTED:got=NORMAL_TEXT;continue;    /* closing " */
  163. X          case SINGLE_QUOTED:goto nodelim;
  164. X        }
  165. X       got=DOUBLE_QUOTED;continue;                /* opening " */
  166. X    case '\'':
  167. X       switch(got)
  168. X        { case DOUBLE_QUOTED:goto nodelim;
  169. X          case SINGLE_QUOTED:got=NORMAL_TEXT;continue;}    /* closing ' */
  170. X       got=SINGLE_QUOTED;continue;                /* opening ' */
  171. X    case '#':
  172. X       if(got>SKIPPING_SPACE)        /* comment at start of word? */
  173. X          break;
  174. X       while((i=fgetc())!=EOF&&i!='\n');            /* skip till EOL */
  175. X       goto ready;
  176. X    case '$':
  177. X       if(got==SINGLE_QUOTED)
  178. X          break;
  179. X       if(EOF==(i=fgetc()))
  180. X        { *p++='$';goto ready;
  181. X        }
  182. X       startb=buf2;
  183. X       if(i=='{')                          /* ${name} */
  184. X        { while(EOF!=(i=fgetc())&&alphanum(i))
  185. X         *startb++=i;
  186. X          *startb='\0';
  187. X          if(i!='}')
  188. X           { log("Bad substitution of");logqnl(buf2);continue;
  189. X           }
  190. X          i='\0';
  191. X        }
  192. X       else if(alphanum(i))                        /* $name */
  193. X        { do *startb++=i;
  194. X          while(EOF!=(i=fgetc())&&alphanum(i));
  195. X          if(i==EOF)
  196. X         i='\0';
  197. X          *startb='\0';
  198. X        }
  199. X       else if(i=='$')                      /* $$ =pid */
  200. X        { ultstr(0,(unsigned long)thepid,p);goto ieofstr;
  201. X        }
  202. X       else if(i=='-')                   /* $- =lastfolder */
  203. X        { strcpy(p,lastfolder);
  204. Xieofstr:      i='\0';goto eofstr;
  205. X        }
  206. X       else
  207. X        { *p++='$';goto newchar;               /* not a substitution */
  208. X        }
  209. X       startb=(char*)tgetenv(buf2);
  210. X       if(!sarg&&got!=DOUBLE_QUOTED)
  211. Xsimplsplit:   for(;;startb++)          /* simply split it up in arguments */
  212. X           { switch(*startb)
  213. X          { case ' ':case '\t':case '\n':
  214. X               if(got<=SKIPPING_SPACE)
  215. X              continue;
  216. X               *p++='\0';got=SKIPPING_SPACE;continue;
  217. X            case '\0':goto eeofstr;
  218. X          }
  219. X         *p++= *startb;got=NORMAL_TEXT;
  220. X           }
  221. X       else
  222. X        { strcpy(p,startb);                   /* simply copy it */
  223. Xeofstr:          if(got<=SKIPPING_SPACE)        /* can only occur if sarg!=0 */
  224. X         got=NORMAL_TEXT;
  225. X          p=strchr(p,'\0');
  226. X        }
  227. Xeeofstr:   if(i)                 /* already read next character? */
  228. X          goto newchar;
  229. X       continue;
  230. X    case ' ':case '\t':
  231. X       switch(got)
  232. X        { case NORMAL_TEXT:
  233. X         if(sarg==1)
  234. X            goto ready;        /* already fetched a single argument */
  235. X         got=SKIPPING_SPACE;*p++=sarg?' ':'\0';     /* space or \0 sep. */
  236. X          case NOTHING_YET:case SKIPPING_SPACE:continue;    /* skip space */
  237. X        }
  238. X    case '\n':
  239. X       if(got<=NORMAL_TEXT)
  240. X          goto ready;                /* EOL means we're ready */
  241. X      }
  242. Xnodelim:
  243. X     *p++=i;                       /* ah, a normal character */
  244. X     if(got<=SKIPPING_SPACE)         /* should we bother to change mode? */
  245. X    got=NORMAL_TEXT;
  246. X   }
  247. X}
  248. X
  249. Xultstr(minwidth,val,dest)unsigned long val;char*dest;
  250. X{ int i;unsigned long j;
  251. X  j=val;i=0;                       /* a beauty, isn't it :-) */
  252. X  do i++;                       /* determine needed width */
  253. X  while(j/=10);
  254. X  while(--minwidth>=i)                 /* fill up any excess width */
  255. X     *dest++=' ';
  256. X  *(dest+=i)='\0';
  257. X  do *--dest='0'+val%10;              /* display value backwards */
  258. X  while(val/=10);
  259. X}
  260. X
  261. Xsputenv(a)char*a;          /* smart putenv, the way it was supposed to be */
  262. X{ static struct lienv{struct lienv*next;char name[255];}*myenv;
  263. X  static alloced;int i,remove;char*split,**preenv;struct lienv*curr,**last;
  264. X  yell("Assigning",a);remove=0;
  265. X  if(!(split=strchr(a,'=')))               /* assignment or removal? */
  266. X     remove=1,split=strchr(a,'\0');
  267. X  i=split-a;
  268. X  for(curr= *(last= &myenv);curr;curr= *(last= &curr->next))    /* is it one */
  269. X     if(!strncmp(a,curr->name,i)&&curr->name[i]=='=')  /* I created earlier? */
  270. X      { split=curr->name;*last=curr->next;free(curr);
  271. X    for(preenv=environ;*preenv!=split;preenv++);
  272. X    goto wipenv;
  273. X      }
  274. X  for(preenv=environ;*preenv;preenv++)            /* is it in the standard */
  275. X     if(!strncmp(a,*preenv,i)&&(*preenv)[i]=='=')         /* environment? */
  276. Xwipenv:
  277. X      { while(*preenv=preenv[1])   /* wipe this entry out of the environment */
  278. X       preenv++;
  279. X    break;
  280. X      }
  281. X  i=(preenv-environ+2)*sizeof*environ;
  282. X  if(alloced)           /* have we ever alloced the environ array before? */
  283. X     environ=realloc(environ,i);
  284. X  else
  285. X     alloced=1,environ=tmemmove(malloc(i),environ,i-sizeof*environ);
  286. X  if(!remove)          /* if not remove, then add it to both environments */
  287. X   { for(preenv=environ;*preenv;preenv++);
  288. X     curr=malloc(ioffsetof(struct lienv,name[0])+(i=strlen(a)+1));
  289. X     tmemmove(*preenv=curr->name,a,i);preenv[1]=0;curr->next=myenv;
  290. X     myenv=curr;
  291. X   }
  292. X}
  293. X                /* strtol replacement which lacks range checking */
  294. X#ifdef NOstrtol
  295. Xlong strtol(start,ptr,base)const char*start,**const ptr;
  296. X{ long result;const char*str=start;unsigned i;int sign,found;
  297. X  if(base>=36||base<(sign=found=result=0))
  298. X     goto fault;
  299. X  for(;;str++)                      /* skip leading whitespace */
  300. X   { switch(*str)
  301. X      { case '\t':case '\n':case '\v':case '\f':case '\r':case ' ':continue;
  302. X      }
  303. X     break;
  304. X   }
  305. X  switch(*str)                               /* any signs? */
  306. X   { case '-':sign=1;
  307. X     case '+':str++;
  308. X   }
  309. X  if(*str=='0')                         /* leading zero(s)? */
  310. X   { start++;
  311. X     if((i= *++str)=='x'||i=='X')            /* leading 0x or 0X? */
  312. X    if(!base||base==16)
  313. X       base=16,str++;                /* hexadecimal all right */
  314. X    else
  315. X       goto fault;
  316. X     else if(!base)
  317. X    base=8;                         /* then it is octal */
  318. X   }
  319. X  else if(!base)
  320. X     base=10;                          /* or else decimal */
  321. X  goto jumpin;
  322. X  do
  323. X   { found=1;result=result*base+i;++str;         /* start converting */
  324. Xjumpin:
  325. X     if((i= *str-'0')<10);
  326. X     else if(i-'A'+'0'<26)
  327. X    i-='A'-10-'0';
  328. X     else if(i-'a'+'0'<26)
  329. X    i-='a'-10-'0';
  330. X     else
  331. X    break;                        /* not of this world */
  332. X   }
  333. X  while(i<base);                      /* still of this world */
  334. Xfault:
  335. X  if(ptr)
  336. X    *ptr=found?str:start;                   /* how far did we get */
  337. X  return sign?-result:result;
  338. X}
  339. X#endif
  340. END_OF_FILE
  341. if test 9144 -ne `wc -c <'procmail/goodies.c'`; then
  342.     echo shar: \"'procmail/goodies.c'\" unpacked with wrong size!
  343. fi
  344. # end of 'procmail/goodies.c'
  345. fi
  346. if test -f 'procmail/man/procmail.man' -a "${1}" != "-c" ; then 
  347.   echo shar: Will not clobber existing file \"'procmail/man/procmail.man'\"
  348. else
  349. echo shar: Extracting \"'procmail/man/procmail.man'\" \(11722 characters\)
  350. sed "s/^X//" >'procmail/man/procmail.man' <<'END_OF_FILE'
  351. X.de Id
  352. X.ds Rv \\$3
  353. X.ds Dt \\$4
  354. X..
  355. X.Id $Id: procmail.man,v 2.26 1992/04/29 15:55:09 berg Rel $
  356. X.de Sh
  357. X.br
  358. X.ne 11
  359. X.SH "\\$1"
  360. X..
  361. X.de Ss
  362. X.br
  363. X.ne 10
  364. X.SS "\\$1"
  365. X..
  366. X.de Tp
  367. X.br
  368. X.ne 9
  369. X.TP \\$1
  370. X..
  371. X.de Rs
  372. X.na
  373. X.nf
  374. X.RS
  375. X..
  376. X.de Re
  377. X.RE
  378. X.fi
  379. X.ad
  380. X..
  381. X.TH PROCMAIL 1 \*(Dt BuGless
  382. X.SH NAME
  383. X.na
  384. Xprocmail \- autonomous mail processor
  385. X.SH SYNOPSIS
  386. X.B procmail
  387. X.RB [ \-+PRESERVOPT++TEMPFAILOPT+ ]
  388. X.RB [ "\-+FROMWHOPT+ \fIfromwhom\fP" ]
  389. X.RI [ "parameter\fB=\fPvalue " | " rcfile" ]
  390. X\&.\|.\|.
  391. X.br
  392. X.B procmail
  393. X.RB [ \-+PRESERVOPT++TEMPFAILOPT+ ]
  394. X.RB [ "\-+FROMWHOPT+ \fIfromwhom\fP" ]
  395. X.B \-+DELIVEROPT+
  396. X.I recipient
  397. X\&.\|.\|.
  398. X.br
  399. X.B procmail
  400. X.B \-+VERSIONOPT+
  401. X.ad
  402. X.Sh DESCRIPTION
  403. XFor a quick start, see
  404. X.B NOTES
  405. Xat the end.
  406. X.PP
  407. X.B Procmail
  408. Xshould be invoked automatically over the
  409. X.B +DOT_FORWARD+
  410. Xfile mechanism as soon as mail arrives.  Alternatively, when installed by
  411. Xa system administrator, it can be invoked from within the mailer immediately.
  412. XWhen invoked, it first sets some environment variables to default values,
  413. Xreads the mail message from stdin until an EOF, separates the body from the
  414. Xheader, and then, if no command line arguments are present, it starts to look
  415. Xfor a file named
  416. X.B +PROCMAILRC+
  417. Xin your home directory.  According to the processing recipes in this file,
  418. Xthe mail message that just arrived gets distributed into the right folder
  419. X(and more).
  420. X.PP
  421. XIf running suid root or with root priviliges, procmail will be able to
  422. Xperform as a functionally enhanced, backwards compatible mail delivery agent.
  423. X.PP
  424. XThe rcfile format is described in detail in the
  425. X.BR procmailrc (5)
  426. Xman page.
  427. X.PP
  428. XExamples for rcfile recipes can be looked up in the
  429. X.BR procmailex (5)
  430. Xman page.
  431. X.Ss Signals
  432. X.Tp 1.2i
  433. X.B TERMINATE
  434. XTerminate prematurely and requeue the mail.
  435. X.Tp
  436. X.B HANGUP
  437. XTerminate prematurely and bounce the mail.
  438. X.Tp
  439. X.B INTERRUPT
  440. XTerminate prematurely and bounce the mail.
  441. X.Tp
  442. X.B QUIT
  443. XTerminate prematurely and silently lose the mail.
  444. X.Tp
  445. X.B ALARM
  446. XForce a timeout (see
  447. X.BR TIMEOUT).
  448. X.Sh OPTIONS
  449. X.Tp 0.5i
  450. X.B \-+VERSIONOPT+
  451. XProcmail will print its version number and exit.
  452. X.Tp
  453. X.B \-+PRESERVOPT+
  454. XPreserve any old environment.  Normally procmail clears the environment
  455. Xupon startup+KEEPENV+.  However, in any case: any default values will override
  456. Xany preexisting environment variables, i.e. procmail will not pay any attention
  457. Xto any predefined environment variables, it will happily overwrite them
  458. Xwith his own defaults.
  459. X.Tp
  460. X.B \-+TEMPFAILOPT+
  461. XMake procmail fail softly, i.e. if procmail cannot deliver the mail to
  462. Xany of the destinations you gave, the mail will not bounce, but will return
  463. Xto the mailqueue.  Another delivery-attempt will be made at some time in
  464. Xthe future.
  465. X.Tp
  466. X.I "\fB\-+FROMWHOPT+\fP fromwhom"
  467. XCauses procmail to regenerate the leading `+FROM+' line with
  468. X.I fromwhom
  469. Xas the sender (instead of \-+FROMWHOPT+ one could use the alternate and
  470. Xobsolete \-+ALTFROMWHOPT+).
  471. X.Tp
  472. X.I "\fB\-+DELIVEROPT+\fP recipient .\|.\|."
  473. XThis turns on explicit delivery mode, delivery will be to the local user
  474. X.IR recipient .
  475. XThis, of course, only is possible if procmail has root priviliges.
  476. XProcmail will setuid to the intended recipients and shall
  477. X.I only
  478. Xread the recipient's +PROCMAILRC+ file (if present, if not, delivery is like
  479. Xordinary mail).
  480. X.Sh ARGUMENTS
  481. XAny arguments containing an '=' are considered to be environment variable
  482. Xassignments, they will
  483. X.I all
  484. Xbe evaluated after the default values have been
  485. Xassigned and before the first rcfile is opened.
  486. X.PP
  487. XAny other arguments are presumed to be rcfile paths (absolute or relative to
  488. X$HOME); procmail will start with the first one it finds on the command line.
  489. XThe following ones will only be parsed if the preceding ones have a not
  490. Xmatching HOST-directive entry, or in case they should not exist.
  491. X.PP
  492. XIf no rcfiles are specified, it looks for
  493. X.BR $HOME/+PROCMAILRC+ .
  494. XIf not even that can be found, processing will continue according to
  495. Xthe default settings of the environment variables and the ones specified
  496. Xon the command line.
  497. X.Sh CAVEATS
  498. XAny default values that procmail has for some environment variables will
  499. X.B always
  500. Xoverride the ones that were already defined.  If you really want to
  501. Xoverride the defaults, you either have to put them in the
  502. X.B rcfile
  503. Xor in the command line as arguments.
  504. X.Sh FILES
  505. X.Tp 2.3i
  506. X.B /etc/passwd
  507. Xto get the recipient's USER, HOME and SHELL variable defaults
  508. X.Tp
  509. X.B +SYSTEM_MBOX+
  510. Xsystem mailbox
  511. X.Tp
  512. X.B $HOME/+PROCMAILRC+
  513. Xdefault rcfile
  514. X.Tp
  515. X.B +SYSTEM_MBOX++DEFlockext+
  516. Xlockfile for the system mailbox (not used by procmail automatically, unless
  517. X$DEFAULT equals +SYSTEM_MBOX+ and procmail is delivering to $DEFAULT)
  518. X.Tp
  519. X.B +DEFsendmail+
  520. Xdefault mail forwarder
  521. X.Tp
  522. X.B +UNIQ_PREFIX+????`hostname`
  523. Xtemporary `unique' zero-length files created by procmail
  524. X.Sh "SEE ALSO"
  525. X.na
  526. X.BR procmailrc (5),
  527. X.BR procmailex (5),
  528. X.BR sh (1),
  529. X.BR csh (1),
  530. X.BR mail (1),
  531. X.BR binmail (1),
  532. X.BR uucp (1C),
  533. X.BR aliases (5),
  534. X.BR sendmail (8),
  535. X.BR egrep (1V),
  536. X.BR lockfile (1),
  537. X.BR formail (1)
  538. X.ad
  539. X.Sh DIAGNOSTICS
  540. X.Tp 2.3i
  541. XBad substitution of "x"
  542. XNot a valid environment variable name specified.
  543. X.Tp
  544. XCouldn't unlock "x"
  545. XLockfile was already gone, or write permission to the directory were the
  546. Xlockfile is has been denied.
  547. X.Tp
  548. XError while writing to "x"
  549. XNonexistent subdirectory, no write permission, pipe died or disk full.
  550. X.Tp
  551. XExceeded LINEBUF
  552. XBuffer overflow detected, LINEBUF was too small, memory might be corrupted.
  553. X.Tp
  554. XFailed forking "x"
  555. XProcess table is full (and NORESRETRY has been exhausted).
  556. X.Tp
  557. XFailed to execute "x"
  558. XProgram not in path, or not executable.
  559. X.Tp
  560. XForced unlock denied on "x"
  561. XNo write permission in the directory where
  562. X.B lockfile
  563. Xresides, or more than one procmail trying to force a lock at exactly the same
  564. Xtime.
  565. X.Tp
  566. XForcing lock on "x"
  567. XSpecified
  568. X.B lockfile
  569. Xis going to be removed by force because of a timeout (see also:
  570. X.BR LOCKTIMEOUT ).
  571. X.Tp
  572. XLock failure on "x"
  573. XCan only occur if you specify some real weird (and illegal) lockfilenames
  574. Xor if the
  575. X.B lockfile
  576. Xcould not be created because of insufficient permissions or noexistent
  577. Xsubdirectories.
  578. X.Tp
  579. XMissing name
  580. XThe \-+FROMWHOPT+ option needs an extra argument
  581. X.Tp
  582. XMissing recipient
  583. XYou specified the \-+DELIVEROPT+ option or called procmail under a different
  584. Xname, it expects one or more recipients as arguments
  585. X.Tp
  586. XOut of memory
  587. XThe system is out of swap space (and NORESRETY has been exhausted).
  588. X.Tp
  589. XProcessing continued
  590. XThe unrecognised options on the command line are ignored, proceeding as
  591. Xusual.
  592. X.Tp
  593. XProgram failure of "x"
  594. XProgram that was started by procmail didn't return EX_OK (=0).
  595. X.Tp
  596. XSkipped: "x"
  597. XCouldn't do anything with "x" in the rcfile (syntax error), ignoring it.
  598. X.Tp
  599. XTerminating prematurely whilst waiting for .\|.\|.
  600. XProcmail received a signal while it was waiting for .\|.\|.
  601. X.Tp
  602. XTimeout, terminating "x"
  603. XTimeout has occurred on program/filter "x".
  604. X.Tp
  605. XTruncating "x" and retrying lock
  606. X"x" does not seem to be a valid filename or the file is not empty.
  607. X.Tp
  608. XRescue of unfiltered data succeeded/failed
  609. XA filter returned unsuccessfully, procmail tried to get back the original text.
  610. X.Tp
  611. XUnexpected EOL
  612. XMissing closing quote, or trying to escape EOF.
  613. X.Sh "EXTENDED DIAGNOSTICS"
  614. X.Tp 2.3i
  615. XAssigning "x"
  616. XEnvironment variable assignment
  617. X.Tp
  618. XExecuting "x"
  619. XStarting program "x"
  620. X.Tp
  621. XHOST mismatched "x"
  622. XThis host was called "x", HOST contained something else
  623. X.Tp
  624. XLocking "x"
  625. XCreating lockfile "x"
  626. X.Tp
  627. XMatch on "x"
  628. XCondition matched
  629. X.Tp
  630. XNo match on "x"
  631. XCondition didn't match, recipe skipped
  632. X.Tp
  633. XOpening "x"
  634. XOpening file "x" for appending
  635. X.Tp
  636. XRcfile: "x"
  637. XRcfile changed to "x"
  638. X.Tp
  639. XUnlocking "x"
  640. XRemoving lockfile "x" again
  641. X.Sh WARNINGS
  642. XYou should create a shell script that uses
  643. X.BR lockfile (1)
  644. Xbefore invoking your mail shell on any mailbox file other than the system
  645. Xmailbox (unless of course, your mail shell uses the same lockfiles (local
  646. Xor global) you specified in your rcfile).
  647. X.PP
  648. XIn the unlikely event that you absolutely need to kill procmail before it has
  649. Xfinished, first try and use the regular kill command (i.e.
  650. X.I not
  651. Xkill -9, see the subsection
  652. X.I Signals
  653. Xfor suggestions), otherwise some
  654. X.I lockfiles
  655. Xmight not get removed.
  656. X.PP
  657. XBeware when using the
  658. X.B \-+TEMPFAILOPT+
  659. Xoption, if procmail repeatedly is unable to deliver the mail (e.g. due to
  660. Xan incorrect rcfile), the system mailqueue could fill up.  This could
  661. Xaggravate both the local postmaster and other users.
  662. X.Sh BUGS
  663. XAfter a lockfile is removed by force, a suspension of $SUSPEND seconds
  664. Xis taken into account, in order to prevent the inadvertent immediate removal
  665. Xof any newly created lockfile by another program.
  666. X.PP
  667. XProcmail uses the regular TERMINATE signal to terminate any runaway filter,
  668. Xbut it does not check if the filter responds to that signal and it only sends
  669. Xit to the filter itself, not to any of the filter's children.
  670. X.Sh MISCELLANEOUS
  671. XAny lines in the body of the message that look like postmarks are prepended
  672. Xwith `+ESCAP+' (disarms bogus mailheaders).  The regular expression that is
  673. Xused to search for these postmarks is:
  674. X.Rs
  675. X"+FROM_EXPR+"
  676. X.Re
  677. X.PP
  678. XIf the destination name used in explicit delivery mode is not in /etc/passwd,
  679. Xprocmail will proceed as if explicit delivery mode was not in effect.
  680. XIf not in explicit delivery mode and
  681. Xshould the uid procmail is running under, have no corresponding /etc/passwd
  682. Xentry, then HOME will default to +Tmp+, USER will default to #uid.
  683. X.PP
  684. XWhen in explicit delivery mode, procmail will generate a leading `+FROM+'
  685. Xline if none is present.  If one is already present+TRUSTED_IDS+ procmail will
  686. Xleave it intact.
  687. X.PP
  688. XFor security reasons procmail will only use an rcfile if it is owned by the
  689. Xrecipient or if the recipient's home directory is not world writeable.
  690. X.PP
  691. XIf +SYSTEM_MBOX+ is a bogus mailbox (i.e. does not belong to the recipient,
  692. Xis unwritable, is a symbolic link or is a hard link), procmail will upon
  693. Xstartup try to rename it into a file starting with `+BOGUSprefix+' and
  694. Xending in an inode-sequence-code.  If this turns out to be impossible,
  695. X.B ORGMAIL
  696. Xwill have
  697. X.I no
  698. Xinitial value.
  699. X.PP
  700. XWhen delivering to directories (or to MH folders) you
  701. X.B don't
  702. Xneed to use lockfiles to prevent several concurrently running procmail
  703. Xprograms from messing up.
  704. X.PP
  705. XDelivering to MH folders is slightly more time consuming than delivering
  706. Xto normal directories or mailboxes, because procmail has to search for
  707. Xthe first available number (instead of having the filename immediately
  708. Xavailable).
  709. X.PP
  710. XOn general failure procmail will return EX_CANTCREAT, unless option
  711. X.B \-+TEMPFAILOPT+
  712. Xis specified, in which case it will return EX_TEMPFAIL.
  713. X.PP
  714. XTo make `egrepping' of headers more consistent, procmail concatenates all
  715. Xcontinued header fields.
  716. X.PP
  717. XIf procmail is called under a different name than `procmail' (i.e. if it
  718. Xis linked to another name and invoked as such), it comes up in explicit
  719. Xdelivery mode, and expects the recipients' names as command line arguments
  720. X(as if \-+DELIVEROPT+ had been specified).
  721. X.PP
  722. XProcmail performs the locking in an NFS-secure way.
  723. X.br
  724. X.ne 11
  725. X.Sh NOTES
  726. XIf procmail is
  727. X.I not
  728. Xinstalled globally as the default mail delivery agent (ask your system
  729. Xadministrator), you have to make sure it is invoked when your mail arrives.
  730. XIn this case your $HOME/+DOT_FORWARD+ (beware, it
  731. X.B has
  732. Xto be world readable) file should contain (include the single and double
  733. Xquotes,
  734. X.I must
  735. Xbe an
  736. X.I absolute
  737. Xpath):
  738. X.PP
  739. X.na
  740. X.nf
  741. X+FW_content+
  742. X.fi
  743. X.ad
  744. X.br
  745. X.ne 14
  746. X.Ss "A sample small +PROCMAILRC+:"
  747. X.na
  748. X.nf
  749. XPATH=/bin:/usr/bin:/usr/local/bin
  750. XMAILDIR=$HOME/Mail      #you'd better make sure it exists
  751. XDEFAULT=$MAILDIR/mbox
  752. XLOGFILE=$MAILDIR/from
  753. X::
  754. X^From.*berg
  755. Xfrom_me
  756. X:
  757. X^Subject:.*Flame
  758. X/dev/null
  759. X.fi
  760. X.ad
  761. X.Sh AUTHOR
  762. XStephen R. van den Berg at RWTH-Aachen, Germany
  763. X.Rs
  764. Xberg@pool.informatik.rwth-aachen.de
  765. Xberg@physik.tu-muenchen.de
  766. X.Re
  767. END_OF_FILE
  768. if test 11722 -ne `wc -c <'procmail/man/procmail.man'`; then
  769.     echo shar: \"'procmail/man/procmail.man'\" unpacked with wrong size!
  770. fi
  771. # end of 'procmail/man/procmail.man'
  772. fi
  773. if test -f 'procmail/man/procmailrc.man' -a "${1}" != "-c" ; then 
  774.   echo shar: Will not clobber existing file \"'procmail/man/procmailrc.man'\"
  775. else
  776. echo shar: Extracting \"'procmail/man/procmailrc.man'\" \(14618 characters\)
  777. sed "s/^X//" >'procmail/man/procmailrc.man' <<'END_OF_FILE'
  778. X.de Id
  779. X.ds Rv \\$3
  780. X.ds Dt \\$4
  781. X..
  782. X.Id $Id: procmailrc.man,v 2.5 1992/04/29 15:55:09 berg Rel $
  783. X.de Sh
  784. X.br
  785. X.ne 11
  786. X.SH "\\$1"
  787. X..
  788. X.de Ss
  789. X.br
  790. X.ne 10
  791. X.SS "\\$1"
  792. X..
  793. X.de Tp
  794. X.br
  795. X.ne 9
  796. X.TP \\$1
  797. X..
  798. X.de Rs
  799. X.na
  800. X.nf
  801. X.RS
  802. X..
  803. X.de Re
  804. X.RE
  805. X.fi
  806. X.ad
  807. X..
  808. X.TH PROCMAILRC 5 \*(Dt BuGless
  809. X.SH NAME
  810. X.na
  811. Xprocmailrc \- procmail rcfile
  812. X.SH SYNOPSIS
  813. X.B $HOME/+PROCMAILRC+
  814. X.ad
  815. X.Sh DESCRIPTION
  816. XFor a quick start, see
  817. X.B NOTES
  818. Xat the end of the
  819. X.BR procmail (1)
  820. Xman page.
  821. X.PP
  822. XThe rcfile can contain a mixture of environment variable assignments (some
  823. Xof which have special meanings to procmail), and recipes.  In their most
  824. Xsimple appearance, the recipes are simply one line regular expressions
  825. Xthat are searched for in the header of the arriving mail, the first recipe
  826. Xthat matches is used to determine where the mail has to go (usually a file).
  827. X.PP
  828. XThis enables you to presort your mail extremely straightforward into several
  829. Xmailfolders.  Bear in mind though that the mail can arrive concurrently in
  830. Xthese mailfolders, to make sure this does not result in a mess, proper use
  831. Xof lockfiles is highly recommended.
  832. X.PP
  833. XThe environment variable
  834. X.B assignments
  835. Xand
  836. X.B recipes
  837. Xcan be freely intermixed in the rcfile. If any environment variable has
  838. Xa special meaning to procmail, it will be used appropiately the moment
  839. Xit is parsed. (i.e. you can change the current directory whenever you
  840. Xwant by specifying a new
  841. X.BR MAILDIR ,
  842. Xswitch lockfiles by specifying a new
  843. X.BR LOCKFILE ,
  844. Xchange the umask at any time, etc., the possibilities are endless :-).
  845. X.PP
  846. XThe assignments and substitutions of these environment variables are handled
  847. Xexactly like in
  848. X.BR sh (1)
  849. X(that includes all possible quotes and escapes),
  850. Xwith the added bonus that blanks around the '=' sign are ignored and that,
  851. Xif an environment variable appears without a trailing '=', it will be
  852. Xremoved from the environment.
  853. X.PP
  854. X.Ss Comments
  855. XA word beginning with # and all the following characters up to a NEWLINE
  856. Xare ignored.
  857. X.Ss Recipes
  858. X.PP
  859. XA line starting with ':' marks the beginning of a recipe.  It has the
  860. Xfollowing format:
  861. X.PP
  862. X.Rs
  863. X: [\fInumber\fP] [\fIflags\fP] [ : [\fIlocallockfile\fP] ]
  864. X<zero or more conditions (one per line)>
  865. X<exactly one action line>
  866. X.Re
  867. X.PP
  868. XThe
  869. X.I number
  870. Xis optional (defaults to 1) and specifies the number of conditions that
  871. Xfollow the first line of the recipe.  Conditions are complete lines that are
  872. Xpassed on to the internal egrep
  873. X.BR literally ,
  874. Xexcept for leading blanks.
  875. XIf a condition starts with an '!', the condition is inverted.  If you really
  876. Xwant the condition to start with an '!', precede the '!' by a '\\'.
  877. XThese conditions are
  878. X.B completely
  879. Xcompatible to the normal
  880. X.BR egrep (1)
  881. Xregular expressions.
  882. X.PP
  883. XA special case condition is one starting with either '<' or '>', this
  884. Xcondition is true only if the total length of the mail is shorter,
  885. Xrespectively longer than the specified (in decimal) number of bytes.
  886. X.PP
  887. XAnother special case condition is one starting with a '$'.  This condition
  888. Xwill be evaluated according to
  889. X.BR sh (1)
  890. Xsubtitution rules inside double quotes, i.e. environment variable
  891. Xsubstitutions take place here, prior to being interpreted as a condition.
  892. X.PP
  893. XConditions are anded; if
  894. X.I number
  895. Xis zero, then the condition is always true and no conditions are expected
  896. Xnext.
  897. X.PP
  898. X.I Flags
  899. Xcan be any of the following:
  900. X.Tp 0.5i
  901. X.B +HEAD_GREP+
  902. XEgrep the header (default).
  903. X.Tp
  904. X.B +BODY_GREP+
  905. XEgrep the body.
  906. X.Tp
  907. X.B +DISTINGUISH_CASE+
  908. XTell the internal egrep to distinguish between upper and lower case (defaults
  909. Xto ignoring case).
  910. X.Tp
  911. X.B +ALSO_NEXT_RECIPE+
  912. XThis recipe will depend on the last preceding recipe without the
  913. X`+ALSO_NEXT_RECIPE+' or `+ALSO_N_IF_SUCC+' flag.  This allows you to chain
  914. Xactions that depend on a common condition.  The number of conditions that
  915. Xare expected to follow default to none.
  916. X.Tp
  917. X.B +ALSO_N_IF_SUCC+
  918. XHas the same meaning as the `+ALSO_NEXT_RECIPE+' flag, but will depend on the
  919. X.I successful
  920. Xcompletion of the immediately preceding recipe as well.
  921. X.Tp
  922. X.B +PASS_HEAD+
  923. XFeed the header to the pipe (default).
  924. X.Tp
  925. X.B +PASS_BODY+
  926. XFeed the body to the pipe (default).
  927. X.Tp
  928. X.B +FILTER+
  929. XConsider the pipe as a filter (ignored if a file).
  930. X.Tp
  931. X.B +CONTINUE+
  932. XContinue processing rcfile even if this recipe matches (not needed when 'f'
  933. Xspecified).
  934. X.Tp
  935. X.B +WAIT_EXIT+
  936. XWait for the filter or program to finish and check its exitcode (normally
  937. Xignored); if the filter is unsuccessful, then the text will
  938. Xnot have been filtered.  This flag is also recommended if you specified any
  939. X.I locallockfile
  940. Xon this recipe.
  941. X.Tp
  942. X.B +WAIT_EXIT_QUIET+
  943. XHas the same meaning as the `+ALSO_NEXT_RECIPE+' flag, but will suppress any
  944. X`Program faillure' messages.
  945. X.Tp
  946. X.B +IGNORE_WRITERR+
  947. XIgnore any write errors on this recipe (i.e. usually due to an early closed
  948. Xpipe).
  949. X.Ss "Local lockfile"
  950. X.PP
  951. XIf you put a second ':' on the first recipe line, then procmail will use a
  952. X.I locallockfile
  953. X(for this recipe only).  You can optionally specify the locallockfile
  954. Xto use; if you don't however, procmail will use the destination filename
  955. X(or the filename following the first '>>') and will append $LOCKEXT to it.
  956. X.Ss "Recipe action line"
  957. X.PP
  958. XThe action line can start with the following characters:
  959. X.Tp
  960. X.B !
  961. XForwards to all the specified mail addresses.
  962. X.Tp
  963. X.B |
  964. XStarts the specified program, possibly in $SHELL if any
  965. Xof the characters $SHELLMETAS are found.
  966. X.PP
  967. XAnything else will be taken as a mailbox name (either a filename or a
  968. Xdirectory, absolute or relative to the current directory (see MAILDIR)).
  969. XIf it is a filename (or nonexistent), the mail will be appended to it.
  970. X.PP
  971. XIf it is a directory, the mail will be delivered to a newly created, guaranteed
  972. Xto be unique file named $MSGPREFIX* in the specified directory.  If the
  973. Xdirectory name ends in "/.", then this directory is presumed to be an MH
  974. Xfolder; i.e. procmail will use the lowest number it finds available.
  975. X.Ss "Environment variable defaults"
  976. X.Tp 2.2i
  977. X.B "USER, HOME and SHELL"
  978. XYour (the recipient's) defaults
  979. X.Tp
  980. X.B SHELLMETAS
  981. X\&+DEFshellmetas+
  982. X.Tp
  983. X.B SHELLFLAGS
  984. X\&+DEFshellflags+
  985. X.Tp
  986. X.BR ORGMAIL
  987. X\&+SYSTEM_MBOX+
  988. X.Tp
  989. X.B MAILDIR
  990. X\&+DEFmaildir+
  991. X.Tp
  992. X.B DEFAULT
  993. X\&+DEFdefault+
  994. X.Tp
  995. X.B MSGPREFIX
  996. X\&+DEFmsgprefix+
  997. X.Tp
  998. X.B SENDMAIL
  999. X\&+DEFsendmail+
  1000. X.Tp
  1001. X.B LOCKEXT
  1002. X\&+DEFlockext+
  1003. X.Tp
  1004. X.B LOCKFILE
  1005. X\&+DEFdefaultlock+
  1006. X.br
  1007. X(after procmail closed the last rcfile)+PRESTENV+
  1008. X.Ss Environment
  1009. X.PP
  1010. XBefore you get lost in the multitude of environment variables, keep in mind
  1011. Xthat all of them have reasonable defaults.
  1012. X.Tp 1.2i
  1013. X.B MAILDIR
  1014. XCurrent directory while procmail is executing (that means that all paths
  1015. Xare relative to $MAILDIR).
  1016. X.Tp
  1017. X.B DEFAULT
  1018. XDefault
  1019. X.B mailbox
  1020. Xfile (if not told otherwise, procmail will dump mail in this mailbox).
  1021. XProcmail will automatically use LOCKFILE=$DEFAULT$LOCKEXT prior to writing
  1022. Xto this mailbox.
  1023. X.Tp
  1024. X.B MSGPREFIX
  1025. XFilename prefix that is used when delivering to a directory (not used when
  1026. Xdelivering to an MH directory).
  1027. X.Tp
  1028. X.B LOGFILE
  1029. XAll incoming messages will be logged here with their `+FROM+' and `Subject:'
  1030. Xlines in the header, and an additional line specifying what folder it
  1031. Xfinally went to and how long (in bytes) the message was.  This file will
  1032. Xalso contain any error or diagnostic messages from procmail
  1033. X(normally none :-) or any other programs started by procmail.  If this file
  1034. Xis not specified it defaults to
  1035. X.BR +console+ .
  1036. XYou can turn on
  1037. X.I extended diagnostics
  1038. Xby prepending a `+DEBUGPREFIX+' to the desired pathname.
  1039. X.Tp
  1040. X.B LOG
  1041. XAnything assigned to this variable will be echoed in $LOGFILE.
  1042. X.Tp
  1043. X.B ORGMAIL
  1044. XUsually the system mailbox (\fBOR\fPi\fBG\fPinal \fBMAIL\fPbox).  If, for
  1045. Xsome obscure reason (like `\fBfilesystem full\fP') the mail could not be
  1046. Xdelivered, then this mailbox will be the last resort.  If procmail
  1047. Xfails to save the mail in here (deep, deep trouble :-), then the mail
  1048. Xwill bounce back to the sender.
  1049. X.Tp
  1050. X.B LOCKFILE
  1051. XGlobal semaphore file.  If this file already exists, procmail
  1052. Xwill wait until it has gone before proceeding, and will create it itself
  1053. X(cleaning it up when ready, of course).  If more than one
  1054. X.I lockfile
  1055. Xare specified, then the previous one will be removed before trying to create
  1056. Xthe new one.  The use of a global lockfile is discouraged, use locallockfiles
  1057. X(on a per recipe basis) instead.
  1058. X.Tp
  1059. X.B LOCKEXT
  1060. XDefault extension that is appended to a destination file to determine
  1061. Xwhat local
  1062. X.I lockfile
  1063. Xto use (only if turned on, on a per-recipe basis).
  1064. X.Tp
  1065. X.B LOCKSLEEP
  1066. XNumber of seconds procmail will sleep before retrying on a
  1067. X.I lockfile
  1068. X(if it already existed); if not specified, it defaults to +DEFlocksleep+
  1069. Xseconds.
  1070. X.Tp
  1071. X.B LOCKTIMEOUT
  1072. XNumber of seconds that have to have passed since a
  1073. X.I lockfile
  1074. Xwas last modified/created before procmail decides that this must be an
  1075. Xerroneously leftover lockfile that can be removed by force now.  If zero,
  1076. Xthen no timeout will be used and procmail will wait forever until the
  1077. Xlockfile is removed; if not specified, it defaults to +DEFlocktimeout+ seconds.
  1078. XThis variable is useful to prevent indefinite hangups of
  1079. X.BR sendmail /procmail.
  1080. XProcmail is immune to clock skews.
  1081. X.Tp
  1082. X.B TIMEOUT
  1083. XNumber of seconds that have to have passed before procmail decides that
  1084. Xsome child it started must be hanging.  The offending program will receive
  1085. Xa TERMINATE signal from procmail, and processing of the rcfile will continue.
  1086. XIf zero, then no timeout will be used and procmail will wait forever until the
  1087. Xchild has terminated; if not specified, it defaults to +DEFtimeout+ seconds.
  1088. X.Tp
  1089. X.B HOST
  1090. XIf this is not the
  1091. X.I hostname
  1092. Xof the machine, processing of the current
  1093. X.I rcfile
  1094. Xwill immediately cease. If other rcfiles were specified on the
  1095. Xcommand line, processing will continue with the next one.  If all rcfiles
  1096. Xare exhausted, the program will terminate, but will not generate an error
  1097. X(i.e. to the mailer it will seem that the mail has been delivered).  Only the
  1098. Xfirst +HOSTNAMElen+ characters of the HOST are significant.
  1099. X.Tp
  1100. X.B UMASK
  1101. XThe name says it all (if it doesn't, then forget about this one :-).  It
  1102. Xis taken as an
  1103. X.B octal
  1104. Xnumber.  If not specified, it defaults to +INIT_UMASK+.
  1105. X.Tp
  1106. X.B SHELLMETAS
  1107. XIf any of the characters in SHELLMETAS appears in the line specifying
  1108. Xa filter or program, the line will be fed to $SHELL
  1109. Xinstead of being executed directly.
  1110. X.Tp
  1111. X.B SHELLFLAGS
  1112. XAny invocation of $SHELL will be like:
  1113. X.br
  1114. X"$SHELL" "$SHELLFLAGS" "$*";
  1115. X.Tp
  1116. X.B SENDMAIL
  1117. XIf you're not using the
  1118. X.I forwarding
  1119. Xfacility don't worry about this one.  It specifies the program being
  1120. Xcalled to forward any mail.
  1121. X.br
  1122. XIt gets invoked as: "$SENDMAIL" "$@";
  1123. X.Tp
  1124. X.B NORESRETRY
  1125. XNumber of retries that are to be made if any `\fBprocess table full\fP',
  1126. X`\fBfile table full\fP', `\fBout of memory\fP' or
  1127. X`\fBout of swap space\fP' error should occur.  If this number is negative,
  1128. Xthen procmail will retry indefinitely; if not specified, it defaults to two
  1129. Xtimes.  The retries occur with a $SUSPEND second interval.  The idea behind
  1130. Xthis is, that if the
  1131. X.I swap
  1132. X.I space
  1133. Xhas been exhausted or the
  1134. X.I process
  1135. X.I table
  1136. Xis full, usually several other programs will either detect this
  1137. Xand abort or crash 8-), and thereby freeing valuable
  1138. X.I resources
  1139. Xfor procmail.
  1140. X.Tp
  1141. X.B SUSPEND
  1142. XNumber of seconds that procmail will pause if it has to wait for something
  1143. Xthat is currently unavailable (memory, fork, etc.); if not specified, it will
  1144. Xdefault to +DEFsuspend+ seconds.  See also:
  1145. X.BR LOCKSLEEP .
  1146. X.Tp
  1147. X.B LINEBUF
  1148. XLength of the internal line buffers, cannot be set smaller than +MINlinebuf+.
  1149. XAll lines read from the rcfile
  1150. X.RI ( not
  1151. Xthe mail itself, which can have arbitrary line lengths, or could be a binary
  1152. Xfile for that matter) should not exceed $LINEBUF characters before and after
  1153. Xexpansion.  If not specified, it defaults to +DEFlinebuf+.
  1154. X.Tp
  1155. X.B DELIVERED
  1156. XIf set (to a dummy value) procmail will pretend (to the mail agent) the mail
  1157. Xhas been delivered.  If mail cannot be delivered after meeting this
  1158. Xassignment, the mail will be lost (i.e. it will not bounce).
  1159. X.Sh EXAMPLES
  1160. XLook in the
  1161. X.BR procmailex (5)
  1162. Xman page.
  1163. X.Sh CAVEATS
  1164. XIf you don't explicitly tell procmail to wait (recipe flag `+WAIT_EXIT+' or
  1165. X`+WAIT_EXIT_QUIET+') for a program to finish, it won't wait and will terminate
  1166. Xearly (not knowing if the program returns success).  That also means that any
  1167. Xlocallockfile on this recipe might get removed
  1168. X.I before
  1169. Xthe program has terminated.
  1170. X.PP
  1171. XContinued lines in a recipe that are to be executed are concatenated
  1172. X.I before
  1173. Xbeing parsed, hence
  1174. X.I any
  1175. Xbackslash-newline combinations in them are removed regardless.
  1176. X.PP
  1177. XDon't put comments on the condition lines (the regular expressions) in a recipe,
  1178. Xthese lines are fed to the internal egrep
  1179. X.IR literally .
  1180. X(Except for any
  1181. X.I leading
  1182. Xwhitespace, `!' or `\\', it will be stripped.
  1183. XPrecede it by a `\\' if you want it to be taken literally too.)
  1184. X.PP
  1185. XWatch out for deadlocks when doing unhealthy things like forwarding mail
  1186. Xto your own account.  Deadlocks can be broken by proper use of
  1187. X.BR LOCKTIMEOUT .
  1188. X.PP
  1189. XAny default values that procmail has for some environment variables will
  1190. X.B always
  1191. Xoverride the ones that were already defined.  If you really want to
  1192. Xoverride the defaults, you either have to put them in the
  1193. X.B rcfile
  1194. Xor on the command line as arguments.
  1195. X.Sh "SEE ALSO"
  1196. X.na
  1197. X.BR procmail (1),
  1198. X.BR procmailex (5),
  1199. X.BR sh (1),
  1200. X.BR csh (1),
  1201. X.BR mail (1),
  1202. X.BR binmail (1),
  1203. X.BR uucp (1C),
  1204. X.BR aliases (5),
  1205. X.BR sendmail (8),
  1206. X.BR egrep (1V),
  1207. X.BR lockfile (1),
  1208. X.BR formail (1)
  1209. X.ad
  1210. X.Sh BUGS
  1211. XThe only substitutions of environment variables that can be handled by
  1212. Xprocmail itself are of the type $name, ${name}, $$ and $\-; whereas $\- will
  1213. Xbe substituted by the name of the last folder delivered to.+UPPERCASE_USERNAMES+
  1214. X.PP
  1215. XA line buffer of length $LINEBUF is used when processing the
  1216. X.IR rcfile ,
  1217. Xany expansions
  1218. X.B have
  1219. Xto fit within this limit; if they don't, behaviour is undefined.
  1220. X.PP
  1221. XIf the global lockfile has a
  1222. X.I relative
  1223. Xpath, and the current directory
  1224. Xis not the same as when the global lockfile was created, then the global
  1225. Xlockfile will not be removed if procmail exits at that point (remedy:
  1226. Xuse
  1227. X.I absolute
  1228. Xpaths to specify global lockfiles).
  1229. X.Sh MISCELLANEOUS
  1230. XWhitespace is ignored in the rcfile, except on the
  1231. Xlines that are fed to the internal egrep where only leading whitespace is
  1232. Xignored; i.e. you can indent everything.
  1233. X.PP
  1234. XIf the regular expression starts with `\fB+TOkey+\fP' it will be substituted by
  1235. X`\fB+TOsubstitute+\fP', which should catch all destination
  1236. Xspecifications.
  1237. X.Sh NOTES
  1238. XFor
  1239. X.I really
  1240. Xcomplicated processing you can even consider calling
  1241. X.B procmail
  1242. Xrecursively.
  1243. X.Sh AUTHOR
  1244. XStephen R. van den Berg at RWTH-Aachen, Germany
  1245. X.Rs
  1246. Xberg@pool.informatik.rwth-aachen.de
  1247. Xberg@physik.tu-muenchen.de
  1248. X.Re
  1249. END_OF_FILE
  1250. if test 14618 -ne `wc -c <'procmail/man/procmailrc.man'`; then
  1251.     echo shar: \"'procmail/man/procmailrc.man'\" unpacked with wrong size!
  1252. fi
  1253. # end of 'procmail/man/procmailrc.man'
  1254. fi
  1255. if test -f 'procmail/retint.c' -a "${1}" != "-c" ; then 
  1256.   echo shar: Will not clobber existing file \"'procmail/retint.c'\"
  1257. else
  1258. echo shar: Extracting \"'procmail/retint.c'\" \(13144 characters\)
  1259. sed "s/^X//" >'procmail/retint.c' <<'END_OF_FILE'
  1260. X/************************************************************************
  1261. X *    Collection of routines that return an int (sort of anyway :-)    *
  1262. X *                                    *
  1263. X *    Copyright (c) 1990-1992, S.R. van den Berg, The Netherlands    *
  1264. X *    The sources can be freely copied for non-commercial use.    *
  1265. X *    #include "README"                        *
  1266. X *                                    *
  1267. X ************************************************************************/
  1268. X#ifdef RCS
  1269. Xstatic char rcsid[]="$Id: retint.c,v 2.26 1992/04/09 16:16:41 berg Rel $";
  1270. X#endif
  1271. X#include "config.h"
  1272. X#include "procmail.h"
  1273. X#include "shell.h"
  1274. X
  1275. Xsetdef(name,contents)const char*const name,*const contents;
  1276. X{ strcat(strcat(strcpy((char*)(sgetcp=buf2),name),"="),contents);
  1277. X  readparse(buf,sgetc,2);sputenv(buf);
  1278. X}
  1279. X
  1280. Xchar*lastexec,*backblock;
  1281. Xlong backlen;               /* length of backblock, filter recovery block */
  1282. Xpid_t pidfilt;
  1283. Xint pbackfd[2];                       /* the emergency backpipe :-) */
  1284. X
  1285. Xpipthrough(line,source,len)char*line,*source;const long len;
  1286. X{ int pinfd[2],poutfd[2];
  1287. X  rpipe(pbackfd);rpipe(pinfd);                 /* main pipes setup */
  1288. X  if(!(pidchild=sfork()))            /* create a sending procmail */
  1289. X   { backblock=source;backlen=len;signal(SIGTERM,stermchild);
  1290. X     signal(SIGINT,stermchild);signal(SIGHUP,stermchild);
  1291. X     signal(SIGQUIT,stermchild);rclose(rc);rclose(PRDI);rclose(PRDB);
  1292. X     rpipe(poutfd);rclose(STDOUT);
  1293. X     if(!(pidfilt=sfork()))                /* create the filter */
  1294. X      { rclose(PWRO);rclose(PWRB);rdup(PWRI);rclose(PWRI);getstdin(PRDO);
  1295. X    callnewprog(line);
  1296. X      }
  1297. X     rclose(PWRI);rclose(PRDO);
  1298. X     if(forkerr(pidfilt,line))
  1299. X    rclose(PWRO),stermchild();
  1300. X     if(dump(PWRO,source,len))          /* send in the text to be filtered */
  1301. X    writeerr(line),stermchild();
  1302. X     if(pwait&&waitfor(pidfilt)!=EX_OK)     /* check the exitcode of the filter */
  1303. X      { if(!(pwait&2))                  /* do we put it on report? */
  1304. X       progerr(line);
  1305. X    stermchild();
  1306. X      }
  1307. X     rclose(PWRB);exit(EX_OK);              /* allow parent to proceed */
  1308. X   }
  1309. X  rclose(PWRI);rclose(PWRB);getstdin(PRDI);
  1310. X  if(forkerr(pidchild,procmailn))
  1311. X     return 1;
  1312. X  return 0;            /* we stay behind to read back the filtered text */
  1313. X}
  1314. X
  1315. Xwaitfor(pid)const pid_t pid;              /* wait for a specific process */
  1316. X{ int i;pid_t j;
  1317. X  while(pid!=(j=wait(&i))||WIFSTOPPED(i))
  1318. X     if(-1==j)
  1319. X    return -1;
  1320. X  return WIFEXITED(i)?WEXITSTATUS(i):-1;
  1321. X}
  1322. X
  1323. Xgetstdin(pip)const int pip;
  1324. X{ rclose(STDIN);rdup(pip);rclose(pip);
  1325. X}
  1326. X
  1327. Xcallnewprog(newname)const char*const newname;
  1328. X{ if(sh)                     /* should we start a shell? */
  1329. X   { const char*newargv[4];
  1330. X     yell(executing,newname);newargv[3]=0;newargv[2]=newname;
  1331. X     newargv[1]=tgetenv(shellflags);*newargv=tgetenv(shell);shexec(newargv);
  1332. X   }
  1333. X {register const char*p;int argc;const char**newargv;
  1334. X  argc=1;p=newname;         /* If no shell, chop up the arguments ourselves */
  1335. X  if(verbose)
  1336. X   { log(executing);log(oquote);goto no_1st_comma;
  1337. X   }
  1338. X  do                         /* show chopped up command line */
  1339. X   { if(verbose)
  1340. X      { log(",");
  1341. Xno_1st_comma:
  1342. X    log(p);
  1343. X      }
  1344. X     while(*p++);
  1345. X   }
  1346. X  while(argc++,*p!=TMNATE);
  1347. X  if(verbose)
  1348. X     log(cquote);
  1349. X  newargv=malloc(argc*sizeof*newargv);p=newname;argc=0;     /* alloc argv array */
  1350. X  do
  1351. X   { newargv[argc++]=p;
  1352. X     while(*p++);
  1353. X   }
  1354. X  while(*p!=TMNATE);
  1355. X  newargv[argc]=0;shexec(newargv);
  1356. X }
  1357. X}
  1358. X
  1359. Xwriteerr(line)const char*const line;
  1360. X{ log("Error while writing to");logqnl(line);
  1361. X}
  1362. X
  1363. Xforkerr(pid,a)const pid_t pid;const char*const a;
  1364. X{ if(pid==-1)
  1365. X   { log("Failed forking");logqnl(a);return 1;
  1366. X   }
  1367. X  return 0;
  1368. X}
  1369. X
  1370. Xprogerr(line)const char*const line;
  1371. X{ log("Program failure of");logqnl(line);
  1372. X}
  1373. X
  1374. Xopena(a)const char*const a;
  1375. X{ lastfolder=cstr(lastfolder,a);yell("Opening",a);
  1376. X#ifdef O_CREAT
  1377. X  return ropen(a,O_WRONLY|O_APPEND|O_CREAT,NORMperm);
  1378. X#else
  1379. X {int fd;
  1380. X  return(fd=ropen(a,O_WRONLY,0))<0?creat(a,NORMperm):fd;
  1381. X }
  1382. X#endif
  1383. X}
  1384. X
  1385. Xyell(a,b)const char*const a,*const b;             /* log if -d option set */
  1386. X{ if(verbose)
  1387. X     log(a),logqnl(b);
  1388. X}
  1389. X
  1390. Xunlock(lockp)char**const lockp;
  1391. X{ lcking|=lck_LOCKFILE;
  1392. X  if(*lockp)
  1393. X   { yell("Unlocking",*lockp);
  1394. X     if(unlink(*lockp))
  1395. X    log("Couldn't unlock"),logqnl(*lockp);
  1396. X     if(!nextexit)               /* if not inside a signal handler */
  1397. X    free(*lockp);
  1398. X     *lockp=0;
  1399. X   }
  1400. X  lcking&=~lck_LOCKFILE;
  1401. X  if(nextexit==1)        /* make sure we are not inside terminate already */
  1402. X     log(newline),terminate();
  1403. X}
  1404. X
  1405. Xnomemerr()          /* set nextexit to prevent log from using malloc() */
  1406. X{ nextexit=2;log("Out of memory\n");
  1407. X  if(buf2)
  1408. X   { buf[linebuf-1]=buf2[linebuf-1]='\0';log("buffer 0:");logqnl(buf);
  1409. X     log("buffer 1:");logqnl(buf2);
  1410. X   }
  1411. X  if(retval!=EX_TEMPFAIL)
  1412. X     retval=EX_OSERR;
  1413. X  terminate();
  1414. X}
  1415. X
  1416. Xlogqnl(a)const char*const a;
  1417. X{ log(oquote);log(a);log(cquote);
  1418. X}
  1419. X
  1420. Xnextrcfile()            /* next rcfile specified on the command line */
  1421. X{ const char*p;
  1422. X  while(p= *gargv)
  1423. X   { gargv++;
  1424. X     if(!strchr(p,'='))
  1425. X      { rcfile=p;return 1;
  1426. X      }
  1427. X   }
  1428. X  return 0;
  1429. X}
  1430. X
  1431. Xrclose(fd)const int fd;              /* a SysV secure close (signal immune) */
  1432. X{ int i;
  1433. X  while((i=close(fd))&&errno==EINTR);
  1434. X  return i;
  1435. X}
  1436. X
  1437. Xrwrite(fd,a,len)const int fd,len;void*const a;          /* a SysV secure write */
  1438. X{ int i;
  1439. X  while(0>(i=write(fd,a,(size_t)len))&&errno==EINTR);
  1440. X  return i;
  1441. X}
  1442. X
  1443. Xrread(fd,a,len)const int fd,len;void*const a;           /* a SysV secure read */
  1444. X{ int i;
  1445. X  while(0>(i=read(fd,a,(size_t)len))&&errno==EINTR);
  1446. X  return i;
  1447. X}
  1448. X
  1449. Xropen(name,mode,mask)const char*const name;const int mode;const mode_t mask;
  1450. X{ int i,r;                           /* a SysV secure open */
  1451. X  for(r=noresretry,lcking|=lck_FILDES;0>(i=open(name,mode,mask));)
  1452. X     if(errno!=EINTR&&!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
  1453. X    break;         /* survives a temporary "file table full" condition */
  1454. X  lcking&=~lck_FILDES;return i;
  1455. X}
  1456. X
  1457. Xrdup(p)const int p;
  1458. X{ int i,r;                      /* catch "file table full" */
  1459. X  for(r=noresretry,lcking|=lck_FILDES;0>(i=dup(p));)
  1460. X     if(!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
  1461. X    break;
  1462. X  lcking&=~lck_FILDES;return i;
  1463. X}
  1464. X
  1465. Xrpipe(fd)int fd[2];
  1466. X{ int i,r;                      /* catch "file table full" */
  1467. X  for(r=noresretry,lcking|=lck_FILDES;0>(i=pipe(fd));)
  1468. X     if(!((errno==EMFILE||errno==ENFILE)&&(r<0||r--)))
  1469. X      { *fd=fd[1]= -1;break;
  1470. X      }
  1471. X  lcking&=~lck_FILDES;return i;
  1472. X}
  1473. X
  1474. Xlockit(name,lockp)char*name;const char**const lockp;
  1475. X{ int i,permanent=2,triedforce=0;struct stat stbuf;time_t t;
  1476. X  if(*lockp)
  1477. X   { if(!strcmp(name,*lockp))    /* compare the previous lockfile to this one */
  1478. X    return;             /* they're equal, save yourself some effort */
  1479. X     unlock(lockp);               /* unlock any previous lockfile FIRST */
  1480. X   }                  /* to prevent deadlocks (I hate deadlocks) */
  1481. X  if(!*name)
  1482. X     return;
  1483. X  name=tstrdup(name); /* allocate now, so we won't hang on memory *and* lock */
  1484. X  for(lcking|=lck_LOCKFILE;;)
  1485. X   { yell("Locking",name);        /* in order to cater for clock skew: */
  1486. X     if(!NFSxopen(name,LOCKperm,&t))           /* get time t from filesystem */
  1487. X      { *lockp=name;break;               /* lock acquired, hurray! */
  1488. X      }
  1489. X     switch(errno)
  1490. X      { case EEXIST:           /* check if it's time for a lock override */
  1491. X       if(!lstat(name,&stbuf)&&stbuf.st_size<=MAX_LOCK_SIZE&&locktimeout
  1492. X        &&!lstat(name,&stbuf)&&locktimeout<t-stbuf.st_mtime)
  1493. X         /*
  1494. X          * stat() till unlink() should be atomic, but can't guarantee that
  1495. X          */
  1496. X        { if(triedforce)            /* already tried, not trying */
  1497. X         goto faillock;                        /* again */
  1498. X          if(S_ISDIR(stbuf.st_mode)||unlink(name))
  1499. X         triedforce=1,log("Forced unlock denied on"),logqnl(name);
  1500. X          else
  1501. X           { log("Forcing lock on");logqnl(name);suspend();goto ce;
  1502. X           }
  1503. X        }
  1504. X       else
  1505. X          triedforce=0;         /* legitimate iteration, clear flag */
  1506. X       break;
  1507. X    default:           /* maybe filename too long, shorten and retry */
  1508. X       if(0<(i=strlen(name)-1)&&!strchr(dirsep,name[i-1]))
  1509. X        { log("Truncating");logqnl(name);log(" and retrying lock\n");
  1510. X          name[i]='\0';continue;
  1511. X        }
  1512. Xfaillock:  log("Lock failure on");logqnl(name);goto term;
  1513. X    case ENOENT:case ENOTDIR:case EIO:case EACCES:
  1514. X       if(!--permanent)
  1515. X          goto faillock;
  1516. X    case ENOSPC:;
  1517. X#ifdef EDQUOT
  1518. X    case EDQUOT:;
  1519. X#endif
  1520. X      }
  1521. X     sleep((unsigned)locksleep);
  1522. Xce:  if(nextexit)
  1523. Xterm: { free(name);break;             /* drop the preallocated buffer */
  1524. X      }
  1525. X   }
  1526. X  lcking&=~lck_LOCKFILE;
  1527. X  if(nextexit)
  1528. X   { log(whilstwfor);log("lockfile");logqnl(name);terminate();
  1529. X   }
  1530. X}
  1531. X
  1532. Xlcllock()                   /* lock a local file (if need be) */
  1533. X{ if(locknext)
  1534. X     if(tolock)
  1535. X    lockit(tolock,&loclock);
  1536. X     else
  1537. X    lockit(strcat(buf2,tgetenv(lockext)),&loclock);
  1538. X}
  1539. X
  1540. Xsterminate()
  1541. X{ static const char*const msg[]={"memory","fork",      /* crosscheck with */
  1542. X   "a file descriptor","a kernel lock"};      /* lck_ defs in procmail.h */
  1543. X  ignoreterm();
  1544. X  if(pidchild>0)        /* don't kill what is not ours, we might be root */
  1545. X     kill(pidchild,SIGTERM);
  1546. X  if(!nextexit)
  1547. X   { nextexit=1;log("Terminating prematurely");
  1548. X     if(!(lcking&lck_LOCKFILE))
  1549. X      { register unsigned i,j;
  1550. X    if(i=(lcking&~(lck_ALLOCLIB|lck_LOCKFILE))>>1)
  1551. X     { log(whilstwfor);
  1552. X       for(j=0;(i>>=1)&1;++j);
  1553. X       log(msg[j]);
  1554. X     }
  1555. X    log(newline);terminate();
  1556. X      }
  1557. X   }
  1558. X}
  1559. X
  1560. Xterminate()
  1561. X{ ignoreterm();
  1562. X  if(retvl2!=EX_OK)
  1563. X     fakedelivery=0,retval=retvl2;
  1564. X  if(getpid()==thepid)
  1565. X   { if(retval!=EX_OK)
  1566. X      { lastfolder=fakedelivery?"**Lost**":        /* don't free() here */
  1567. X     retval==EX_TEMPFAIL?"**Requeued**":"**Bounced**";
  1568. X      }
  1569. X     logabstract();nextexit=2;unlock(&loclock);unlock(&globlock);fdunlock();
  1570. X   }
  1571. X  exit(fakedelivery==2?EX_OK:retval);
  1572. X}
  1573. X
  1574. Xignoreterm()
  1575. X{ signal(SIGTERM,SIG_IGN);signal(SIGHUP,SIG_IGN);signal(SIGINT,SIG_IGN);
  1576. X  signal(SIGQUIT,SIG_IGN);
  1577. X}
  1578. X
  1579. Xsuspend()
  1580. X{ long t;
  1581. X  sleep((unsigned)suspendv);
  1582. X  if(alrmtime)
  1583. X     if((t=alrmtime-time((time_t*)0))<=1)      /* if less than 1s timeout */
  1584. X    ftimeout();                  /* activate it by hand now */
  1585. X     else            /* set it manually again, to avoid problems with */
  1586. X    alarm((unsigned)t);    /* badly implemented sleep library functions */
  1587. X}
  1588. X
  1589. Xinittmout(progname)const char*const progname;
  1590. X{ lastexec=cstr(lastexec,progname);
  1591. X  alrmtime=timeoutv?time((time_t*)0)+(unsigned)timeoutv:0;
  1592. X  alarm((unsigned)timeoutv);
  1593. X}
  1594. X
  1595. Xskipspace()
  1596. X{ while(testb(' ')||testb('\t'));
  1597. X}
  1598. X
  1599. Xsgetc()                        /* a fake fgetc for a string */
  1600. X{ return *sgetcp?*(uchar*)sgetcp++:EOF;
  1601. X}
  1602. X
  1603. Xskipped(x)const char*const x;
  1604. X{ log("Skipped");logqnl(x);
  1605. X}
  1606. X
  1607. Xconcatenate(old)char*const old;
  1608. X{ register char*p=old;
  1609. X  while(*p!=TMNATE)              /* concatenate all other arguments */
  1610. X   { while(*p++);
  1611. X     p[-1]=' ';
  1612. X   }
  1613. X  *p=p[-1]='\0';return*old;
  1614. X}
  1615. X
  1616. Xdetab(p)char*p;
  1617. X{ while(p=strchr(p,'\t'))
  1618. X     *p=' ';                        /* take out all tabs */
  1619. X}
  1620. X
  1621. Xstatic uchar rcbuf[STDBUF],*rcbufp,*rcbufend;     /* buffers for custom stdio */
  1622. Xstatic ungetb;                         /* pushed back char */
  1623. X
  1624. Xbopen(name)const char*const name;                 /* my fopen */
  1625. X{ rcbufp=rcbufend=0;ungetb= -1;yell("Rcfile:",name);
  1626. X  return rc=ropen(name,O_RDONLY,0);
  1627. X}
  1628. X
  1629. Xgetbl(p)char*p;                              /* my gets */
  1630. X{ int i;char*q;
  1631. X  for(q=p;;)
  1632. X   { switch(i=getb())
  1633. X      { case '\n':case EOF:
  1634. X       *p='\0';return p!=q;             /* did we read anything at all? */
  1635. X      }
  1636. X     *p++=i;
  1637. X   }
  1638. X}
  1639. X
  1640. Xgetb()                                 /* my fgetc */
  1641. X{ if(ungetb>=0)                        /* anything pushed back? */
  1642. X   { int i;
  1643. X     i=ungetb;ungetb= -1;return i;
  1644. X   }
  1645. X  if(rcbufp==rcbufend)
  1646. X     rcbufend=rcbuf+rread(rc,rcbufp=rcbuf,STDBUF);           /* refill */
  1647. X  return rcbufp<rcbufend?*rcbufp++:EOF;
  1648. X}
  1649. X
  1650. Xtestb(x)const int x;           /* fgetc that only succeeds if it matches */
  1651. X{ int i;
  1652. X  if((i=getb())==x)
  1653. X     return 1;
  1654. X  ungetb=i;return 0;
  1655. X}
  1656. X
  1657. Xalphanum(c)const int c;
  1658. X{ return c>='0'&&c<='9'||c>='a'&&c<='z'||c>='A'&&c<='Z'||c=='_';
  1659. X}
  1660. X                       /* open file or new file in directory */
  1661. Xdeliver(boxname)char*const boxname;
  1662. X{ struct stat stbuf;
  1663. X  strcpy(buf,boxname);             /* boxname can be found back in buf */
  1664. X  return stat(buf,&stbuf)||!S_ISDIR(stbuf.st_mode)?
  1665. X   (tofolder=1,opena(buf)):dirmail();
  1666. X}
  1667. X
  1668. X#ifdef KERNEL_LOCKS
  1669. Xstatic oldfdlock;                    /* the fd we locked last */
  1670. X#ifdef F_SETLKW
  1671. Xstatic struct flock flck;        /* why can't it be a local variable? */
  1672. X
  1673. Xfdlock(fd)                       /* the POSIX-fcntl() lock */
  1674. X{ flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_len=0;
  1675. X  flck.l_start=tell(fd);lcking|=lck_KERNELL;
  1676. X  fd=fcntl(oldfdlock=fd,F_SETLKW,&flck);lcking&=~lck_KERNELL;return fd;
  1677. X}
  1678. X
  1679. Xfdunlock()
  1680. X{ flck.l_type=F_UNLCK;return fcntl(oldfdlock,F_SETLK,&flck);
  1681. X}
  1682. X#else /* F_SETLKW */
  1683. X#ifdef F_LOCK
  1684. Xstatic long oldlockoffset;
  1685. X
  1686. Xfdlock(fd)                         /* the SysV-lockf() */
  1687. X{ oldlockoffset=tell(fd);lcking|=lck_KERNELL;fd=lockf(oldfdlock=fd,F_LOCK,0L);
  1688. X  lcking&=~lck_KERNELL;return fd;
  1689. X}
  1690. X
  1691. Xfdunlock()
  1692. X{ lseek(oldfdlock,oldlockoffset,SEEK_SET);return lockf(oldfdlock,F_ULOCK,0L);
  1693. X}
  1694. X#else /* F_LOCK */
  1695. X#ifdef LOCK_EX
  1696. Xfdlock(fd)                          /* the BSD-flock() */
  1697. X{ lcking|=lck_KERNELL;fd=flock(oldfdlock=fd,LOCK_EX);lcking&=~lck_KERNELL;
  1698. X  return fd;
  1699. X}
  1700. X
  1701. Xfdunlock()
  1702. X{ return flock(oldfdlock,LOCK_UN);
  1703. X}
  1704. X#endif /* LOCK_EX */
  1705. X#endif /* F_LOCK */
  1706. X#endif /* F_SETLKW */
  1707. X#endif /* KERNEL_LOCKS */
  1708. X                    /* an NFS secure exclusive file open */
  1709. XNFSxopen(name,mode,tim)char*name;const mode_t mode;time_t*const tim;
  1710. X{ char*p;int j= -2,i;struct stat stbuf;
  1711. X  i=lastdirsep(name)-name;strncpy(p=malloc(i+UNIQnamelen),name,i);
  1712. X  if(unique(p,p+i,mode))           /* try and rename the unique filename */
  1713. X   { stat(p,&stbuf);
  1714. X     if(tim)
  1715. X    *tim=stbuf.st_mtime;     /* return the filesystem time to the caller */
  1716. X     j=myrename(p,name);
  1717. X   }
  1718. X  free(p);return j;
  1719. X}
  1720. END_OF_FILE
  1721. if test 13144 -ne `wc -c <'procmail/retint.c'`; then
  1722.     echo shar: \"'procmail/retint.c'\" unpacked with wrong size!
  1723. fi
  1724. # end of 'procmail/retint.c'
  1725. fi
  1726. echo shar: End of archive 4 \(of 5\).
  1727. cp /dev/null ark4isdone
  1728. MISSING=""
  1729. for I in 1 2 3 4 5 ; do
  1730.     if test ! -f ark${I}isdone ; then
  1731.     MISSING="${MISSING} ${I}"
  1732.     fi
  1733. done
  1734. if test "${MISSING}" = "" ; then
  1735.     echo You have unpacked all 5 archives.
  1736.     rm -f ark[1-9]isdone
  1737. else
  1738.     echo You still need to unpack the following archives:
  1739.     echo "        " ${MISSING}
  1740. fi
  1741. ##  End of shell archive.
  1742. exit 0
  1743. -- 
  1744. Sincerely,                                  berg@pool.informatik.rwth-aachen.de
  1745.            Stephen R. van den Berg (AKA BuGless).    berg@physik.tu-muenchen.de
  1746.  
  1747. "I have a *cunning* plan!"
  1748.  
  1749. exit 0 # Just in case...
  1750.