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