TK/09
[exim.git] / src / src / buildconfig.c
CommitLineData
b1c749bb 1/* $Cambridge: exim/src/src/buildconfig.c,v 1.8 2005/06/16 14:10:13 ph10 Exp $ */
059ec3d9
PH
2
3/*************************************************
4* Exim - an Internet mail transport agent *
5*************************************************/
6
c988f1f4 7/* Copyright (c) University of Cambridge 1995 - 2005 */
059ec3d9
PH
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
16process:
17
b1c749bb
PH
18First, it determines the size of off_t variables, and generates macro code to
19define OFF_T_FMT as a suitable format, if it is not already defined in the
20system-specific header file.
21
22Then it reads Makefile, looking for certain OS-specific definitions which it
23uses to define some specific macros. Finally, it reads the defaults file
24config.h.defaults.
059ec3d9
PH
25
26The defaults file contains normal C #define statements for various macros; if
27the name of a macro is found in the environment, the environment value replaces
28the default. If the default #define does not contain any value, then that macro
29is not copied to the created file unless there is some value in the
30environment.
31
32This program is compiled and run as part of the Make process and is not
33normally 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
44typedef struct {
45 char *name;
46 int *flag;
47} have_item;
48
49typedef struct {
50 char *name;
51 char *data;
52} save_item;
53
54static char *db_opts[] = { "", "USE_DB", "USE_GDBM", "USE_TDB" };
55
56static int have_ipv6 = 0;
57static int have_iconv = 0;
58
59static char errno_quota[256];
60static char ostype[256];
61static char cc[256];
62
63/* If any entry is an initial substring of another, the longer one must
64appear first. */
65
66static have_item have_list[] = {
67 { "HAVE_IPV6", &have_ipv6 },
68 { "HAVE_ICONV", &have_iconv },
69 { NULL, NULL}
70};
71
72static 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,
81bomb out. */
82
83void
84check_percent_ess(char *value, char *name)
85{
86int OK = 0;
87char *p = strstr(value, "%s");
88if (p != NULL) OK = strstr(p+2, "%s") == NULL;
89if (!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
101int
102main(int argc, char **argv)
103{
b1c749bb 104off_t test_off_t = 0;
059ec3d9
PH
105FILE *base;
106FILE *new;
107int last_initial = 'A';
108int linecount = 0;
109int have_auth = 0;
110int in_local_makefile = 0;
111int use_which_db = 0;
112int use_which_db_in_local_makefile = 0;
113int support_crypteq = 0;
114char buffer[1024];
115
116if (argc != 1)
117 {
118 printf("*** Buildconfig: called with incorrect arguments\n");
119 exit(1);
120 }
121
122new = fopen("config.h", "wb");
123if (new == NULL)
124 {
125 printf("*** Buildconfig: failed to open config.h for output\n");
126 exit(1);
127 }
128
129printf("Building configuration file config.h\n");
130
131fprintf(new, "/*************************************************\n");
132fprintf(new, "* Configuration header for Exim *\n");
133fprintf(new, "*************************************************/\n\n");
134
135fprintf(new, "/* This file was automatically generated from Makefile and "
136 "config.h.defaults,\n");
137fprintf(new, "using values specified in the configuration file Local/Makefile.\n");
138fprintf(new, "Do not edit it. Instead, edit Local/Makefile and "
139 "rerun make. */\n\n");
140
b1c749bb
PH
141/* First, deal with the printing format for off_t variables. We assume that if
142the size of off_t is greater than 4, "%lld" will be available as a format for
143printing long long variables, and there will be support for the long long type.
144This assumption is known to be OK for the common operating systems. */
145
146fprintf(new, "#ifndef OFF_T_FMT\n");
147if (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 }
152else
153 {
154 fprintf(new, "#define OFF_T_FMT \"%%ld\"\n");
155 }
156fprintf(new, "#endif\n\n");
157
158/* Now search the makefile for certain settings */
059ec3d9
PH
159
160base = fopen("Makefile", "rb");
161if (base == NULL)
162 {
163 printf("*** Buildconfig: failed to open Makefile\n");
164 fclose(new);
165 exit(1);
166 }
167
168errno_quota[0] = 0; /* no over-riding value set */
169ostype[0] = 0; /* just in case */
170cc[0] = 0;
171
172while (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
259fprintf(new, "#define HAVE_IPV6 %s\n",
260 have_ipv6? "TRUE" : "FALSE");
261
262fprintf(new, "#define HAVE_ICONV %s\n",
263 have_iconv? "TRUE" : "FALSE");
264
265if (errno_quota[0] != 0)
266 fprintf(new, "\n#define ERRNO_QUOTA %s\n", errno_quota);
267
268if (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
275fprintf(new, "\n");
276fclose(base);
277
278
279/* Now handle the macros listed in the defaults */
280
281base = fopen("../src/config.h.defaults", "rb");
282if (base == NULL)
283 {
284 printf("*** Buildconfig: failed to open ../src/config.h.defaults\n");
285 fclose(new);
286 exit(1);
287 }
288
289while (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
35edf2ff
PH
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. */
059ec3d9 502
35edf2ff
PH
503 if (strcmp(name, "CONFIGURE_OWNER") == 0 ||
504 strcmp(name, "CONFIGURE_GROUP") == 0)
059ec3d9 505 {
8e669ac1 506 int isgroup = name[10] == 'G';
059ec3d9 507 uid_t uid = 0;
8e669ac1 508 gid_t gid = 0;
059ec3d9
PH
509 char *s;
510 char *username = NULL;
35edf2ff 511 char *user = getenv(name);
059ec3d9
PH
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 {
35edf2ff 525 printf("\n*** %s contains the control character 0x%02X in "
059ec3d9 526 "one of the files\n in the \"Local\" directory. Please review "
35edf2ff 527 "your build-time\n configuration.\n\n", name, *s);
059ec3d9
PH
528 return 1;
529 }
530 }
531
532 /* Numeric uid given */
533
534 if (user[strspn(user, "0123456789")] == 0)
535 {
35edf2ff
PH
536 if (isgroup)
537 gid = (gid_t)atoi(user);
8e669ac1 538 else
35edf2ff 539 uid = (uid_t)atoi(user);
059ec3d9
PH
540 }
541
35edf2ff 542 /* Name given. Normally, we look up the uid or gid right away. However,
059ec3d9
PH
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
35edf2ff
PH
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
059ec3d9
PH
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 }
059ec3d9
PH
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)
35edf2ff
PH
583 {
584 if (isgroup)
585 fprintf(new, "#define CONFIGURE_GROUPNAME \"%s\"\n", username);
8e669ac1 586 else
35edf2ff
PH
587 fprintf(new, "#define CONFIGURE_OWNERNAME \"%s\"\n", username);
588 }
8e669ac1 589
35edf2ff
PH
590 if (isgroup)
591 fprintf(new, "#define CONFIGURE_GROUP %d\n", (int)gid);
8e669ac1 592 else
35edf2ff 593 fprintf(new, "#define CONFIGURE_OWNER %d\n", (int)uid);
059ec3d9
PH
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;
926e1192 610 int i, j;
059ec3d9
PH
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
926e1192 618 for (i = 1, j = 0; i <= count; list++, i++)
059ec3d9
PH
619 {
620 char name[64];
8e669ac1 621
059ec3d9
PH
622 p = list;
623 while (*list != 0 && *list != ':') list++;
624 strncpy(name, p, list-p);
625 name[list-p] = 0;
8e669ac1 626
926e1192
PH
627 if (name[0] == 0)
628 {
8e669ac1
PH
629 continue;
630 }
926e1192 631 else if (name[strspn(name, "0123456789")] == 0)
059ec3d9 632 {
926e1192 633 vector[j++] = (uid_t)atoi(name);
059ec3d9
PH
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 }
926e1192 645 vector[j++] = pw->pw_uid;
059ec3d9
PH
646 }
647 }
926e1192
PH
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");
059ec3d9
PH
651 }
652 continue;
653 }
654
8e669ac1
PH
655 /* WITH_CONTENT_SCAN is another special case: it must be set if either it or
656 WITH_OLD_DEMIME is set. */
c6e692d7
PH
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;
8e669ac1 666 }
c6e692d7 667
059ec3d9
PH
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 ||
7766a4f0 703 strcmp(value, "RADIUSCLIENTNEW") == 0 ||
059ec3d9
PH
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
798fclose(base);
799
800/* If any AUTH macros were defined, ensure that SUPPORT_CRYPTEQ is also
801defined. */
802
803if (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
811fprintf(new, "\n/* End of config.h */\n");
812fclose(new);
813return 0;
814}
815
816/* End of buildconfig.c */