1 /* A sed script generator (for transmogrifying the man pages automagically) */
2 
3 /*$Id: manconf.c,v 1.73 2001/08/27 08:43:58 guenther Exp $*/
4 
5 #include "../patchlevel.h"
6 #include "procmail.h"
7 
8 #define pn(name,val)	pnr(name,(long)(val))
9 
10 static char pm_version[]=VERSION,ffileno[]=DEFfileno;
11 const char offvalue[]="no",empty[]="";
12 static int lines;
13 const char dirsep[]=DIRSEP;
14 static const char*const keepenv[]=KEEPENV,*const prestenv[]=PRESTENV,
15  *const trusted_ids[]=TRUSTED_IDS,*const etcrc=ETCRC,
16  *const krnllocks[]={
17 #ifndef NOfcntl_lock
18   "\1.BR fcntl (2)",
19 #endif
20 #ifdef USElockf
21   "\1.BR lockf (3)",
22 #endif
23 #ifdef USEflock
24   "\1.BR flock (2)",
25 #endif
26   0};
27 
skltmark(nl,current)28 static char*skltmark(nl,current)int nl;char**current;
29 { char*from= *current,*p;
30   while(nl--)					 /* skip some newlines first */
31      from=strchr(from,'\n')+1;
32   while(*from=='\t')
33      from++;
34   *(p=strchr(from,'\n'))='\0';*current=p+1;
35   return from;
36 }
37 
putcesc(i)38 static void putcesc(i)int i;
39 { switch(i)
40    { case '\\':i='e';
41 	goto twoesc;
42      case '\1':i='\n';lines--;		    /* \1 doubles for nroff newlines */
43 	goto singesc;
44      case '\2':i='\\';			 /* \2 doubles for nroff backslashes */
45 	goto singesc;
46      case '\t':i='t';
47 	goto fin;
48      case '\n':i='n';lines--;
49 fin:	putchar('\\');putchar('\\');
50 twoesc: putchar('\\');
51 singesc:
52      case '&':case '/':putchar('\\');
53    }
54   putchar(i);
55 }
56 
putsesc(a)57 static void putsesc(a)const char*a;
58 { int c,k;
59   for(c=0;;putcesc(c=k))
60      switch(k= *a++)
61       { case '\0':
62 	   return;
63 	case '|':case ':':
64 	   if(c!=' ')	 /* only insert these if there wasn't a space before */
65 	      printf("\\\\h'-\\\\w' 'u' ");		 /* breaking nospace */
66       }
67 }
68 
69 const char*const*gargv;
70 
pname(name,supps)71 static void pname(name,supps)const char*const name;int supps;
72 { static unsigned filecount;
73   static char*filebuf;
74   if(!filebuf&&!(filebuf=malloc(strlen(*gargv)+1+4+1)))
75      exit(EX_OSERR);
76   if(lines<=0)
77    { sprintf(filebuf,"%s.%04d",*gargv,filecount++);freopen(filebuf,"w",stdout);
78      lines=64;				  /* POSIX says commands are limited */
79    }		      /* some !@#$%^&*() implementations limit lines instead */
80   if(!supps)putchar('s');
81   putchar('/');putchar('@');putsesc(name);putchar('@');putchar('/');
82 }
83 
pnr(name,value)84 static void pnr(name,value)const char*const name;const long value;
85 { pname(name,0);printf("%s%ld/g\n",value<0?"\\":"",value);lines--;
86 }
87 
putsg(void)88 static void putsg P((void))
89 { puts("/g");lines--;
90 }
91 
plist(name,preamble,list,postamble,ifno,andor)92 static void plist(name,preamble,list,postamble,ifno,andor)
93  const char*const name,*const preamble,*const postamble,*const ifno,
94  *const andor;const char*const*list;
95 { pname(name,0);
96   if(!*list)
97      putsesc(ifno);
98   else
99    { putsesc(preamble);
100      goto jin;
101      do
102       { putsesc(list[1]?", ":andor);
103 jin:	putsesc(*list);
104       }
105      while(*++list);
106      putsesc(postamble);
107    }
108   putsg();
109 }
110 
ps(name,value)111 static void ps(name,value)const char*const name,*const value;
112 { pname(name,0);putsesc(value);putsg();
113 }
114 
pc(name,value)115 static void pc(name,value)const char*const name;const int value;
116 { pname(name,0);putcesc(value);putsg();
117 }
118 
main(argc,argv)119 int main(argc,argv)int argc;const char*const argv[];
120 { char*p;
121   gargv=argv+1;
122 #ifdef CF_no_procmail_yet
123   ps("CF_procmail","If procmail is\1\
124 .I not\1\
125 installed globally as the default mail delivery agent (ask your system \
126 administrator), you have to make sure it is invoked when your mail arrives.");
127 #else
128   ps("CF_procmail","Instead of using the system provided invocation of \
129 procmail when mail arrives, you can control the invocation of procmail \
130 yourself.");
131 #endif
132 #ifndef MAILBOX_SEPARATOR
133   ps("DOT_FORWARD",".forward");
134 #ifdef buggy_SENDMAIL
135   ps("FW_content","\"|IFS=' '&&p=@BINDIR@/procmail&&test -f $p&&exec $p -Yf-||\
136 exit 75 \2fB#\2fP\2fIYOUR_USERNAME\2fP\"");
137   ps("FW_comment","The \\fB#\\fP\\fIYOUR_USERNAME\\fP is not actually a\1\
138 parameter that is required by procmail, in fact, it will be discarded by\1\
139 sh before procmail ever sees it; it is however a necessary kludge against\1\
140 overoptimising sendmail programs:\1");
141 #else
142   ps("FW_content","\"|exec @BINDIR@/procmail || exit 75\"");
143   ps("FW_comment","");
144 #endif
145 #else
146   ps("DOT_FORWARD",".maildelivery");
147   ps("FW_content","* - | ? \"IFS=' '&&p=@BINDIR@/procmail&&test -f $p&&\
148 exec $p||exit 75 \2fB#\2fP\2fIYOUR_USERNAME\2fP\"");
149 #endif
150   plist("PRESTENV",
151    "\1.na\1.PP\1Other cleared or preset environment variables are ",
152    prestenv,".\1.ad",""," and ");
153   plist("KEEPENV",", except for the value of ",keepenv,"",""," and ");
154   plist("TRUSTED_IDS",
155   "  If procmail is not invoked with one of the following user or group ids: ",
156    trusted_ids,", but still has to generate or accept a new `@FROM@' line,\1\
157 it will generate an additional `@FAKE_FIELD@' line to help distinguish\1\
158 fake mails.",""," or ");
159   plist("KERNEL_LOCKING",
160    "consistently uses the following kernel locking strategies:",krnllocks,"",
161    "doesn't use any additional kernel locking strategies","\1and");
162 #ifdef RESTRICT_EXEC
163   ps("RESTRICT_EXEC","\1.PP\1Users with userids >= @RESTRICT_EXEC_ID@ are\1\
164 prevented from executing external programs from\1\
165 within their own rcfiles");
166   pn("RESTRICT_EXEC_ID",RESTRICT_EXEC);
167   ps("WARN_RESTRICT_EXEC","\1.TP\1No permission to execute \"x\"\1\
168 An attempt to execute a program from within the rcfile was blocked.");
169 #else
170   ps("RESTRICT_EXEC","");
171   ps("WARN_RESTRICT_EXEC","");
172 #endif
173   ps("LD_ENV_FIX","\1.PP\1For security reasons, upon startup procmail will\
174  wipe out all environment variables that are suspected of modifying the\
175  behavior of the runtime linker.");
176   ps("MAILSPOOLDIR",MAILSPOOLDIR);
177   ps("ETCRC_desc",etcrc?"\1.PP\1If no rcfiles and no\1.B \2-@PRESERVOPT@\1have\
178  been specified on the command line, procmail will, prior to reading\
179  @PROCMAILRC@, interpret commands from\1.B @ETCRC@\1(if present).\1\
180 Care must be taken when creating @ETCRC@, because, if circumstances\
181  permit, it will be executed with root privileges (contrary to the\
182  @PROCMAILRC@ file of course).":"");
183   ps("ETCRC_files",etcrc?"\1.TP\1.B @ETCRC@\1initial global rcfile":"");
184   ps("DROPPRIVS",etcrc?"\1.TP\1.B DROPPRIVS\1If set to `yes' procmail\
185  will drop all privileges it might have had (suid or sgid).  This is\
186  only useful if you want to guarantee that the bottom half of the\
187  @ETCRC@ file is executed on behalf of the recipient.":"");
188   ps("ETCRC_warn",etcrc?"\1.PP\1The\1.B @ETCRC@\1file might be executed\
189  with root privileges, so be very careful of what you put in it.\1\
190 .B SHELL\1\
191 will be equal to that of the current recipient, so if procmail has to invoke\
192  the shell, you'd better set it to some safe value first.\1\
193 See also:\1.BR DROPPRIVS .":"");
194   ps("ETCRC",etcrc?etcrc:"");
195 #ifdef ETCRCS
196   ps("ETCRCS_desc","\1If the rcfile is an absolute path starting with\
197 \1.B @ETCRCS@\
198 \1without backward references (i.e. the parent directory cannot\
199  be mentioned) procmail will, only if no security violations are found,\
200  take on the identity of the owner of the rcfile (or symbolic link).");
201   ps("ETCRCS_files","\1.TP\1.B @ETCRCS@\1special privileges path for rcfiles");
202   ps("ETCRCS_warn","\1.PP\1Keep in mind that if\1.BR chown (1)\1is permitted\
203  on files in\1.BR @ETCRCS@ ,\1that they can be chowned to root\
204  (or anyone else) by their current owners.\1For maximum security, make\
205  sure this directory is\1.I executable\1to root only.");
206   ps("ETCRCS_error","\1.TP\1Denying special privileges for \"x\"\1\
207 Procmail will not take on the identity that comes with the rcfile because\1\
208 a security violation was found (e.g. \1.B \2-@PRESERVOPT@\1or variable\
209  assignments on the command line) or procmail had insufficient privileges\
210  to do so.");
211   ps("ETCRCS",ETCRCS);
212 #else
213   ps("ETCRCS_desc","");ps("ETCRCS_files","");ps("ETCRCS_warn","");
214   ps("ETCRCS_error","");
215 #endif
216 #ifdef console
217   ps("pconsole","appear on\1.BR ");
218   ps("console",console);
219   ps("aconsole"," .");
220 #else
221   ps("pconsole","be mailed back to the ");
222   ps("console","sender");
223   ps("aconsole",".");
224 #endif
225 #ifdef LMTP
226   ps("LMTPusage","\1.br\1.B procmail\1.RB [ \
227  \2-@TEMPFAILOPT@@OVERRIDEOPT@@BERKELEYOPT@ ]\1.RB [ \"\2-@ARGUMENTOPT@ \
228  \2fIargument\2fP\" ]\1.B \2-@LMTPOPT@\1");
229   ps("LMTPOPTdesc","\1.TP\1.B \2-@LMTPOPT@\1This turns on LMTP mode, wherein\
230  procmail acts as an RFC2033 LMTP server.\1Delivery takes place in the same \
231  manner and under the same restrictions as\1the delivery mode enabled \
232  with\1.BR \2-@DELIVEROPT@ .\1This option is incompatible with\1.B \
233  \2-@PRESERVOPT@\1and\1.BR \2-@FROMWHOPT@ .\1");
234   pc("LMTPOPT",LMTPOPT);
235 #else
236   ps("LMTPOPTdesc","");ps("LMTPusage","");
237 #endif
238   pname("INIT_UMASK",0);printf("0%lo/g\n",(unsigned long)INIT_UMASK);lines--;
239   pn("DEFlinebuf",DEFlinebuf);
240   ps("BOGUSprefix",BOGUSprefix);
241   ps("FAKE_FIELD",FAKE_FIELD);
242   ps("PROCMAILRC",PROCMAILRC);
243   pn("RETRYunique",RETRYunique);
244   pn("DEFsuspend",DEFsuspend);
245   pn("DEFlocksleep",DEFlocksleep);
246   ps("TO_key",TO_key);
247   ps("TO_substitute",TO_substitute);
248   ps("TOkey",TOkey);
249   ps("TOsubstitute",TOsubstitute);
250   ps("FROMDkey",FROMDkey);
251   ps("FROMDsubstitute",FROMDsubstitute);
252   ps("FROMMkey",FROMMkey);
253   ps("FROMMsubstitute",FROMMsubstitute);
254   ps("DEFshellmetas",DEFshellmetas);
255   ps("DEFmaildir",DEFmaildir);
256   ps("DEFdefault",DEFdefault);
257   ps("DEFmsgprefix",DEFmsgprefix);
258   ps("DEFsendmail",DEFsendmail);
259   ps("DEFflagsendmail",DEFflagsendmail);
260   ps("DEFlockext",DEFlockext);
261   ps("DEFshellflags",DEFshellflags);
262   ps("DEFpath",strchr(DEFPATH,'=')+1);
263   ps("DEFspath",strchr(DEFSPATH,'=')+1);
264   pn("DEFlocktimeout",DEFlocktimeout);
265   pn("DEFtimeout",DEFtimeout);
266   pn("DEFnoresretry",DEFnoresretry);
267   ps("MATCHVAR",MATCHVAR);
268   ps("COMSAThost",COMSAThost);
269   ps("COMSATservice",COMSATservice);
270   ps("COMSATprotocol",COMSATprotocol);
271   ps("COMSATxtrsep",COMSATxtrsep);
272   pc("SERV_ADDRsep",SERV_ADDRsep);
273   ps("DEFcomsat",DEFcomsat);
274   ps("BinSh",BinSh);
275   ps("ROOT_DIR",ROOT_DIR);
276   ps("DEAD_LETTER",DEAD_LETTER);
277   pc("MCDIRSEP",*MCDIRSEP);
278   pc("chCURDIR",chCURDIR);
279   pc("HELPOPT1",HELPOPT1);
280   pc("HELPOPT2",HELPOPT2);
281   pc("VERSIONOPT",VERSIONOPT);
282   pc("PRESERVOPT",PRESERVOPT);
283   pc("TEMPFAILOPT",TEMPFAILOPT);
284   pc("MAILFILTOPT",MAILFILTOPT);
285   pc("FROMWHOPT",FROMWHOPT);
286   pc("REFRESH_TIME",REFRESH_TIME);
287   pc("ALTFROMWHOPT",ALTFROMWHOPT);
288   pc("OVERRIDEOPT",OVERRIDEOPT);
289   pc("BERKELEYOPT",BERKELEYOPT);
290   pc("ARGUMENTOPT",ARGUMENTOPT);
291   pc("DELIVEROPT",DELIVEROPT);
292   pn("MINlinebuf",MINlinebuf);
293   ps("FROM",FROM);
294   pc("HEAD_GREP",RECFLAGS[HEAD_GREP]);
295   pc("BODY_GREP",RECFLAGS[BODY_GREP]);
296   pc("DISTINGUISH_CASE",RECFLAGS[DISTINGUISH_CASE]);
297   pc("ALSO_NEXT_RECIPE",RECFLAGS[ALSO_NEXT_RECIPE]);
298   pc("ALSO_N_IF_SUCC",RECFLAGS[ALSO_N_IF_SUCC]);
299   pc("ELSE_DO",RECFLAGS[ELSE_DO]);
300   pc("ERROR_DO",RECFLAGS[ERROR_DO]);
301   pc("PASS_HEAD",RECFLAGS[PASS_HEAD]);
302   pc("PASS_BODY",RECFLAGS[PASS_BODY]);
303   pc("FILTER",RECFLAGS[FILTER]);
304   pc("CONTINUE",RECFLAGS[CONTINUE]);
305   pc("WAIT_EXIT",RECFLAGS[WAIT_EXIT]);
306   pc("WAIT_EXIT_QUIET",RECFLAGS[WAIT_EXIT_QUIET]);
307   pc("IGNORE_WRITERR",RECFLAGS[IGNORE_WRITERR]);
308   pc("RAW_NONL",RECFLAGS[RAW_NONL]);
309   ps("FROM_EXPR",FROM_EXPR);
310   pc("UNIQ_PREFIX",UNIQ_PREFIX);
311   ps("ESCAP",ESCAP);
312   ps("UNKNOWN",UNKNOWN);
313   ps("OLD_PREFIX",OLD_PREFIX);
314   ps("DEFfileno",ffileno+LEN_FILENO_VAR);
315   ffileno[LEN_FILENO_VAR-1]='\0';
316   ps("FILENO",ffileno);
317   pn("MAX32",MAX32);
318   pn("MIN32",MIN32);
319   pc("FM_SKIP",FM_SKIP);
320   pc("FM_TOTAL",FM_TOTAL);
321   pc("FM_BOGUS",FM_BOGUS);
322   pc("FM_BERKELEY",FM_BERKELEY);
323   pc("FM_QPREFIX",FM_QPREFIX);
324   pc("FM_CONCATENATE",FM_CONCATENATE);
325   pc("FM_ZAPWHITE",FM_ZAPWHITE);
326   pc("FM_LOGSUMMARY",FM_LOGSUMMARY);
327   pc("FM_FORCE",FM_FORCE);
328   pc("FM_REPLY",FM_REPLY);
329   pc("FM_KEEPB",FM_KEEPB);
330   pc("FM_TRUST",FM_TRUST);
331   pc("FM_SPLIT",FM_SPLIT);
332   pc("FM_NOWAIT",FM_NOWAIT);
333   pc("FM_EVERY",FM_EVERY);
334   pc("FM_MINFIELDS",FM_MINFIELDS);
335   pn("DEFminfields",DEFminfields);
336   pc("FM_DIGEST",FM_DIGEST);
337   pc("FM_BABYL",FM_BABYL);
338   pc("FM_QUIET",FM_QUIET);
339   pc("FM_DUPLICATE",FM_DUPLICATE);
340   pc("FM_EXTRACT",FM_EXTRACT);
341   pc("FM_EXTRC_KEEP",FM_EXTRC_KEEP);
342   pc("FM_ADD_IFNOT",FM_ADD_IFNOT);
343   pc("FM_ADD_ALWAYS",FM_ADD_ALWAYS);
344   pc("FM_REN_INSERT",FM_REN_INSERT);
345   pc("FM_DEL_INSERT",FM_DEL_INSERT);
346   pc("FM_FIRST_UNIQ",FM_FIRST_UNIQ);
347   pc("FM_LAST_UNIQ",FM_LAST_UNIQ);
348   pc("FM_ReNAME",FM_ReNAME);
349   pc("FM_VERSION",FM_VERSION);
350   pn("EX_OK",EXIT_SUCCESS);
351   ps("PM_VERSION",PM_VERSION);
352   ps("BINDIR",BINDIR);
353 #ifdef NOpow
354   pc("POW",'1');
355 #else
356   pc("POW",'x');
357 #endif
358   ps("SETRUID",setRuid(getuid())?"":	/* is setruid() a valid system call? */
359    " (or if procmail is already running with the recipient's euid and egid)");
360   if(lines<20)lines=0;				  /* make sure we have space */
361   pname("AUTHORS",1);putchar('c');
362   p=strchr(pm_version,'\n')+1;
363   while(*p!='\n')
364    { char*q=strchr(p,',')+2;
365      puts("\\");lines--;
366      *(p=strchr(q,'\t'))='\0';
367      putsesc(q);puts("\\\n.RS\\");lines-=2;
368      while(*++p=='\t');*(q=strchr(p,'\n'))='\0';
369      putsesc(p);printf("\\\n.RE");lines--;
370      p=q+1;
371    }
372   putchar('\n');lines--;
373   ps("PM_MAILINGLIST",skltmark(2,&p));
374   ps("PM_MAILINGLISTR",skltmark(2,&p));
375   return EXIT_SUCCESS;
376 }
377