Added lots of "(void)" casts to standard function calls.
[exim.git] / src / src / buildconfig.c
1 /* $Cambridge: exim/src/src/buildconfig.c,v 1.10 2005/06/27 14:29:43 ph10 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2005 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
10
11 /*************************************************
12 *       Build configuration header for Exim      *
13 *************************************************/
14
15 /* This auxiliary program builds the file config.h by the following
16 process:
17
18 First, it determines the size of off_t and time_t variables, and generates
19 macro code to define OFF_T_FMT and TIME_T_FMT as suitable formats, if they are
20 not already defined in the system-specific header file.
21
22 Then it reads Makefile, looking for certain OS-specific definitions which it
23 uses to define some specific macros. Finally, it reads the defaults file
24 config.h.defaults.
25
26 The defaults file contains normal C #define statements for various macros; if
27 the name of a macro is found in the environment, the environment value replaces
28 the default. If the default #define does not contain any value, then that macro
29 is not copied to the created file unless there is some value in the
30 environment.
31
32 This program is compiled and run as part of the Make process and is not
33 normally called independently. */
34
35
36 #include <ctype.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/types.h>
41 #include <pwd.h>
42 #include <grp.h>
43
44 typedef struct {
45   char *name;
46   int *flag;
47 } have_item;
48
49 typedef struct {
50   char *name;
51   char *data;
52 } save_item;
53
54 static char *db_opts[] = { "", "USE_DB", "USE_GDBM", "USE_TDB" };
55
56 static int have_ipv6 = 0;
57 static int have_iconv = 0;
58
59 static char errno_quota[256];
60 static char ostype[256];
61 static char cc[256];
62
63 /* If any entry is an initial substring of another, the longer one must
64 appear first. */
65
66 static have_item have_list[] = {
67   { "HAVE_IPV6",      &have_ipv6 },
68   { "HAVE_ICONV",     &have_iconv },
69   { NULL, NULL}
70 };
71
72 static save_item save_list[] = {
73   { "ERRNO_QUOTA",    errno_quota },
74   { "OSTYPE",         ostype },
75   { "CC",             cc },
76   { NULL, NULL}
77 };
78
79
80 /* Subroutine to check a string for precisely one instance of "%s". If not,
81 bomb out. */
82
83 void
84 check_percent_ess(char *value, char *name)
85 {
86 int OK = 0;
87 char *p = strstr(value, "%s");
88 if (p != NULL) OK = strstr(p+2, "%s") == NULL;
89 if (!OK)
90   {
91   printf("\n*** \"%s\" (%s) must contain precisely one occurrence of\n"
92     "*** \"%%s\". Please review your build-time configuration.\n\n/", value,
93     name);
94   exit(1);
95   }
96 }
97
98
99 /* Main program */
100
101 int
102 main(int argc, char **argv)
103 {
104 off_t test_off_t = 0;
105 time_t test_time_t = 0;
106 FILE *base;
107 FILE *new;
108 int last_initial = 'A';
109 int linecount = 0;
110 int have_auth = 0;
111 int in_local_makefile = 0;
112 int use_which_db = 0;
113 int use_which_db_in_local_makefile = 0;
114 int support_crypteq = 0;
115 char buffer[1024];
116
117 if (argc != 1)
118   {
119   printf("*** Buildconfig: called with incorrect arguments\n");
120   exit(1);
121   }
122
123 new = fopen("config.h", "wb");
124 if (new == NULL)
125   {
126   printf("*** Buildconfig: failed to open config.h for output\n");
127   exit(1);
128   }
129
130 printf("Building configuration file config.h\n");
131
132 fprintf(new, "/*************************************************\n");
133 fprintf(new, "*           Configuration header for Exim        *\n");
134 fprintf(new, "*************************************************/\n\n");
135
136 fprintf(new, "/* This file was automatically generated from Makefile and "
137   "config.h.defaults,\n");
138 fprintf(new, "using values specified in the configuration file Local/Makefile.\n");
139 fprintf(new, "Do not edit it. Instead, edit Local/Makefile and "
140   "rerun make. */\n\n");
141
142 /* First, deal with the printing format for off_t variables. We assume that if
143 the size of off_t is greater than 4, "%lld" will be available as a format for
144 printing long long variables, and there will be support for the long long type.
145 This assumption is known to be OK for the common operating systems. */
146
147 fprintf(new, "#ifndef OFF_T_FMT\n");
148 if (sizeof(test_off_t) > 4)
149   {
150   fprintf(new, "#define OFF_T_FMT  \"%%lld\"\n");
151   fprintf(new, "#define LONGLONG_T long long int\n");
152   }
153 else
154   {
155   fprintf(new, "#define OFF_T_FMT  \"%%ld\"\n");
156   fprintf(new, "#define LONGLONG_T long int\n");
157   }
158 fprintf(new, "#endif\n\n");
159
160 /* Now do the same thing for time_t variables. If the length is greater than
161 4, we want to assume long long support (even if off_t was less than 4). If the
162 length is 4 or less, we can leave LONGLONG_T to whatever was defined above for
163 off_t. */
164
165 fprintf(new, "#ifndef TIME_T_FMT\n");
166 if (sizeof(test_time_t) > 4)
167   {
168   fprintf(new, "#define TIME_T_FMT  \"%%lld\"\n");
169   fprintf(new, "#undef  LONGLONG_T\n");
170   fprintf(new, "#define LONGLONG_T long long int\n");
171   }
172 else
173   {
174   fprintf(new, "#define TIME_T_FMT  \"%%ld\"\n");
175   }
176 fprintf(new, "#endif\n\n");
177
178 /* Now search the makefile for certain settings */
179
180 base = fopen("Makefile", "rb");
181 if (base == NULL)
182   {
183   printf("*** Buildconfig: failed to open Makefile\n");
184   (void)fclose(new);
185   exit(1);
186   }
187
188 errno_quota[0] = 0;    /* no over-riding value set */
189 ostype[0] = 0;         /* just in case */
190 cc[0] = 0;
191
192 while (fgets(buffer, sizeof(buffer), base) != NULL)
193   {
194   int i;
195   have_item *h;
196   save_item *s;
197   char *p = buffer + (int)strlen(buffer);
198   linecount++;
199   while (p > buffer && isspace((unsigned char)p[-1])) p--;
200   *p = 0;
201   p = buffer;
202   while (isspace((unsigned char)*p)) p++;
203
204   /* Notice when we hit the user's makefile */
205
206   if (strcmp(p, "# From Local/Makefile") == 0)
207     {
208     in_local_makefile = 1;
209     continue;
210     }
211
212   /* Remember the last DB option setting. If we hit two in the user's
213   Makefile, complain. */
214
215   for (i = 1; i < sizeof(db_opts)/sizeof(char *); i++)
216     {
217     int len = (int)strlen(db_opts[i]);
218     if (strncmp(p, db_opts[i], len) == 0 && (p[len] == ' ' || p[len] == '='))
219       {
220       if (in_local_makefile)
221         {
222         if (use_which_db_in_local_makefile)
223           {
224           printf("*** Only one of USE_DB, USE_GDBM, or USE_TDB should be "
225             "defined in Local/Makefile\n");
226           exit(1);
227           }
228         use_which_db_in_local_makefile = 1;
229         }
230       use_which_db = i;
231       break;
232       }
233     }
234   if (i < sizeof(db_opts)/sizeof(char *)) continue;
235
236   /* Items where we just save a boolean */
237
238   for (h = have_list; h->name != NULL; h++)
239     {
240     int len = (int)strlen(h->name);
241     if (strncmp(p, h->name, len) == 0)
242       {
243       p += len;
244       while (isspace((unsigned char)*p)) p++;
245       if (*p++ != '=')
246         {
247         printf("*** Buildconfig: syntax error in Makefile line %d\n", linecount);
248         exit(1);
249         }
250       while (isspace((unsigned char)*p)) p++;
251       if (strcmp(p, "YES") == 0 || strcmp(p, "yes") == 0) *(h->flag) = 1;
252         else *(h->flag) = 0;   /* Must reset in case multiple instances */
253       break;
254       }
255     }
256
257   if (h->name != NULL) continue;
258
259   /* Items where we save the complete string */
260
261   for (s = save_list; s->name != NULL; s++)
262     {
263     int len = (int)strlen(s->name);
264     if (strncmp(p, s->name, len) == 0)
265       {
266       p += len;
267       while (isspace((unsigned char)*p)) p++;
268       if (*p++ != '=')
269         {
270         printf("*** Buildconfig: syntax error in Makefile line %d\n", linecount);
271         exit(1);
272         }
273       while (isspace((unsigned char)*p)) p++;
274       strcpy(s->data, p);
275       }
276     }
277   }
278
279 fprintf(new, "#define HAVE_IPV6             %s\n",
280   have_ipv6? "TRUE" : "FALSE");
281
282 fprintf(new, "#define HAVE_ICONV            %s\n",
283   have_iconv? "TRUE" : "FALSE");
284
285 if (errno_quota[0] != 0)
286   fprintf(new, "\n#define ERRNO_QUOTA           %s\n", errno_quota);
287
288 if (strcmp(cc, "gcc") == 0 && strstr(ostype, "IRIX") != NULL)
289   {
290   fprintf(new, "\n/* This switch includes the code to fix the inet_ntoa() */");
291   fprintf(new, "\n/* bug when using gcc on an IRIX system. */");
292   fprintf(new, "\n#define USE_INET_NTOA_FIX");
293   }
294
295 fprintf(new, "\n");
296 (void)fclose(base);
297
298
299 /* Now handle the macros listed in the defaults */
300
301 base = fopen("../src/config.h.defaults", "rb");
302 if (base == NULL)
303   {
304   printf("*** Buildconfig: failed to open ../src/config.h.defaults\n");
305   (void)fclose(new);
306   exit(1);
307   }
308
309 while (fgets(buffer, sizeof(buffer), base) != NULL)
310   {
311   int i;
312   char name[256];
313   char *value;
314   char *p = buffer;
315   char *q = name;
316
317   while (*p == ' ' || *p == '\t') p++;
318
319   if (strncmp(p, "#define ", 8) != 0) continue;
320
321   p += 8;
322   while (*p == ' ' || *p == '\t') p++;
323
324   if (*p < last_initial) fprintf(new, "\n");
325   last_initial = *p;
326
327   while (*p && (isalnum((unsigned char)*p) || *p == '_')) *q++ = *p++;
328   *q = 0;
329
330   /* USE_DB, USE_GDBM, and USE_TDB are special cases. We want to have only
331   one of them set. The scan of the Makefile has saved which was the last one
332   encountered. */
333
334   for (i = 1; i < sizeof(db_opts)/sizeof(char *); i++)
335     {
336     if (strcmp(name, db_opts[i]) == 0)
337       {
338       if (use_which_db == i)
339         fprintf(new, "#define %s %.*syes\n", db_opts[i],
340           21 - (int)strlen(db_opts[i]), "                         ");
341       else
342         fprintf(new, "/* %s not set */\n", name);
343       break;
344       }
345     }
346   if (i < sizeof(db_opts)/sizeof(char *)) continue;
347
348   /* EXIM_USER is a special case. We look in the environment for EXIM_USER or
349   EXIM_UID (the latter for backward compatibility with Exim 3). If the value is
350   not numeric, we look up the user, and default the GID if found. Otherwise,
351   EXIM_GROUP or EXIM_GID must be in the environment. */
352
353   if (strcmp(name, "EXIM_UID") == 0)
354     {
355     uid_t uid = 0;
356     gid_t gid = 0;
357     int gid_set = 0;
358     char *username = NULL;
359     char *groupname = NULL;
360     char *s;
361     char *user = getenv("EXIM_USER");
362     char *group = getenv("EXIM_GROUP");
363
364     if (user == NULL) user = getenv("EXIM_UID");
365     if (group == NULL) group = getenv("EXIM_GID");
366
367     if (user == NULL)
368       {
369       printf("\n*** EXIM_USER has not been defined in any of the Makefiles in "
370         "the\n    \"Local\" directory. Please review your build-time "
371         "configuration.\n\n");
372       return 1;
373       }
374
375     while (isspace((unsigned char)(*user))) user++;
376     if (*user == 0)
377       {
378       printf("\n*** EXIM_USER is defined as an empty string in one of the "
379         "files\n    in the \"Local\" directory. Please review your build-time"
380         "\n    configuration.\n\n");
381       return 1;
382       }
383
384     for (s = user; *s != 0; s++)
385       {
386       if (iscntrl((unsigned char)(*s)))
387         {
388         printf("\n*** EXIM_USER contains the control character 0x%02X in one "
389           "of the files\n    in the \"Local\" directory. Please review your "
390           "build-time\n    configuration.\n\n", *s);
391         return 1;
392         }
393       }
394
395     /* Numeric uid given */
396
397     if (user[strspn(user, "0123456789")] == 0)
398       {
399       uid = (uid_t)atoi(user);
400       }
401
402     /* User name given. Normally, we look up the uid right away. However,
403     people building binary distributions sometimes want to retain the name till
404     runtime. This is supported if the name begins "ref:". */
405
406     else if (strncmp(user, "ref:", 4) == 0)
407       {
408       user += 4;
409       while (isspace(*user)) user++;
410       username = user;
411       gid_set = 1;
412       }
413
414     else
415       {
416       struct passwd *pw = getpwnam(user);
417       if (pw == NULL)
418         {
419         printf("\n*** User \"%s\" (specified in one of the Makefiles) does not "
420           "exist.\n    Please review your build-time configuration.\n\n",
421           user);
422         return 1;
423         }
424
425       uid = pw->pw_uid;
426       gid = pw->pw_gid;
427       gid_set = 1;
428       }
429
430     /* Use explicit group if set. */
431
432     if (group != NULL)
433       {
434       while (isspace((unsigned char)(*group))) group++;
435       if (*group == 0)
436         {
437         printf("\n*** EXIM_GROUP is defined as an empty string in one of "
438           "the files in the\n    \"Local\" directory. ");
439         if (gid_set)
440           {
441           printf("If you want the Exim group to be taken from the\n    "
442             "password data for the Exim user, just remove the EXIM_GROUP "
443             "setting.\n    Otherwise, p");
444           }
445         else printf("EXIM_USER is defined numerically, so there is no"
446           "\n    default for EXIM_GROUP and you must set it explicitly.\n    P");
447         printf("lease review your build-time configuration.\n\n");
448         return 1;
449         }
450
451       for (s = group; *s != 0; s++)
452         {
453         if (iscntrl((unsigned char)(*s)))
454           {
455           printf("\n*** EXIM_GROUP contains the control character 0x%02X in one "
456             "of the files\n    in the \"Local\" directory. Please review your "
457             "build-time\n    configuration.\n\n", *s);
458           return 1;
459           }
460         }
461
462       /* Group name given. This may be by reference or to be looked up now,
463       as for user. */
464
465       if (strncmp(group, "ref:", 4) == 0)
466         {
467         group += 4;
468         while (isspace(*group)) group++;
469         groupname = group;
470         }
471
472       else if (username != NULL)
473         {
474         groupname = group;
475         }
476
477       else if (group[strspn(group, "0123456789")] == 0)
478         {
479         gid = (gid_t)atoi(group);
480         }
481
482       else
483         {
484         struct group *gr = getgrnam(group);
485         if (gr == NULL)
486           {
487           printf("\n*** Group \"%s\" (specified in one of the Makefiles) does "
488             "not exist.\n   Please review your build-time configuration.\n\n",
489             group);
490           return 1;
491           }
492         gid = gr->gr_gid;
493         }
494       }
495
496     /* Else trouble unless found in passwd file with user */
497
498     else if (!gid_set)
499       {
500       printf("\n*** No group set for Exim. Please review your build-time "
501         "configuration.\n\n");
502       return 1;
503       }
504
505     /* Output user and group names or uid/gid. When names are set, uid/gid
506     are set to zero but will be replaced at runtime. */
507
508     if (username != NULL)
509       fprintf(new, "#define EXIM_USERNAME         \"%s\"\n", username);
510     if (groupname != NULL)
511       fprintf(new, "#define EXIM_GROUPNAME        \"%s\"\n", groupname);
512
513     fprintf(new, "#define EXIM_UID              %d\n", (int)uid);
514     fprintf(new, "#define EXIM_GID              %d\n", (int)gid);
515     continue;
516     }
517
518   /* CONFIGURE_OWNER and CONFIGURE_GROUP are special cases. We look in the
519   environment for first. If the value is not numeric, we look up the user or
520   group. A lot of this code is similar to that for EXIM_USER, but it's easier
521   to keep it separate. */
522
523   if (strcmp(name, "CONFIGURE_OWNER") == 0 ||
524       strcmp(name, "CONFIGURE_GROUP") == 0)
525     {
526     int isgroup = name[10] == 'G';
527     uid_t uid = 0;
528     gid_t gid = 0;
529     char *s;
530     char *username = NULL;
531     char *user = getenv(name);
532
533     if (user == NULL) user = "";
534     while (isspace((unsigned char)(*user))) user++;
535     if (*user == 0)
536       {
537       fprintf(new, "/* %s not set */\n", name);
538       continue;
539       }
540
541     for (s = user; *s != 0; s++)
542       {
543       if (iscntrl((unsigned char)(*s)))
544         {
545         printf("\n*** %s contains the control character 0x%02X in "
546           "one of the files\n    in the \"Local\" directory. Please review "
547           "your build-time\n    configuration.\n\n", name, *s);
548         return 1;
549         }
550       }
551
552     /* Numeric uid given */
553
554     if (user[strspn(user, "0123456789")] == 0)
555       {
556       if (isgroup)
557         gid = (gid_t)atoi(user);
558       else
559         uid = (uid_t)atoi(user);
560       }
561
562     /* Name given. Normally, we look up the uid or gid right away. However,
563     people building binary distributions sometimes want to retain the name till
564     runtime. This is supported if the name begins "ref:". */
565
566     else if (strncmp(user, "ref:", 4) == 0)
567       {
568       user += 4;
569       while (isspace(*user)) user++;
570       username = user;
571       }
572
573     else if (isgroup)
574       {
575       struct group *gr = getgrnam(user);
576       if (gr == NULL)
577         {
578         printf("\n*** Group \"%s\" (specified in one of the Makefiles) does not "
579           "exist.\n    Please review your build-time configuration.\n\n",
580           user);
581         return 1;
582         }
583       gid = gr->gr_gid;
584       }
585
586     else
587       {
588       struct passwd *pw = getpwnam(user);
589       if (pw == NULL)
590         {
591         printf("\n*** User \"%s\" (specified in one of the Makefiles) does not "
592           "exist.\n    Please review your build-time configuration.\n\n",
593           user);
594         return 1;
595         }
596       uid = pw->pw_uid;
597       }
598
599     /* Output user and group names or uid/gid. When names are set, uid/gid
600     are set to zero but will be replaced at runtime. */
601
602     if (username != NULL)
603       {
604       if (isgroup)
605         fprintf(new, "#define CONFIGURE_GROUPNAME         \"%s\"\n", username);
606       else
607         fprintf(new, "#define CONFIGURE_OWNERNAME         \"%s\"\n", username);
608       }
609
610     if (isgroup)
611       fprintf(new, "#define CONFIGURE_GROUP              %d\n", (int)gid);
612     else
613       fprintf(new, "#define CONFIGURE_OWNER              %d\n", (int)uid);
614     continue;
615     }
616
617   /* FIXED_NEVER_USERS is another special case. Look up the uid values and
618   create suitable initialization data for a vector. */
619
620   if (strcmp(name, "FIXED_NEVER_USERS") == 0)
621     {
622     char *list = getenv("FIXED_NEVER_USERS");
623     if (list == NULL)
624       {
625       fprintf(new, "#define FIXED_NEVER_USERS     0\n");
626       }
627     else
628       {
629       int count = 1;
630       int i, j;
631       uid_t *vector;
632       char *p = list;
633       while (*p != 0) if (*p++ == ':') count++;
634
635       vector = malloc((count+1) * sizeof(uid_t));
636       vector[0] = (uid_t)count;
637
638       for (i = 1, j = 0; i <= count; list++, i++)
639         {
640         char name[64];
641
642         p = list;
643         while (*list != 0 && *list != ':') list++;
644         strncpy(name, p, list-p);
645         name[list-p] = 0;
646
647         if (name[0] == 0)
648           {
649           continue;
650           }
651         else if (name[strspn(name, "0123456789")] == 0)
652           {
653           vector[j++] = (uid_t)atoi(name);
654           }
655         else
656           {
657           struct passwd *pw = getpwnam(name);
658           if (pw == NULL)
659             {
660             printf("\n*** User \"%s\" (specified for FIXED_NEVER_USERS in one of the Makefiles) does not "
661               "exist.\n    Please review your build-time configuration.\n\n",
662               name);
663             return 1;
664             }
665           vector[j++] = pw->pw_uid;
666           }
667         }
668       fprintf(new, "#define FIXED_NEVER_USERS     %d", j);
669       for (i = 0; i < j; i++) fprintf(new, ", %d", (unsigned int)vector[i]);
670       fprintf(new, "\n");
671       }
672     continue;
673     }
674
675   /* WITH_CONTENT_SCAN is another special case: it must be set if either it or
676   WITH_OLD_DEMIME is set. */
677
678   if (strcmp(name, "WITH_CONTENT_SCAN") == 0)
679     {
680     char *wcs = getenv("WITH_CONTENT_SCAN");
681     char *wod = getenv("WITH_OLD_DEMIME");
682     if (wcs != NULL || wod != NULL)
683       fprintf(new, "#define WITH_CONTENT_SCAN     yes\n");
684     else fprintf(new, "/* WITH_CONTENT_SCAN not set */\n");
685     continue;
686     }
687
688   /* Otherwise, check whether a value exists in the environment. Remember if
689   it is an AUTH setting or SUPPORT_CRYPTEQ. */
690
691   if ((value = getenv(name)) != NULL)
692     {
693     int len;
694     len = 21 - (int)strlen(name);
695
696     if (strncmp(name, "AUTH_", 5) == 0) have_auth = 1;
697     if (strncmp(name, "SUPPORT_CRYPTEQ", 15) == 0) support_crypteq = 1;
698
699     /* The text value of LDAP_LIB_TYPE refers to a macro that gets set. */
700
701     if (strcmp(name, "LDAP_LIB_TYPE") == 0)
702       {
703       if (strcmp(value, "NETSCAPE") == 0 ||
704           strcmp(value, "UMICHIGAN") == 0 ||
705           strcmp(value, "OPENLDAP1") == 0 ||
706           strcmp(value, "OPENLDAP2") == 0 ||
707           strcmp(value, "SOLARIS") == 0 ||
708           strcmp(value, "SOLARIS7") == 0)              /* Compatibility */
709         {
710         fprintf(new, "#define LDAP_LIB_%s\n", value);
711         }
712       else
713         {
714         printf("\n*** LDAP_LIB_TYPE=%s is not a recognized LDAP library type."
715           "\n*** Please review your build-time configuration.\n\n", value);
716         return 1;
717         }
718       }
719
720     else if (strcmp(name, "RADIUS_LIB_TYPE") == 0)
721       {
722       if (strcmp(value, "RADIUSCLIENT") == 0 ||
723           strcmp(value, "RADIUSCLIENTNEW") == 0 ||
724           strcmp(value, "RADLIB") == 0)
725         {
726         fprintf(new, "#define RADIUS_LIB_%s\n", value);
727         }
728       else
729         {
730         printf("\n*** RADIUS_LIB_TYPE=%s is not a recognized RADIUS library type."
731           "\n*** Please review your build-time configuration.\n\n", value);
732         return 1;
733         }
734       }
735
736     /* Other macros get set to the environment value. */
737
738     else
739       {
740       fprintf(new, "#define %s ", name);
741       while(len-- > 0) fputc(' ', new);
742
743       /* LOG_FILE_PATH is now messy because it can be a path containing %s or
744       it can be "syslog" or ":syslog" or "syslog:path" or even "path:syslog". */
745
746       if (strcmp(name, "LOG_FILE_PATH") == 0)
747         {
748         char *ss = value;
749         for(;;)
750           {
751           char *pp;
752           char *sss = strchr(ss, ':');
753           if (sss != NULL)
754             {
755             strncpy(buffer, ss, sss-ss);
756             buffer[sss-ss] = 0;  /* For empty case */
757             }
758           else strcpy(buffer, ss);
759           pp = buffer + (int)strlen(buffer);
760           while (pp > buffer && isspace((unsigned char)pp[-1])) pp--;
761           *pp = 0;
762           if (buffer[0] != 0 && strcmp(buffer, "syslog") != 0)
763             check_percent_ess(buffer, name);
764           if (sss == NULL) break;
765           ss = sss + 1;
766           while (isspace((unsigned char)*ss)) ss++;
767           }
768         fprintf(new, "\"%s\"\n", value);
769         }
770
771       /* Timezone values and HEADERS_CHARSET get quoted */
772
773       else if (strcmp(name, "TIMEZONE_DEFAULT") == 0||
774                strcmp(name, "HEADERS_CHARSET") == 0)
775         fprintf(new, "\"%s\"\n", value);
776
777       /* For others, quote any paths and don't quote anything else */
778
779       else
780         {
781         if (value[0] == '/') fprintf(new, "\"%s\"\n", value);
782           else fprintf(new, "%s\n", value);
783         }
784       }
785     }
786
787   /* Value not defined in the environment; use the default */
788
789   else
790     {
791     char *t = p;
792     while (*p == ' ' || *p == '\t') p++;
793     if (*p != '\n') fputs(buffer, new); else
794       {
795       *t = 0;
796       if (strcmp(name, "BIN_DIRECTORY")   == 0 ||
797           strcmp(name, "CONFIGURE_FILE")  == 0)
798         {
799         printf("\n*** %s has not been defined in any of the Makefiles in the\n"
800           "    \"Local\" directory. "
801           "Please review your build-time configuration.\n\n", name);
802         return 1;
803         }
804
805       if (strcmp(name, "TIMEZONE_DEFAULT") == 0)
806         {
807         char *tz = getenv("TZ");
808         fprintf(new, "#define TIMEZONE_DEFAULT      ");
809         if (tz == NULL) fprintf(new, "NULL\n"); else
810           fprintf(new, "\"%s\"\n", tz);
811         }
812
813       else fprintf(new, "/* %s not set */\n", name);
814       }
815     }
816   }
817
818 (void)fclose(base);
819
820 /* If any AUTH macros were defined, ensure that SUPPORT_CRYPTEQ is also
821 defined. */
822
823 if (have_auth)
824   {
825   if (!support_crypteq) fprintf(new, "/* Force SUPPORT_CRYPTEQ for AUTH */\n"
826     "#define SUPPORT_CRYPTEQ\n");
827   }
828
829 /* End off */
830
831 fprintf(new, "\n/* End of config.h */\n");
832 (void)fclose(new);
833 return 0;
834 }
835
836 /* End of buildconfig.c */