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