Bug Summary

File:src/usr.sbin/config/main.c
Warning:line 804, column 8
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name main.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/config/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/config -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/config/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/config/main.c
1/* $OpenBSD: main.c,v 1.63 2021/11/20 03:13:37 jcs Exp $ */
2/* $NetBSD: main.c,v 1.22 1997/02/02 21:12:33 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: @(#)main.c 8.1 (Berkeley) 6/6/93
42 */
43
44#include <sys/types.h>
45#include <sys/stat.h>
46
47#include <ctype.h>
48#include <err.h>
49#include <errno(*__errno()).h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
54#include <limits.h>
55
56#include "config.h"
57
58int firstfile(const char *);
59int yyparse(void);
60
61static struct hashtab *mkopttab;
62static struct nvlist **nextopt;
63static struct nvlist **nextdefopt;
64static struct nvlist **nextmkopt;
65
66static __dead__attribute__((__noreturn__)) void stop(void);
67static int do_option(struct hashtab *, struct nvlist ***,
68 const char *, const char *, const char *);
69static int crosscheck(void);
70static int badstar(void);
71static int mksymlinks(void);
72static int hasparent(struct devi *);
73static int cfcrosscheck(struct config *, const char *, struct nvlist *);
74static void optiondelta(void);
75
76int verbose;
77
78const char *conffile; /* source file, e.g., "GENERIC.sparc" */
79const char *last_component;
80const char *machine; /* machine type, e.g., "sparc" or "sun3" */
81const char *machinearch; /* machine arch, e.g., "sparc" or "m68k" */
82const char *srcdir; /* path to source directory (rel. to build) */
83const char *builddir; /* path to build directory */
84const char *defbuilddir; /* default build directory */
85int errors; /* counts calls to error() */
86int minmaxusers; /* minimum "maxusers" parameter */
87int defmaxusers; /* default "maxusers" parameter */
88int maxmaxusers; /* default "maxusers" parameter */
89int maxusers; /* configuration's "maxusers" parameter */
90int maxpartitions; /* configuration's "maxpartitions" parameter */
91struct nvlist *options; /* options */
92struct nvlist *defoptions; /* "defopt"'d options */
93struct nvlist *mkoptions; /* makeoptions */
94struct hashtab *devbasetab; /* devbase lookup */
95struct hashtab *devatab; /* devbase attachment lookup */
96struct hashtab *selecttab; /* selects things that are "optional foo" */
97struct hashtab *needcnttab; /* retains names marked "needs-count" */
98struct hashtab *opttab; /* table of configured options */
99struct hashtab *defopttab; /* options that have been "defopt"'d */
100struct devbase *allbases; /* list of all devbase structures */
101struct deva *alldevas; /* list of all devbase attachment structures */
102struct config *allcf; /* list of configured kernels */
103struct devi *alldevi; /* list of all instances */
104struct devi *allpseudo; /* list of all pseudo-devices */
105int ndevi; /* number of devi's (before packing) */
106int npseudo; /* number of pseudo's */
107
108struct files *allfiles; /* list of all kernel source files */
109struct objects *allobjects; /* list of all kernel object and library files */
110
111struct devi **packed; /* arrayified table for packed devi's */
112int npacked; /* size of packed table, <= ndevi */
113
114struct parents parents;
115struct locators locators;
116
117__dead__attribute__((__noreturn__)) void
118usage(void)
119{
120 extern char *__progname;
121
122 fprintf(stderr(&__sF[2]),
123 "usage: %s [-p] [-b builddir] [-s srcdir] [config-file]\n"
124 " %s -e [-u] [-c cmdfile] [-f | -o outfile] infile\n",
125 __progname, __progname);
126
127 exit(1);
128}
129
130int pflag = 0;
131char *sflag = NULL((void *)0);
132char *bflag = NULL((void *)0);
133char *startdir;
134char *cmdfile = NULL((void *)0);
135FILE *cmdfp = NULL((void *)0);
136
137int
138main(int argc, char *argv[])
139{
140 char *p;
141 char *outfile = NULL((void *)0);
142 int ch, eflag, uflag, fflag;
143 char dirbuffer[PATH_MAX1024];
144
145 if (pledge("stdio rpath wpath cpath flock proc exec", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
146 err(1, "pledge");
147
148 pflag = eflag = uflag = fflag = 0;
149 while ((ch = getopt(argc, argv, "c:epfb:s:o:u")) != -1) {
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 199
150 switch (ch) {
151 case 'c':
152 cmdfile = optarg;
153 break;
154 case 'o':
155 outfile = optarg;
156 break;
157 case 'u':
158 uflag = 1;
159 break;
160 case 'f':
161 fflag = 1;
162 break;
163
164 case 'e':
165 eflag = 1;
166 if (!isatty(STDIN_FILENO0))
167 verbose = 1;
168 break;
169
170 case 'p':
171 /*
172 * Essentially the same as makeoptions PROF="-pg",
173 * but also changes the path from ../../compile/FOO
174 * to ../../compile/FOO.PROF; i.e., compile a
175 * profiling kernel based on a typical "regular"
176 * kernel.
177 *
178 * Note that if you always want profiling, you
179 * can (and should) use a "makeoptions" line.
180 */
181 pflag = 1;
182 break;
183
184 case 'b':
185 bflag = optarg;
186 builddir = optarg;
187 break;
188
189 case 's':
190 sflag = optarg;
191 srcdir = optarg;
192 break;
193
194 default:
195 usage();
196 }
197 }
198
199 argc -= optind;
200 argv += optind;
201 if (argc > 1 || (eflag
5.1
'eflag' is 0
&& argv[0] == NULL((void *)0)))
5
Assuming 'argc' is <= 1
202 usage();
203 if (bflag
5.2
'bflag' is null
) {
6
Taking false branch
204 startdir = getcwd(dirbuffer, sizeof dirbuffer);
205 if (startdir == NULL((void *)0))
206 warn("Use of -b and can't getcwd, no make config");
207 } else {
208 startdir = "../../conf";
209 }
210
211 if (eflag
6.1
'eflag' is 0
) {
7
Taking false branch
212#ifdef MAKE_BOOTSTRAP
213 errx(1, "UKC not available in this binary");
214#else
215 if (cmdfile != NULL((void *)0)) {
216 cmdfp = fopen(cmdfile, "r");
217 if (cmdfp == NULL((void *)0))
218 err(1, "open %s", cmdfile);
219 }
220 return (ukc(argv[0], outfile, uflag, fflag));
221#endif
222 }
223
224 conffile = (argc == 1) ? argv[0] : "CONFIG";
8
Assuming 'argc' is not equal to 1
9
'?' condition is false
225 if (firstfile(conffile))
10
Assuming the condition is false
11
Taking false branch
226 err(2, "cannot read %s", conffile);
227
228 /*
229 * Init variables.
230 */
231 minmaxusers = 1;
232 maxmaxusers = 10000;
233 initintern();
234 initfiles();
235 initsem();
236 devbasetab = ht_new();
237 devatab = ht_new();
238 selecttab = ht_new();
239 needcnttab = ht_new();
240 opttab = ht_new();
241 mkopttab = ht_new();
242 defopttab = ht_new();
243 nextopt = &options;
244 nextmkopt = &mkoptions;
245 nextdefopt = &defoptions;
246
247 /*
248 * Handle profiling (must do this before we try to create any
249 * files).
250 */
251 last_component = strrchr(conffile, '/');
252 last_component = (last_component) ? last_component + 1 : conffile;
12
Assuming 'last_component' is null
13
'?' condition is false
253 if (pflag
13.1
'pflag' is 0
) {
14
Taking false branch
254 if (asprintf(&p, "../compile/%s.PROF", last_component) == -1)
255 err(1, NULL((void *)0));
256 (void)addmkoption(intern("PROF"), "-pg");
257 (void)addoption(intern("GPROF"), NULL((void *)0));
258 } else {
259 if (asprintf(&p, "../compile/%s", last_component) == -1)
15
Assuming the condition is false
16
Taking false branch
260 err(1, NULL((void *)0));
261 }
262 defbuilddir = (argc == 0) ? "." : p;
17
Assuming 'argc' is not equal to 0
18
'?' condition is false
263
264 /*
265 * Parse config file (including machine definitions).
266 */
267 if (yyparse())
19
Assuming the condition is false
20
Taking false branch
268 stop();
269
270 /*
271 * Fix (as in `set firmly in place') files.
272 */
273 if (fixfiles())
21
Assuming the condition is false
22
Taking false branch
274 stop();
275
276 /*
277 * Fix objects and libraries.
278 */
279 if (fixobjects())
23
Assuming the condition is false
24
Taking false branch
280 stop();
281
282 /*
283 * Perform cross-checking.
284 */
285 if (maxusers == 0) {
25
Assuming 'maxusers' is not equal to 0
26
Taking false branch
286 if (defmaxusers) {
287 (void)printf("maxusers not specified; %d assumed\n",
288 defmaxusers);
289 maxusers = defmaxusers;
290 } else {
291 warnx("need \"maxusers\" line");
292 errors++;
293 }
294 }
295 if (crosscheck() || errors)
27
Assuming 'errors' is 0
28
Taking false branch
296 stop();
297
298 /*
299 * Squeeze things down and finish cross-checks (STAR checks must
300 * run after packing).
301 */
302 pack();
303 if (badstar())
29
Assuming the condition is false
30
Taking false branch
304 stop();
305
306 /*
307 * Ready to go. Build all the various files.
308 */
309 if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
31
Assuming the condition is false
32
Assuming the condition is false
33
Assuming the condition is false
35
Taking false branch
310 mkioconf())
34
Assuming the condition is false
311 stop();
312 optiondelta();
36
Calling 'optiondelta'
313 return (0);
314}
315
316static int
317mksymlink(const char *value, const char *path)
318{
319 int ret = 0;
320
321 if (remove(path) && errno(*__errno()) != ENOENT2) {
322 warn("remove(%s)", path);
323 ret = 1;
324 }
325 if (symlink(value, path)) {
326 warn("symlink(%s -> %s)", path, value);
327 ret = 1;
328 }
329 return (ret);
330}
331
332
333/*
334 * Make a symlink for "machine" so that "#include <machine/foo.h>" works,
335 * and for the machine's CPU architecture, so that works as well.
336 */
337static int
338mksymlinks(void)
339{
340 int ret;
341 char *p, buf[PATH_MAX1024];
342 const char *q;
343
344 snprintf(buf, sizeof buf, "arch/%s/include", machine);
345 p = sourcepath(buf);
346 ret = mksymlink(p, "machine");
347 if (machinearch != NULL((void *)0)) {
348 snprintf(buf, sizeof buf, "arch/%s/include", machinearch);
349 p = sourcepath(buf);
350 q = machinearch;
351 } else {
352 p = strdup("machine");
353 if (!p)
354 errx(1, "out of memory");
355 q = machine;
356 }
357 ret |= mksymlink(p, q);
358 free(p);
359
360 return (ret);
361}
362
363static __dead__attribute__((__noreturn__)) void
364stop(void)
365{
366 (void)fprintf(stderr(&__sF[2]), "*** Stop.\n");
367 exit(1);
368}
369
370/*
371 * Define a standard option, for which a header file will be generated.
372 */
373void
374defoption(const char *name)
375{
376 char *p, *low, c;
377 const char *n;
378
379 /*
380 * Convert to lower case. The header file name will be
381 * in lower case, so we store the lower case version in
382 * the hash table to detect option name collisions. The
383 * original string will be stored in the nvlist for use
384 * in the header file.
385 */
386 low = emalloc(strlen(name) + 1);
387 for (n = name, p = low; (c = *n) != '\0'; n++)
388 *p++ = isupper((unsigned char)c) ?
389 tolower((unsigned char)c) : c;
390 *p = 0;
391
392 n = intern(low);
393 free(low);
394 (void)do_option(defopttab, &nextdefopt, n, name, "defopt");
395
396 /*
397 * Insert a verbatim copy of the option name, as well,
398 * to speed lookups when creating the Makefile.
399 */
400 (void)ht_insert(defopttab, name, (void *)name)ht_insrep(defopttab, name, (void *)name, 0);
401}
402
403/*
404 * Remove an option.
405 */
406void
407removeoption(const char *name)
408{
409 struct nvlist *nv, *nvt;
410 char *p, *low, c;
411 const char *n;
412
413 if ((nv = ht_lookup(opttab, name)) != NULL((void *)0)) {
414 if (options == nv) {
415 options = nv->nv_next;
416 nvfree(nv);
417 } else {
418 nvt = options;
419 while (nvt->nv_next != NULL((void *)0)) {
420 if (nvt->nv_next == nv) {
421 nvt->nv_next = nvt->nv_next->nv_next;
422 nvfree(nv);
423 break;
424 } else
425 nvt = nvt->nv_next;
426 }
427 }
428 }
429
430 (void)ht_remove(opttab, name);
431
432 low = emalloc(strlen(name) + 1);
433 /* make lowercase, then remove from select table */
434 for (n = name, p = low; (c = *n) != '\0'; n++)
435 *p++ = isupper((unsigned char)c) ?
436 tolower((unsigned char)c) : c;
437 *p = 0;
438 n = intern(low);
439 free(low);
440 (void)ht_remove(selecttab, n);
441}
442
443/*
444 * Add an option from "options FOO". Note that this selects things that
445 * are "optional foo".
446 */
447void
448addoption(const char *name, const char *value)
449{
450 char *p, *low, c;
451 const char *n;
452
453 if (do_option(opttab, &nextopt, name, value, "options"))
454 return;
455
456 low = emalloc(strlen(name) + 1);
457 /* make lowercase, then add to select table */
458 for (n = name, p = low; (c = *n) != '\0'; n++)
459 *p++ = isupper((unsigned char)c) ?
460 tolower((unsigned char)c) : c;
461 *p = 0;
462 n = intern(low);
463 free(low);
464 (void)ht_insert(selecttab, n, (void *)n)ht_insrep(selecttab, n, (void *)n, 0);
465}
466
467/*
468 * Add a "make" option.
469 */
470void
471addmkoption(const char *name, const char *value)
472{
473
474 (void)do_option(mkopttab, &nextmkopt, name, value, "mkoptions");
475}
476
477/*
478 * Add a name=value pair to an option list. The value may be NULL.
479 */
480static int
481do_option(struct hashtab *ht, struct nvlist ***nppp, const char *name,
482 const char *value, const char *type)
483{
484 struct nvlist *nv;
485
486 /* assume it will work */
487 nv = newnv(name, value, NULL((void *)0), 0, NULL((void *)0));
488 if (ht_insert(ht, name, nv)ht_insrep(ht, name, nv, 0) == 0) {
489 **nppp = nv;
490 *nppp = &nv->nv_next;
491 return (0);
492 }
493
494 /* oops, already got that option */
495 nvfree(nv);
496 if ((nv = ht_lookup(ht, name)) == NULL((void *)0))
497 panic("do_option");
498 if (nv->nv_strnv_un.un_str != NULL((void *)0))
499 error("already have %s `%s=%s'", type, name, nv->nv_strnv_un.un_str);
500 else
501 error("already have %s `%s'", type, name);
502 return (1);
503}
504
505/*
506 * Return true if there is at least one instance of the given unit
507 * on the given device attachment (or any units, if unit == WILD).
508 */
509int
510deva_has_instances(struct deva *deva, int unit)
511{
512 struct devi *i;
513
514 if (unit == WILD(-2))
515 return (deva->d_ihead != NULL((void *)0));
516 for (i = deva->d_ihead; i != NULL((void *)0); i = i->i_asame)
517 if (unit == i->i_unit)
518 return (1);
519 return (0);
520}
521
522/*
523 * Return true if there is at least one instance of the given unit
524 * on the given base (or any units, if unit == WILD).
525 */
526int
527devbase_has_instances(struct devbase *dev, int unit)
528{
529 struct deva *da;
530
531 for (da = dev->d_ahead; da != NULL((void *)0); da = da->d_bsame)
532 if (deva_has_instances(da, unit))
533 return (1);
534 return (0);
535}
536
537static int
538hasparent(struct devi *i)
539{
540 struct nvlist *nv;
541 int atunit = i->i_atunit;
542
543 /*
544 * We determine whether or not a device has a parent in in one
545 * of two ways:
546 * (1) If a parent device was named in the config file,
547 * i.e. cases (2) and (3) in sem.c:adddev(), then
548 * we search its devbase for a matching unit number.
549 * (2) If the device was attach to an attribute, then we
550 * search all attributes the device can be attached to
551 * for parents (with appropriate unit numbers) that
552 * may be able to attach the device.
553 */
554
555 /*
556 * Case (1): A parent was named. Either it's configured, or not.
557 */
558 if (i->i_atdev != NULL((void *)0))
559 return (devbase_has_instances(i->i_atdev, atunit));
560
561 /*
562 * Case (2): No parent was named. Look for devs that provide the attr.
563 */
564 if (i->i_atattr != NULL((void *)0))
565 for (nv = i->i_atattr->a_refs; nv != NULL((void *)0); nv = nv->nv_next)
566 if (devbase_has_instances(nv->nv_ptrnv_un.un_ptr, atunit))
567 return (1);
568 return (0);
569}
570
571static int
572cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv)
573{
574 struct devbase *dev;
575 struct devi *pd;
576 int errs, devminor;
577
578 if (maxpartitions <= 0)
579 panic("cfcrosscheck");
580
581 for (errs = 0; nv != NULL((void *)0); nv = nv->nv_next) {
582 if (nv->nv_name == NULL((void *)0))
583 continue;
584 dev = ht_lookup(devbasetab, nv->nv_name);
585 if (dev == NULL((void *)0))
586 panic("cfcrosscheck(%s)", nv->nv_name);
587 devminor = minor(nv->nv_int)((unsigned)((nv->nv_int) & 0xff) | (((nv->nv_int) &
0xffff0000) >> 8))
/ maxpartitions;
588 if (devbase_has_instances(dev, devminor))
589 continue;
590 if (devbase_has_instances(dev, STAR(-1)) &&
591 devminor >= dev->d_umax)
592 continue;
593 for (pd = allpseudo; pd != NULL((void *)0); pd = pd->i_next)
594 if (pd->i_base == dev && devminor < dev->d_umax &&
595 devminor >= 0)
596 goto loop;
597 (void)fprintf(stderr(&__sF[2]),
598 "%s:%d: %s says %s on %s, but there's no %s\n",
599 conffile, cf->cf_lineno,
600 cf->cf_name, what, nv->nv_strnv_un.un_str, nv->nv_strnv_un.un_str);
601 errs++;
602loop:
603 ;
604 }
605 return (errs);
606}
607
608/*
609 * Cross-check the configuration: make sure that each target device
610 * or attribute (`at foo[0*?]') names at least one real device. Also
611 * see that the root, swap, and dump devices for all configurations
612 * are there.
613 */
614int
615crosscheck(void)
616{
617 struct devi *i;
618 struct config *cf;
619 int errs;
620
621 errs = 0;
622 for (i = alldevi; i != NULL((void *)0); i = i->i_next) {
623 if (i->i_at == NULL((void *)0) || hasparent(i))
624 continue;
625 xerror(conffile, i->i_lineno,
626 "%s at %s is orphaned", i->i_name, i->i_at);
627 (void)fprintf(stderr(&__sF[2]), " (%s %s declared)\n",
628 i->i_atunit == WILD(-2) ? "nothing matching" : "no",
629 i->i_at);
630 errs++;
631 }
632 if (allcf == NULL((void *)0)) {
633 (void)fprintf(stderr(&__sF[2]), "%s has no configurations!\n",
634 conffile);
635 errs++;
636 }
637 for (cf = allcf; cf != NULL((void *)0); cf = cf->cf_next) {
638 if (cf->cf_root != NULL((void *)0)) { /* i.e., not swap generic */
639 errs += cfcrosscheck(cf, "root", cf->cf_root);
640 errs += cfcrosscheck(cf, "swap", cf->cf_swap);
641 errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
642 }
643 }
644 return (errs);
645}
646
647/*
648 * Check to see if there is a *'d unit with a needs-count file.
649 */
650int
651badstar(void)
652{
653 struct devbase *d;
654 struct deva *da;
655 struct devi *i;
656 int errs, n;
657
658 errs = 0;
659 for (d = allbases; d != NULL((void *)0); d = d->d_next) {
660 for (da = d->d_ahead; da != NULL((void *)0); da = da->d_bsame)
661 for (i = da->d_ihead; i != NULL((void *)0); i = i->i_asame) {
662 if (i->i_unit == STAR(-1))
663 goto foundstar;
664 }
665 continue;
666 foundstar:
667 if (ht_lookup(needcnttab, d->d_name)) {
668 warnx("%s's cannot be *'d until its driver is fixed",
669 d->d_name);
670 errs++;
671 continue;
672 }
673 for (n = 0; i != NULL((void *)0); i = i->i_alias)
674 if (!i->i_collapsed)
675 n++;
676 if (n < 1)
677 panic("badstar() n<1");
678 }
679 return (errs);
680}
681
682/*
683 * Verify/create builddir if necessary, change to it, and verify srcdir.
684 * This will be called when we see the first include.
685 */
686void
687setupdirs(void)
688{
689 struct stat st;
690 FILE *fp;
691
692 /* srcdir must be specified if builddir is not specified or if
693 * no configuration filename was specified. */
694 if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) {
695 error("source directory must be specified");
696 exit(1);
697 }
698
699 if (srcdir == NULL((void *)0))
700 srcdir = "../../../..";
701 if (builddir == NULL((void *)0))
702 builddir = defbuilddir;
703
704 if (stat(builddir, &st) != 0) {
705 if (mkdir(builddir, 0777))
706 err(2, "cannot create %s", builddir);
707 } else if (!S_ISDIR(st.st_mode)((st.st_mode & 0170000) == 0040000))
708 errc(2, ENOTDIR20, "%s", builddir);
709 if (chdir(builddir) != 0)
710 errx(2, "cannot change to %s", builddir);
711 if (stat(srcdir, &st) != 0 || !S_ISDIR(st.st_mode)((st.st_mode & 0170000) == 0040000))
712 errc(2, ENOTDIR20, "%s", srcdir);
713
714 if (bflag) {
715 if (pledge("stdio rpath wpath cpath flock", NULL((void *)0)) == -1)
716 err(1, "pledge");
717 return;
718 }
719
720 if (stat("obj", &st) == 0)
721 goto reconfig;
722
723 fp = fopen("Makefile", "w");
724 if (!fp)
725 errx(2, "cannot create Makefile");
726 if (fprintf(fp, ".include \"../Makefile.inc\"\n") < 0 ||
727 fclose(fp) == EOF(-1))
728 errx(2, "cannot write Makefile");
729
730reconfig:
731 if (system("make obj") != 0)
732 exit(2);
733 if (system("make config") != 0)
734 exit(2);
735 exit(0);
736}
737
738struct opt {
739 const char *name;
740 const char *val;
741};
742
743int
744optcmp(const void *v1, const void *v2)
745{
746 const struct opt *sp1 = v1, *sp2 = v2;
747 int r;
748
749 r = strcmp(sp1->name, sp2->name);
750 if (r == 0) {
751 if (!sp1->val && !sp2->val)
752 r = 0;
753 else if (sp1->val && !sp2->val)
754 r = -1;
755 else if (sp2->val && !sp1->val)
756 r = 1;
757 else r = strcmp(sp1->val, sp2->val);
758 }
759 return (r);
760}
761
762void
763optiondelta(void)
764{
765 struct nvlist *nv;
766 char nbuf[BUFSIZ1024], obuf[BUFSIZ1024]; /* XXX size */
767 int nnewopts, ret = 0, i;
768 struct opt *newopts;
769 FILE *fp;
770
771 for (nnewopts = 0, nv = options; nv != NULL((void *)0); nv = nv->nv_next)
37
Assuming 'nv' is not equal to NULL
38
Loop condition is true. Entering loop body
39
Assuming 'nv' is equal to NULL
40
Loop condition is false. Execution continues on line 773
772 nnewopts++;
773 newopts = ereallocarray(NULL((void *)0), nnewopts, sizeof(struct opt));
41
Value assigned to 'newopts'
774 if (newopts == NULL((void *)0))
42
Assuming 'newopts' is equal to NULL
43
Taking true branch
775 ret = 0;
776 for (i = 0, nv = options; nv != NULL((void *)0); nv = nv->nv_next, i++) {
44
Assuming 'nv' is equal to NULL
45
Loop condition is false. Execution continues on line 780
777 newopts[i].name = nv->nv_name;
778 newopts[i].val = nv->nv_strnv_un.un_str;
779 }
780 qsort(newopts, nnewopts, sizeof (struct opt), optcmp);
781
782 /* compare options against previous config */
783 if ((fp = fopen("options", "r"))) {
46
Assuming 'fp' is null
47
Taking false branch
784 for (i = 0; !feof(fp)(!__isthreaded ? (((fp)->_flags & 0x0020) != 0) : (feof
)(fp))
&& i < nnewopts && ret == 0; i++) {
785 if (newopts[i].val)
786 snprintf(nbuf, sizeof nbuf, "%s=%s\n",
787 newopts[i].name, newopts[i].val);
788 else
789 snprintf(nbuf, sizeof nbuf, "%s\n",
790 newopts[i].name);
791 if (fgets(obuf, sizeof obuf, fp) == NULL((void *)0) ||
792 strcmp(nbuf, obuf))
793 ret = 1;
794 }
795 fclose(fp);
796 fp = NULL((void *)0);
797 } else if (access("options", F_OK0) == 0)
48
Assuming the condition is false
49
Taking false branch
798 ret = 1;
799
800 /* replace with the new list of options */
801 if ((fp = fopen("options", "w+"))) {
50
Assuming 'fp' is non-null
51
Taking true branch
802 rewind(fp);
803 for (i = 0; i < nnewopts; i++) {
52
Loop condition is true. Entering loop body
804 if (newopts[i].val)
53
Dereference of null pointer
805 fprintf(fp, "%s=%s\n", newopts[i].name,
806 newopts[i].val);
807 else
808 fprintf(fp, "%s\n", newopts[i].name);
809 }
810 fclose(fp);
811 }
812 free(newopts);
813 if (ret == 0)
814 return;
815 (void)printf("Kernel options have changed -- you must run \"make clean\"\n");
816}