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