1 /* $OpenBSD: mkheaders.c,v 1.18 2003/06/28 04:55:07 deraadt Exp $ */
2 /* $NetBSD: mkheaders.c,v 1.12 1997/02/02 21:12:34 thorpej Exp $ */
3
4 /*
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This software was developed by the Computer Systems Engineering group
9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10 * contributed to Berkeley.
11 *
12 * All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by the University of
15 * California, Lawrence Berkeley Laboratories.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * from: @(#)mkheaders.c 8.1 (Berkeley) 6/6/93
42 */
43
44 #include <sys/param.h>
45 #include <ctype.h>
46 #include <errno.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include "config.h"
51
52 __RCSID("$MirOS: src/usr.sbin/config/mkheaders.c,v 1.3 2008/06/13 15:20:01 tg Exp $");
53
54 static int emitcnt(struct nvlist *);
55 static int emitopt(struct nvlist *);
56 static int err(const char *, char *, FILE *);
57 static char *cntname(const char *);
58
59 /*
60 * Make headers containing counts, as needed.
61 */
62 int
mkheaders(void)63 mkheaders(void)
64 {
65 struct files *fi;
66 struct nvlist *nv;
67
68 for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
69 if (fi->fi_flags & FI_HIDDEN)
70 continue;
71 if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) &&
72 emitcnt(fi->fi_optf))
73 return (1);
74 }
75
76 for (nv = defoptions; nv != NULL; nv = nv->nv_next)
77 if (emitopt(nv))
78 return (1);
79
80 return (0);
81 }
82
83 static int
emitcnt(struct nvlist * head)84 emitcnt(struct nvlist *head)
85 {
86 struct nvlist *nv;
87 FILE *fp;
88 int cnt;
89 char nam[100];
90 char buf[BUFSIZ];
91 char fname[BUFSIZ];
92
93 (void)snprintf(fname, sizeof fname, "%s.h", head->nv_name);
94 if ((fp = fopen(fname, "r")) == NULL)
95 goto writeit;
96 nv = head;
97 while (fgets(buf, sizeof(buf), fp) != NULL) {
98 if (nv == NULL)
99 goto writeit;
100 if (sscanf(buf, "#define\t%99s\t%d", nam, &cnt) != 2 ||
101 strcmp(nam, cntname(nv->nv_name)) != 0 ||
102 cnt != nv->nv_int)
103 goto writeit;
104 nv = nv->nv_next;
105 }
106 if (ferror(fp))
107 return (err("read", fname, fp));
108 (void)fclose(fp);
109 if (nv == NULL)
110 return (0);
111 writeit:
112 if ((fp = fopen(fname, "w")) == NULL) {
113 (void)fprintf(stderr, "config: cannot write %s: %s\n",
114 fname, strerror(errno));
115 return (1);
116 }
117 for (nv = head; nv != NULL; nv = nv->nv_next)
118 if (fprintf(fp, "#define\t%s\t%d\n",
119 cntname(nv->nv_name), nv->nv_int) < 0)
120 return (err("writ", fname, fp));
121 if (fclose(fp))
122 return (err("writ", fname, NULL));
123 return (0);
124 }
125
126 static int
emitopt(struct nvlist * nv)127 emitopt(struct nvlist *nv)
128 {
129 struct nvlist *option;
130 char new_contents[BUFSIZ], buf[BUFSIZ];
131 char fname[BUFSIZ];
132 int totlen, nlines;
133 FILE *fp;
134
135 /*
136 * Generate the new contents of the file.
137 */
138 if ((option = ht_lookup(opttab, nv->nv_str)) == NULL)
139 totlen = snprintf(new_contents, sizeof new_contents,
140 "/* option `%s' not defined */\n",
141 nv->nv_str);
142 else {
143 if (option->nv_str != NULL)
144 totlen = snprintf(new_contents, sizeof new_contents,
145 "#define\t%s\t%s\n",
146 option->nv_name, option->nv_str);
147 else
148 totlen = snprintf(new_contents, sizeof new_contents,
149 "#define\t%s\n",
150 option->nv_name);
151 }
152
153 if (totlen < 0 || (size_t)totlen >= sizeof new_contents) {
154 fprintf(stderr, "config: string too long\n");
155 return (1);
156 }
157
158 /*
159 * Compare the new file to the old.
160 */
161 snprintf(fname, sizeof fname, "opt_%s.h", nv->nv_name);
162 if ((fp = fopen(fname, "r")) == NULL)
163 goto writeit;
164 nlines = 0;
165 while (fgets(buf, sizeof(buf), fp) != NULL) {
166 if (++nlines != 1 ||
167 strcmp(buf, new_contents) != 0)
168 goto writeit;
169 }
170 if (ferror(fp))
171 return (err("read", fname, fp));
172 (void)fclose(fp);
173 if (nlines == 1)
174 return (0);
175 writeit:
176 /*
177 * They're different, or the file doesn't exist.
178 */
179 if ((fp = fopen(fname, "w")) == NULL) {
180 (void)fprintf(stderr, "config: cannot write %s: %s\n",
181 fname, strerror(errno));
182 return (1);
183 }
184 if (fprintf(fp, "%s", new_contents) < 0)
185 return (err("writ", fname, fp));
186 if (fclose(fp))
187 return (err("writ", fname, fp));
188 return (0);
189 }
190
191 static int
err(const char * what,char * fname,FILE * fp)192 err(const char *what, char *fname, FILE *fp)
193 {
194
195 (void)fprintf(stderr, "config: error %sing %s: %s\n",
196 what, fname, strerror(errno));
197 if (fp)
198 (void)fclose(fp);
199 return (1);
200 }
201
202 static char *
cntname(const char * src)203 cntname(const char *src)
204 {
205 char *dst, c;
206 static char buf[100];
207
208 dst = buf;
209 *dst++ = 'N';
210 while ((c = *src++) != 0)
211 *dst++ = islower(c) ? toupper(c) : c;
212 *dst = 0;
213 return (buf);
214 }
215