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