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
10static char pm_version[]=VERSION,ffileno[]=DEFfileno;
11const char offvalue[]="no",empty[]="";
12static int lines;
13const char dirsep[]=DIRSEP;
14static 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
28static 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
38static 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--;
49fin:	putchar('\\');putchar('\\');
50twoesc: putchar('\\');
51singesc:
52     case '&':case '/':putchar('\\');
53   }
54  putchar(i);
55}
56
57static 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
69const char*const*gargv;
70
71static 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
84static 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
88static void putsg P((void))
89{ puts("/g");lines--;
90}
91
92static 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);
103jin:	putsesc(*list);
104      }
105     while(*++list);
106     putsesc(postamble);
107   }
108  putsg();
109}
110
111static void ps(name,value)const char*const name,*const value;
112{ pname(name,0);putsesc(value);putsg();
113}
114
115static void pc(name,value)const char*const name;const int value;
116{ pname(name,0);putcesc(value);putsg();
117}
118
119int 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\
125installed globally as the default mail delivery agent (ask your system \
126administrator), 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 \
129procmail when mail arrives, you can control the invocation of procmail \
130yourself.");
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-||\
136exit 75 \2fB#\2fP\2fIYOUR_USERNAME\2fP\"");
137  ps("FW_comment","The \\fB#\\fP\\fIYOUR_USERNAME\\fP is not actually a\1\
138parameter that is required by procmail, in fact, it will be discarded by\1\
139sh before procmail ever sees it; it is however a necessary kludge against\1\
140overoptimising sendmail programs:\1");
141#else
142  ps("FW_content","\"|exec @BINDIR@/procmail\"");
143  ps("FW_comment","");
144#endif
145#else
146  ps("DOT_FORWARD",".maildelivery");
147  ps("FW_content","* - | ? \"IFS=' '&&p=@BINDIR@/procmail&&test -f $p&&\
148exec $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\
157it will generate an additional `@FAKE_FIELD@' line to help distinguish\1\
158fake 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\
164prevented from executing external programs from\1\
165within their own rcfiles");
166  pn("RESTRICT_EXEC_ID",RESTRICT_EXEC);
167  ps("WARN_RESTRICT_EXEC","\1.TP\1No permission to execute \"x\"\1\
168An 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\
180Care 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\
191will 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\
193See 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\
207Procmail will not take on the identity that comes with the rcfile because\1\
208a 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