Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / conf / mhconfig.c
1 /* mhconfig.c - configure MH */
2 /* cc [-DSYS5] mhconfig.c -o mhconfig */
3 #ifndef lint
4 static char ident[] = "@(#)$Id: mhconfig.c,v 2.73 1996/02/08 19:07:47 jromine Exp $";
5 #endif  /* lint */
6
7 #include <ctype.h>
8 #include <stdio.h>
9 #ifdef  hpux
10 #define SYS5
11 #endif
12 #ifdef  SYS5
13 #define index   strchr
14 #define rindex  strrchr
15 #endif /* SYS5 */
16
17 static void insopt(), mkopts();
18
19 extern  char *strcpy(), *malloc(), *index(), *rindex();
20 #ifdef  notdef
21 extern  char *sprintf();        /* rely on stdio.h to declare this */
22 #endif
23
24 #define BANNER  "This is %s, for generic UNIX (MH.6 configuration program)\n\n"
25
26
27 #define SED             "config.sed"
28 #define SEDOC           "doc/config.sed"
29 #define MAKE            "../%s/Makefile"
30
31 #define WARNING "This file is automatically generated.  Do not edit!"
32 #define MHRELEASE       "6.8.4"         /* for version: "Maj.min.pat" */
33 #define MHCENTERFOOT    "MH.6.8"        /* for nroff page footers */
34 #define MHLEFTFOOT      "[mh.6]"        /* [mh.6]    MH.6.6   page# */
35 #define MHSLIBVER       "3.2"           /* SunOS4 shared library version */
36
37 #define NOTOK   (-1)
38
39 #define NULLCP  ((char *) 0)
40
41 #define SVAL(s) (s ? s : "")
42
43 #define QUOTE   '\\'
44
45 /* \f */
46
47 static int   smtp = 0;
48 static int   mpop = 0;
49
50 static int   sedP = 1;
51 static int   filesP = 1;
52 static int   docP = 1;
53 static int   makeP = 1;
54
55 static char *myname = "mhconfig";
56 static char *config = NULL;
57 static char *myopts = NULL;
58
59 static char *binpath = "/usr/local";
60 static char *bbhome = "/usr/spool/bboards";
61 static char *bboards = "off";
62 static char *bbdelivery = "off";
63 static char *ccoptions = NULL;
64 static char *chownpath = "/etc/chown";
65 static char *compiler = "/bin/cc";
66 static char *copy = "cp";
67 static char *curses = "-lcurses -ltermlib";
68 static char *debug = "off";
69 static char *editor = "prompter";
70 static char *etcpath = "/usr/local/lib/mh";
71 static char *ldoptions = NULL;
72 static char *ldoptlibs = NULL;
73 static char *lex = "lex -nt";
74 static char *ln = "ln";
75 static char *mailgroup = "off";
76 static char *mailpath = "/usr/spool/mail";
77 static char *maildir = NULL;
78 static char *mailfile = NULL;
79 static char *mancat = "man";
80 static char *mandir = "/usr/man";
81 static char *manuals = "standard";
82 static char *mf = "off";
83 static char *mts = "sendmail";
84 static char *poppath = "/usr/etc";
85 static char *removeit = "mv -f";
86 static char *regtest = "off";
87 static char *oldload = "off";
88 static char *options = NULL;
89 static char *pop = "off";
90 static char *ranlib = "on";
91 static char *sharedlib = "off";
92 static char *signl = "int";
93 static char *slibdir = "/usr/local/lib";
94 static char *slflags = "-pic";
95 static char *sprntf = NULL;
96
97 /* \f */
98
99 #define unknown         0
100 #define mmdf            1
101 #define mmdf2           2
102 #define mh              3
103 #define sendmail        4
104 static int mtsnum = unknown;
105
106 static struct mtsopt {
107     char  *mtskey;
108     char  *optval;
109     int    code;
110     int    mtsflags;
111 #define NOFLAGS 0x00
112 #define DOSMTP  0x01
113 #define NOMF    0x02
114 } mtsopts[] = {
115     "mmdf", "MMDFMTS MMDFI", mmdf, NOFLAGS,
116     "mmdf/smtp", "SENDMTS SMTP", mmdf, DOSMTP,
117     "mmdf2", "MMDFMTS MMDFII", mmdf2, NOFLAGS,
118     "mmdf2/smtp", "SENDMTS MMDFII SMTP", mmdf2, DOSMTP,
119     "mh", "MHMTS", mh, NOFLAGS,
120     "sendmail", "SENDMTS", sendmail, NOMF,
121     "sendmail/smtp", "SENDMTS SMTP", sendmail, NOMF,
122     "zmailer", "ZMAILER SENDMTS", sendmail, NOMF,
123     "zmailer/smtp", "ZMAILER SENDMTS SMTP", sendmail, NOMF,
124     NULL, NULL, unknown, NOFLAGS
125 };
126
127 /* other options which cause sed BEGIN/END configuration changes */
128
129 static struct copt {
130     char *c_name;
131     int   c_value;
132 }       copts[] = {
133     "APOP", 0,  /* authenticated pop */
134     "BSD43", 0, /* sgid ttys */
135     "BSD44", 0, /* manual headings */
136     "KPOP", 0,  /* KERBEROS pop */
137     "HESIOD", 0,
138     "MIME", 0,  /* multi-media extensions */
139     "MPOP", 0,  /* mobile pop */
140     "MSGID", 0, /* slocal dup surpression */
141     "NORUSERPASS", 0, /* no ruserpass(3) */
142     "TMA", 0,   /* trusted mail */
143     "TTYD", 0,
144     "UCI", 0,
145     NULL, 0
146 };
147
148
149
150 /* \f */
151
152 static struct bind {
153     char   *keyword;
154
155     char  **value;
156
157     int     flags;
158 #define BD_NIL  0x00
159 #define BD_ADD  0x01
160 }                   binds[] = {
161                         "bin", &binpath, BD_NIL,
162                         "bbhome", &bbhome, BD_NIL,
163                         "bboards", &bboards, BD_NIL,
164                         "bbdelivery", &bbdelivery, BD_NIL,
165                         "ccoptions", &ccoptions, BD_ADD,
166                         "chown", &chownpath, BD_NIL,
167                         "cc", &compiler, BD_NIL,
168                         "cp", &copy, BD_NIL,
169                         "curses", &curses, BD_NIL,
170                         "debug", &debug, BD_NIL,
171                         "editor", &editor, BD_NIL,
172                         "etc", &etcpath, BD_NIL,
173                         "ldoptions", &ldoptions, BD_ADD,
174                         "ldoptlibs", &ldoptlibs, BD_ADD,
175                         "lex", &lex, BD_NIL,
176                         "ln", &ln, BD_NIL,
177                         "mail", &mailpath, BD_NIL,
178                         "mailgroup", &mailgroup, BD_NIL,
179                         "mandir", &mandir, BD_NIL,
180                         "manuals", &manuals, BD_NIL,
181                         "mf", &mf, BD_NIL,
182                         "mts", &mts, BD_NIL,
183                         "oldload", &oldload, BD_NIL,
184                         "options", &options, BD_ADD,
185                         "pop", &pop, BD_NIL,
186                         "popdir", &poppath, BD_NIL,
187                         "ranlib", &ranlib, BD_NIL,
188                         "remove", &removeit, BD_NIL,
189                         "regtest", &regtest, BD_NIL,
190                         "sharedlib", &sharedlib, BD_NIL,
191                         "signal", &signl, BD_NIL,
192                         "slflags", &slflags, BD_NIL,
193                         "slibdir", &slibdir, BD_NIL,
194                         "sprintf", &sprntf, BD_NIL,
195                         NULL
196 };
197
198 /* \f */
199
200 char   *files[] = {
201     "../support/bboards/bboards.daily",
202     "../support/bboards/bboards.weekly",
203     "../support/bboards/crontab",
204     "../support/bboards/MakeBBoards",
205     "../config/config.c",
206     "../zotnet/mts/mts.c",
207     "../zotnet/mts/mtstailor",
208     "../support/general/MailAliases",
209     "../mts/sendmail/bboardsMH.m4",
210     "../mts/sendmail/popMH.m4",
211     NULL
212 };
213
214 static struct pair {
215     char   *infile;
216     char   *outfile;
217 }                  makefiles[] = {
218                         "makefiles/MH-Makefile", ".",
219                         "makefiles/config","config",
220                         "makefiles/dist","dist",
221                         "makefiles/doc","doc",
222                         "makefiles/mtsM","mts",
223                             "makefiles/mts/mh","mts/mh",
224                             "makefiles/mts/mmdf","mts/mmdf",
225                             "makefiles/mts/sendmail","mts/sendmail",
226                         "makefiles/papers","papers",
227                         "makefiles/sbr","sbr",
228                         "makefiles/supportM","support",
229                             "makefiles/support/bboards","support/bboards",
230                             "makefiles/support/general","support/general",
231                             "makefiles/support/pop","support/pop",
232                         "makefiles/uip","uip",
233                         "makefiles/zotnetM","zotnet",
234                             "makefiles/zotnet/bboards","zotnet/bboards",
235                             "makefiles/zotnet/mf","zotnet/mf",
236                             "makefiles/zotnet/mts","zotnet/mts",
237                             "makefiles/zotnet/tws","zotnet/tws",
238                         NULL
239 };
240
241
242 static do_sed(), do_sedfile(), do_files(), do_doc(), do_make();
243 static shell(), arginit(), add_option(), trim();
244
245 static char   *stradd (), *strdup (), *tail ();
246
247 long    time ();
248
249 /* \f */
250
251 /* ARGSUSED */
252
253 main (argc, argv, envp)
254 int     argc;
255 char  **argv,
256       **envp;
257 {
258     arginit (argv);
259
260     if (sedP)
261         do_sed ();
262     if (filesP)
263         do_files ();
264     if (docP)
265         do_doc ();
266     if (makeP)
267         do_make ();
268
269 #ifdef  notdef
270     printf ("Don't forget to edit \"config/mtstailor\"\n");
271 #endif
272     if (filesP || makeP)
273         printf ("Don't forget to run \"make clean\" in the top directory before compiling\n");
274
275     exit (0);
276 }
277
278 /* \f */
279
280 static  do_sed () {
281     if (docP != 2)
282         do_sedfile (SED, 0);
283     do_sedfile (SEDOC, smtp);
284 }
285
286 static do_alldoc (fp)
287 FILE *fp;
288 {
289     fprintf (fp, "%s\n%s\n%s\n%s\n",    /* turn @BEGIN: XX into #ifdef XX */
290         "s!^@BEGIN: \\(.*\\)$!.br\\",   /* for MH wizard manual set */
291         ".ti 0i\\",
292         "#ifdef \\1\\",
293         ".br!"
294     );
295     fprintf (fp, "%s\n%s\n%s\n%s\n", 
296         "s!^@END: \\(.*\\)$!.br\\",
297         ".ti 0i\\",
298         "#endif /* \\1\\ */",
299         ".br!"
300     );
301 }
302
303 /* \f */
304
305 static do_sedfile (sed, flag)
306 char    *sed;
307 int     flag;
308 {
309     int     i;
310     FILE * fp;
311     struct copt *op;
312
313     if ((fp = fopen (sed, "w")) == NULL)
314         adios (sed, "unable to write");
315     printf ("generating %s\n", sed);
316
317     if (docP == 2) {
318         printf ("...using special all-doc format.\n");
319         printf ("Be sure to reconfigure before compiling.\n");
320         do_alldoc(fp);  /* hack up doc/config.sed */
321     }
322
323     fprintf (fp, "s%%@(MHCONFIGFILE)%%%s%%g\n", SVAL(config));
324     fprintf (fp, "s%%@(MHWARNING)%%%s%%g\n", WARNING);
325     fprintf (fp, "s%%@(MHRELEASE)%%%s%%g\n", MHRELEASE);
326     fprintf (fp, "s%%@(MHCENTERFOOT)%%%s%%g\n", MHCENTERFOOT);
327     fprintf (fp, "s%%@(MHLEFTFOOT)%%%s%%g\n", MHLEFTFOOT);
328     fprintf (fp, "s%%@(MHBINPATH)%%%s%%g\n", SVAL (binpath));
329     fprintf (fp, "s%%@(MHETCPATH)%%%s%%g\n", SVAL (etcpath));
330     fprintf (fp, "s%%@(MHPOPDPATH)%%%s%%g\n", SVAL (poppath));
331     fprintf (fp, "s%%@(MHCHOWNPATH)%%%s%%g\n", SVAL (chownpath));
332     fprintf (fp, "s%%@(MHDROPATH)%%%s%%g\n", SVAL (maildir));
333     fprintf (fp, "s%%@(MHDROPFIL)%%%s%%g\n", SVAL (mailfile));
334     if (maildir)
335         fprintf (fp, "s%%@(MHDROPLOC)%%%s/$USER%%g\n", SVAL (maildir));
336     else
337         fprintf (fp, "s%%@(MHDROPLOC)%%$HOME/%s%%g\n", SVAL (mailfile));
338     fprintf (fp, "s%%@(MHDROPHAK)%%%s%%g\n",/* HACK */
339         maildir ? maildir : "/usr/spool/mail");
340
341     fprintf (fp, "s%%@(MHMANDIR)%%%s%%g\n", mandir);
342     fprintf (fp, "s%%@(MHCATMAN)%%%s%%g\n",
343         strcmp(mancat, "cat") == 0 ? "| nroff -man" : "");
344     if (strcmp (manuals, "standard") == 0 || strcmp (manuals, "gen") == 0)
345         for (i = 1; i <= 8; i++) {
346             fprintf (fp, "s%%@(MHMANDIR%d)%%%s%d%%g\n", i, mancat, i);
347             fprintf (fp, "s%%@(MHMANEXT%d)%%%d%%g\n", i, i);
348         }
349     else
350         for (i = 1; i <= 8; i++) {
351             fprintf (fp, "s%%@(MHMANDIR%d)%%%s%c%%g\n", i, mancat,
352                     strcmp (manuals, "new") == 0 ? 'n'
353                     : strcmp (manuals, "old") == 0 ? 'o'
354                     : strcmp (manuals, "bsd44") == 0 ? i + '0'
355                     : 'l');
356             fprintf (fp, "s%%@(MHMANEXT%d)%%%c%%g\n", i,
357                     strcmp (manuals, "new") == 0 ? 'n'
358                     : strcmp (manuals, "old") == 0 ? 'o'
359                     : strcmp (manuals, "bsd44") == 0 ? '0'
360                     : 'l');
361         }
362
363 /* \f */
364
365     if (strcmp (regtest, "on") == 0)
366         fprintf (fp, "s%%@(MHHOSTVER)%%%s%%g\n", "-n");
367     else
368         fprintf (fp, "s%%@(MHHOSTVER)%%%s%%g\n", "");
369
370     if (strcmp (manuals, "gen") == 0 || strcmp (manuals, "none") == 0)
371         fprintf (fp, "s%%@(MHMANGEN)%%%s%%g\n", "#"); /* comment char */
372     else
373         fprintf (fp, "s%%@(MHMANGEN)%%%s%%g\n", "");
374
375     fprintf (fp, "s%%@(MHEDITOR)%%%s%%g\n", SVAL (editor));
376     fprintf (fp, "s%%@(MHCONFIG)%%%s%%g\n", SVAL (myopts));
377     fprintf (fp, "s%%@(MHCOMPILER)%%%s%%g\n", SVAL (compiler));
378     fprintf (fp, "s%%@(CP)%%%s%%g\n", SVAL (copy));
379     fprintf (fp, "s%%@(LN)%%%s%%g\n", SVAL (ln));
380     fprintf (fp, "s%%@(LEX)%%%s%%g\n", SVAL (lex));
381     if (ccoptions)
382         fprintf (fp, "s%%@(MHOPTIONS)%%%s %s%%g\n",
383                 SVAL (options), SVAL (ccoptions));
384     else
385         fprintf (fp, "s%%@(MHOPTIONS)%%%s %s%%g\n",
386                 SVAL (options), "-O");
387     fprintf (fp, "s%%@(LDOPTIONS)%%%s%%g\n", SVAL (ldoptions));
388     fprintf (fp, "s%%@(LDOPTLIB)%%%s%%g\n", SVAL (ldoptlibs));
389     fprintf (fp, "s%%@(LDCURSES)%%%s%%g\n", SVAL (curses));
390
391     if (strcmp (bboards, "off") == 0)
392         fprintf (fp, "/^@BEGIN: BBOARDS$/,/^@END: BBOARDS$/d\n");
393     else
394         fprintf (fp, "/^@BEGIN: BBOARDS$/d\n/^@END: BBOARDS$/d\n");
395     fprintf (fp, "s%%@(BBHOME)%%%s%%g\n", SVAL (bbhome));
396     if (strcmp (bbdelivery, "off") == 0)
397         fprintf (fp, "/^@BEGIN: BBSERVER$/,/^@END: BBSERVER$/d\n");
398     else
399         fprintf (fp, "/^@BEGIN: BBSERVER$/d\n/^@END: BBSERVER$/d\n");
400
401     if (strcmp (debug, "on") == 0) {
402         fprintf (fp, "/^@BEGIN: DEBUG$/d\n/^@END: DEBUG$/d\n");
403         fprintf (fp, "/^@BEGIN: OPTIM$/,/^@END: OPTIM$/d\n");
404     }
405     else {
406         fprintf (fp, "/^@BEGIN: DEBUG$/,/^@END: DEBUG$/d\n");
407         fprintf (fp, "/^@BEGIN: OPTIM$/d\n/^@END: OPTIM$/d\n");
408     }
409
410     if (strcmp (mailgroup, "off")) { /* for SYS5 sgid-inc */
411         fprintf (fp, "/^@BEGIN: MAILGROUP$/d\n/^@END: MAILGROUP$/d\n");
412         fprintf (fp, "s%%@(MAILGROUP)%%%s%%g\n", SVAL (mailgroup));
413     }
414     else
415         fprintf (fp, "/^@BEGIN: MAILGROUP$/,/^@END: MAILGROUP$/d\n");
416
417     if (strcmp (oldload, "on") == 0)
418         fprintf (fp, "/^@BEGIN: OLDLOAD$/d\n/^@END: OLDLOAD$/d\n");
419     else
420         fprintf (fp, "/^@BEGIN: OLDLOAD$/,/^@END: OLDLOAD$/d\n");
421     if (strcmp (oldload, "off") == 0)
422         fprintf (fp, "/^@BEGIN: NEWLOAD$/d\n/^@END: NEWLOAD$/d\n");
423     else
424         fprintf (fp, "/^@BEGIN: NEWLOAD$/,/^@END: NEWLOAD$/d\n");
425
426 /* \f */
427
428     if (strcmp (ranlib, "on") == 0) {
429         fprintf (fp, "/^@BEGIN: RANLIB$/d\n/^@END: RANLIB$/d\n");
430         fprintf (fp, "/^@BEGIN: LORDER$/,/^@END: LORDER$/d\n");
431     }
432     else {
433         fprintf (fp, "/^@BEGIN: LORDER$/d\n/^@END: LORDER$/d\n");
434         fprintf (fp, "/^@BEGIN: RANLIB$/,/^@END: RANLIB$/d\n");
435     }
436
437     if (strcmp (sharedlib, "off")) {    /* if not off */
438         fprintf (fp, "/^@BEGIN: SHAREDLIB$/d\n/^@END: SHAREDLIB$/d\n");
439         fprintf (fp, "/^@BEGIN: STDLIB$/,/^@END: STDLIB$/d\n");
440         fprintf (fp, "s%%@(SLIBDIR)%%%s%%g\n", slibdir);
441         fprintf (fp, "s%%@(SLIBVER)%%%s%%g\n", MHSLIBVER);
442         fprintf (fp, "s%%@(SLFLAGS)%%%s%%g\n", SVAL(slflags));
443         if (strcmp (sharedlib, "secure") == 0)
444             fprintf (fp, "s%%@(SLDFLAG)%%-L%s%%g\n",slibdir);
445         else
446             fprintf (fp, "s%%@(SLDFLAG)%%%%g\n");
447     }
448     else {
449         fprintf (fp, "/^@BEGIN: STDLIB$/d\n/^@END: STDLIB$/d\n");
450         fprintf (fp, "/^@BEGIN: SHAREDLIB$/,/^@END: SHAREDLIB$/d\n");
451     }
452     if (strcmp (sharedlib, "sun4") == 0 || strcmp (sharedlib, "on") == 0)
453         fprintf (fp, "/^@BEGIN: SUN4SHLIB$/d\n/^@END: SUN4SHLIB$/d\n");
454     else
455         fprintf (fp, "/^@BEGIN: SUN4SHLIB$/,/^@END: SUN4SHLIB$/d\n");
456     if (strcmp (sharedlib, "sys5") == 0)
457         fprintf (fp, "/^@BEGIN: SYS5SHLIB$/d\n/^@END: SYS5SHLIB$/d\n");
458     else
459         fprintf (fp, "/^@BEGIN: SYS5SHLIB$/,/^@END: SYS5SHLIB$/d\n");
460
461 /* \f */
462
463     if (flag || ((mtsnum == mmdf || mtsnum == mmdf2) && !smtp)) {
464         fprintf (fp, "/^@BEGIN: MMDFMTS$/d\n/^@END: MMDFMTS$/d\n");
465         if (mtsnum == mmdf)
466             fprintf (fp, "/^@BEGIN: MMDFIMTS$/d\n/^@END: MMDFIMTS$/d\n");
467         else
468             fprintf (fp, "/^@BEGIN: MMDFIMTS$/,/^@END: MMDFIMTS$/d\n");
469         if (mtsnum == mmdf2)
470             fprintf (fp, "/^@BEGIN: MMDFIIMTS$/d\n/^@END: MMDFIIMTS$/d\n");
471         else
472             fprintf (fp, "/^@BEGIN: MMDFIIMTS$/,/^@END: MMDFIIMTS$/d\n");
473     }
474     else {
475         fprintf (fp, "/^@BEGIN: MMDFMTS$/,/^@END: MMDFMTS$/d\n");
476         fprintf (fp, "/^@BEGIN: MMDFIMTS$/,/^@END: MMDFIMTS$/d\n");
477         fprintf (fp, "/^@BEGIN: MMDFIIMTS$/,/^@END: MMDFIIMTS$/d\n");
478     }
479
480     if (mtsnum == mh)
481         fprintf (fp, "/^@BEGIN: MHMTS$/d\n/^@END: MHMTS$/d\n");
482     else
483         fprintf (fp, "/^@BEGIN: MHMTS$/,/^@END: MHMTS$/d\n");
484
485     if (!flag && (mtsnum == sendmail || smtp))
486         fprintf (fp, "/^@BEGIN: SENDMTS$/d\n/^@END: SENDMTS$/d\n");
487     else
488         fprintf (fp, "/^@BEGIN: SENDMTS$/,/^@END: SENDMTS$/d\n");
489
490     switch (mtsnum) {
491         case mh:
492         case sendmail:
493         case mmdf:
494             fprintf (fp, "/^@BEGIN: SENDMTSHACK$/d\n/^@END: SENDMTSHACK$/d\n");
495             break;
496
497         default:
498             fprintf (fp, "/^@BEGIN: SENDMTSHACK$/,/^@END: SENDMTSHACK$/d\n");
499             break;
500     }
501
502 /* \f */
503
504     /* special hack for support/pop/popser.c */
505     fprintf (fp, "s%%@(POPUUMBOX)%%%s%%g\n",
506             mtsnum == sendmail ? "-DPOPUUMBOX" : "");
507
508     if (smtp)
509         fprintf (fp, "/^@BEGIN: SMTP$/d\n/^@END: SMTP$/d\n");
510     else
511         fprintf (fp, "/^@BEGIN: SMTP$/,/^@END: SMTP$/d\n");
512
513     if (strcmp (pop, "on") == 0)
514         fprintf (fp, "/^@BEGIN: POP$/d\n/^@END: POP$/d\n");
515     else
516         fprintf (fp, "/^@BEGIN: POP$/,/^@END: POP$/d\n");
517
518     if (strcmp (bboards, "pop") == 0)
519         fprintf (fp, "/^@BEGIN: BPOP$/d\n/^@END: BPOP$/d\n");
520     else
521         fprintf (fp, "/^@BEGIN: BPOP$/,/^@END: BPOP$/d\n");
522
523     if (strcmp (bboards, "nntp") == 0)
524         fprintf (fp, "/^@BEGIN: NNTP$/d\n/^@END: NNTP$/d\n");
525     else
526         fprintf (fp, "/^@BEGIN: NNTP$/,/^@END: NNTP$/d\n");
527
528     if (strcmp (mf, "on") == 0)
529         fprintf (fp, "/^@BEGIN: MF$/d\n/^@END: MF$/d\n");
530     else
531         fprintf (fp, "/^@BEGIN: MF$/,/^@END: MF$/d\n");
532
533     fprintf (fp, "s%%@(MHREMOVE)%%%s%%g\n", SVAL (removeit));
534
535     for (op = copts; op->c_name; op++) {
536         fprintf (fp, op->c_value ? "/^@BEGIN: %s$/d\n/^@END: %s$/d\n" :
537                                  "/^@BEGIN: %s$/,/^@END: %s$/d\n",
538                      op->c_name, op->c_name);
539     }
540
541     (void) fclose (fp);
542 }
543
544 /* \f */
545
546 static  do_files () {
547     char  **pp;
548
549     for (pp = files; *pp; pp++)
550         shell ("rm -f %s; sed -f %s < config/%s > %s",
551                 *pp, SED, tail (*pp), *pp);
552 }
553
554
555 static  do_doc () {
556     shell ("./mhdoc");
557 }
558
559
560 static  do_make () {
561     char    buffer[BUFSIZ];
562     struct pair *pp;
563
564     for (pp = makefiles; pp -> infile; pp++) {
565         (void) sprintf (buffer, MAKE, pp -> outfile);
566         shell ("rm -f %s; sed -f %s < %s > %s",
567                 buffer, SED, pp -> infile, buffer);
568     }
569 }
570
571 /* \f */
572
573 /* VARARGS */
574
575 static  shell (fmt, a, b, c, d)
576 char   *fmt,
577        *a,
578        *b,
579        *c,
580        *d;
581 {
582     char    buffer[BUFSIZ];
583
584     (void) sprintf (buffer, fmt, a, b, c, d);
585     printf ("%s\n", buffer);
586     (void) fflush (stdout);
587
588     if (system (buffer))
589         adios (NULLCP, "failed");
590 }
591
592 /* \f */
593
594 static  arginit (vec)
595 char  **vec;
596 {
597     int     i;
598     char   *ap,
599            *cp,
600            *dp,
601             buffer[BUFSIZ];
602     struct bind *bp;
603     FILE * fp;
604
605     myname = tail (*vec);
606     printf (BANNER, myname);
607     (void) fflush (stdout);
608     
609     for (vec++; *vec; vec++) {
610         if (strcmp (*vec, "-D") == 0) {
611             sedP = 1; filesP = makeP = 0; docP = 2;
612             continue;
613         }
614         if (strcmp (*vec, "-s") == 0) {
615             sedP = !sedP;
616             continue;
617         }
618         if (strcmp (*vec, "-f") == 0) {
619             filesP = !filesP;
620             continue;
621         }
622         if (strcmp (*vec, "-d") == 0) {
623             docP = !docP;
624             continue;
625         }
626         if (strcmp (*vec, "-m") == 0) {
627             makeP = !makeP;
628             continue;
629         }
630         if (strcmp (*vec, "-help") == 0) {
631             printf ("usage: %s [opt] file\n", myname);
632             printf ("%s\n%s\n%s\n%s\n",
633                 " -s\tno sed files", " -f\tno config files",
634                 " -d\tno doc files", " -m\tno makefiles");
635             exit (0);
636         }
637         break;
638     }
639     if ((config = *vec) == NULL || vec[1] != NULL) /* no arg or too many */
640         adios (NULLCP, "usage: %s file", myname);
641
642 /* \f */
643
644     if ((fp = fopen (config, "r")) == NULL)
645         adios (config, "unable to read");
646
647     while (fgets (buffer, sizeof buffer, fp)) {
648         if (ap = index (buffer, '\n'))
649             *ap-- = '\0';
650         else
651             ap = &buffer[strlen (buffer) - 1];
652         while (ap >= buffer)
653             if (isspace (*ap))
654                 *ap = '\0';
655             else
656                 break;
657         for (cp = buffer; isspace (*cp); cp++)
658             continue;
659         if (*cp == '\0' || *cp == '#')
660             continue;
661         for (ap = cp; *ap; ap++)
662             if (isspace (*ap) || *ap == ':') {
663                 *ap++ = '\0';
664                 while (isspace (*ap))
665                     ap++;
666                 break;
667             }
668         for (bp = binds; bp -> keyword; bp++)
669             if (strcmp (bp -> keyword, cp) == 0)
670                 break;
671         if (bp -> keyword == NULL)
672             adios (NULLCP, "unknown option %s in %s", cp, config);
673         else
674             if (*(bp -> value) == NULL || !(bp -> flags & BD_ADD))
675                 *(bp -> value) = strdup (ap);
676             else
677                 *(bp -> value) = stradd (ap, stradd (" ", *(bp -> value)));
678     }
679
680     (void) fclose (fp);
681
682 /* \f */
683
684     if (binpath == NULL)
685         adios (NULLCP, "bin must be specified in %s", config);
686     trim (binpath);
687
688     if (strcmp (bboards, "on") && strcmp (bboards, "off") &&
689         strcmp (bboards, "pop") && strcmp (bboards, "nntp"))
690         adios (NULLCP, "bboards should be %s not %s",
691                 "either \"on\", \"off\", \"pop\" or \"nntp\"", bboards);
692     if (strcmp (bboards, "off") == 0 && strcmp (bbdelivery, "off"))
693         adios (NULLCP, 
694             "you cannot have \"bbdelivery\" \"%s\" with \"bboards\" \"%s\"",
695             bbdelivery, bboards);
696     if (bbhome == NULL)
697         adios (NULLCP, "bbhome must be specified in %s", config);
698     trim (bbhome);
699
700     if (strcmp (debug, "on") && strcmp (debug, "off"))
701         adios (NULLCP, "debug should be either \"on\" or \"off\", not %s",
702                 debug);
703
704     if (etcpath == NULL)
705         adios (NULLCP, "etc must be specified in %s", config);
706     trim (etcpath);
707
708     if (strcmp (mailgroup, "off"))      /* if not "off" */
709         add_option ("MAILGROUP");
710     if (mailpath == NULL)
711         adios (NULLCP, "mail must be specified in %s", config);
712     trim (mailpath);
713     if (*mailpath == '/')
714         maildir = mailpath;
715     else
716         mailfile = mailpath;
717
718     if (cp = index (manuals, '/')) {    /* "standard/cat" */
719         *cp++ = 0;
720         mancat = cp;
721         if (strcmp (mancat, "cat"))
722             adios (NULLCP,"invalid manuals setting: %s/%s",manuals, mancat);
723     }
724     if (strcmp (manuals, "standard")
725             && strcmp (manuals, "bsd44")
726             && strcmp (manuals, "local")
727             && strcmp (manuals, "new")
728             && strcmp (manuals, "old")
729             && strcmp (manuals, "gen")
730             && strcmp (manuals, "none"))
731         adios (NULLCP,"invalid manuals setting: %s",manuals);
732
733     if (mts == NULL)
734         adios (NULLCP, "mts must be specified in %s", config);
735     for (i = 0; mtsopts[i].mtskey; i++)
736         if (strcmp (mts, mtsopts[i].mtskey) == 0)
737             break;
738     if ((mtsnum = mtsopts[i].code) == unknown)
739         adios (NULLCP, "invalid mts setting: %s", mts);
740     add_option (mtsopts[i].optval);
741     smtp = mtsopts[i].mtsflags & DOSMTP;
742     if (mtsopts[i].mtsflags & NOMF)
743         mf = "off";             /* hack... */
744
745     if (strcmp (pop, "on") && strcmp (pop, "off"))
746         adios (NULLCP, "pop should be either \"on\" or \"off\", not %s", pop);
747     if (strcmp (pop, "on") == 0)
748         add_option ("POP");
749
750     if (strcmp (bboards, "pop") == 0) {
751         add_option ("BPOP");
752         if (strcmp (pop, "on"))
753             adios (NULLCP, "bboards \"pop\" requires pop \"on\"");
754     }
755     else if (strcmp (bboards, "nntp") == 0) {
756         add_option ("BPOP");/* used by msh.c & bbc.c, but see also pshsbr.c */
757         add_option ("NNTP");
758         if (mpop)
759             adios (NULLCP,
760                 "bboards \"nntp\" is incompatible with \"options MPOP\"");
761     }
762
763     if (strcmp (mf, "on") && strcmp (mf, "off"))
764         adios (NULLCP, "mf should be either \"on\" or \"off\", not %s", mf);
765     if (strcmp (mf, "on") == 0)
766         add_option ("MF");
767
768     if (sprntf && strcmp (sprntf, "char *")) {/* this defaults to "char *" */
769         if (strcmp (sprntf, "int"))
770             adios (NULLCP,
771                     "sprintf should be either \"int\" or \"char *\", not %s",
772                     sprntf);
773         add_option ("SPRINTFTYPE=int");
774     }
775
776     if (strcmp (sharedlib, "on") && strcmp (sharedlib, "off")
777             && strcmp (sharedlib, "sun4") && strcmp (sharedlib, "sys5")
778             && strcmp (sharedlib, "secure"))
779         adios (NULLCP,
780             "sharedlib should be either \"sun4\", \"sys5\", or \"off\", not %s",
781             sharedlib);
782
783     (void) sprintf(buffer, "TYPESIG=%s", signl);
784     add_option (buffer);
785
786 /* loop over options string and add -D ccoptions */
787
788     begin_myopt ();
789     if (cp = options) {
790         for (ap = cp; *ap; ap++)
791             if (isspace (*ap))
792                 *ap = ' ';
793         options = NULL;
794         for (ap = cp; dp = index (ap, ' '); ap = dp) {
795             *dp++ = '\0';
796             add_myopt (ap);
797             (void) sprintf (buffer, "%s-D%s", options ? " " : "", ap);
798             ap = buffer;
799             options = stradd (ap, options);
800             while (isspace (*dp))
801                 dp++;
802         }
803         if (*ap) {
804             add_myopt (ap);
805             (void) sprintf (buffer, "%s-D%s", options ? " " : "", ap);
806             ap = buffer;
807             options = stradd (ap, options);
808         }
809         free (cp);
810     }
811     end_myopt ();
812     if (strcmp (bboards, "nntp") == 0 && mpop)
813         adios (NULLCP,
814                 "bboards \"nntp\" is incompatible with \"options MPOP\"");
815 }
816
817 /* \f */
818
819 static  add_option (s)
820 char   *s;
821 {
822     options = options ? stradd (s, stradd (" ", options)) : strdup (s);
823 }
824
825
826 begin_myopt () {
827     myopts = strdup ("char *options[] = {");
828 }
829
830
831 add_myopt (s)
832 char   *s;
833 {
834     int     len;
835     char   *bp,
836             buffer[BUFSIZ];
837     struct copt *op;
838     static int  nameoutput = 0;
839     static int  linepos = 0;
840     static int  outputlinelen = 72;
841
842     for (op = copts; op->c_name; op++)
843         if (!strncmp (op->c_name,s,strlen(op->c_name))) {
844             op->c_value = 1;
845             break;
846         }
847
848     if (strcmp (s, "MPOP") == 0)
849         mpop = 1;
850     if (smtp && strcmp (s, "BERK") == 0) {
851         fprintf (stderr, "\"options BERK\" overriding smtp suffix...\n");
852         smtp = 0;
853     }
854     if (!nameoutput) {
855         printf ("%s: ", bp = "options");
856         linepos += (nameoutput = strlen (bp) + 2);
857     }
858     len = strlen (s);
859     if (linepos != nameoutput)
860         if (len + linepos + 3 > outputlinelen)
861             printf ("\n%*s", linepos = nameoutput, "");
862         else
863             printf (" "), linepos++;
864     printf ("[%s]", s);
865     linepos += len + 2;
866     (void) fflush (stdout);
867
868     bp = buffer;
869     *bp++ = '"';
870     while (*s) {
871         if (*s == '"')
872             *bp++ = QUOTE, *bp++ = QUOTE;
873         *bp++ = *s++;
874     }
875     (void) strcpy (bp, "\", ");
876     insopt (buffer);
877 }
878
879
880 end_myopt () {
881     printf ("\n");
882     (void) fflush (stdout);
883     mkopts();
884     myopts = stradd ("NULL};", myopts);
885 }
886
887 /* \f */
888
889 static  trim (s)
890 char   *s;
891 {
892     char   *p;
893
894     if (s == NULL || (p = rindex (s, '/')) == NULL)
895         return;
896     if (*++p == '\0')
897         *--p = '\0';
898 }
899
900
901 static char *tail (s)
902 char   *s;
903 {
904     char   *p;
905
906     if (p = rindex (s, '/'))
907         p++;
908     return ((p == NULL || *p == '\0') ? s : p);
909 }
910
911 /* \f */
912
913 static char *stradd (s1, s2)
914 char   *s1,
915        *s2;
916 {
917     char   *p;
918
919     if (s1 == NULL || *s1 == '\0')
920         return s2;
921     if (s2 == NULL)
922         return strdup (s1);
923     if ((p = malloc ((unsigned) (strlen (s1) + strlen (s2) + 2))) == NULL)
924         adios (NULLCP, "insufficient memory");
925
926     (void) sprintf (p, "%s%s", s2, s1);
927     if (s2)
928         free (s2);
929     return p;
930 }
931
932
933 static char *strdup (s)
934 char   *s;
935 {
936     char   *p;
937
938     if ((p = malloc ((unsigned) (strlen (s) + 1))) == NULL)
939         adios (NULLCP, "insufficient memory");
940
941     (void) strcpy (p, s);
942     return p;
943 }
944
945 /* \f */
946
947 #ifdef  notdef
948 /* these used to be for SYS5 machines, but now this is compiled
949  * with -DSYS5 which redefines the SYS5 str[r]chr names to [r]index.
950  */
951 static char *index (s, c)
952 char   *s,
953         c;
954 {
955     char    i;
956
957     while (i = *s++)
958         if (i == c)
959             return (s - 1);
960
961     return NULL;
962 }
963
964
965 static char *rindex (s, c)
966 char   *s,
967         c;
968 {
969     char    i,
970            *t;
971
972     t = NULL;
973     while (i = *s++)
974         if (i == c)
975             t = s - 1;
976
977     return t;
978 }
979 #endif /* notdef */
980
981 /* \f */
982
983 /* VARARGS */
984
985 adios (what, fmt, a, b, c)
986 char   *what,
987        *fmt,
988        *a,
989        *b,
990        *c;
991 {
992     (void) fflush (stdout);
993
994     fprintf (stderr, "%s: ", myname);
995     fprintf (stderr, fmt, a, b, c);
996     if (what) {
997         (void) fputc (' ', stderr);
998         perror (what);
999     }
1000     else
1001         (void) fputc ('\n', stderr);
1002
1003     exit (1);
1004 }
1005
1006 /* quick and dirty ordering of options for readability */
1007
1008 struct opt {
1009     char *s;
1010     struct opt *n;
1011 };
1012
1013 static struct opt *optp = (struct opt *)NULL;
1014
1015 static void
1016 insopt(s)
1017 char *s;        /* string for sorting */
1018 {
1019     struct opt  *p,
1020                 *np,
1021                 *lp = (struct opt *)NULL;
1022
1023     if ((np = (struct opt *) malloc ((unsigned) sizeof (struct opt))) == 
1024             (struct opt *)NULL)
1025         adios (NULL, "unable to malloc opt");
1026     np -> s = strdup(s);
1027     np -> n = (struct opt *)NULL;
1028
1029     for (p = optp; p; lp = p, p = p -> n) {
1030         if (strcmp (p->s, s) > 0)
1031             break;
1032     }
1033     if (p)
1034         np -> n = p;
1035     if (lp)
1036         lp -> n = np;
1037     else
1038         optp = np;
1039 }
1040
1041 static void
1042 mkopts()
1043 {
1044     struct opt *p;
1045
1046     for (p = optp; p; p = p -> n)
1047         myopts = stradd (p->s, myopts);
1048 }