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