--- old/usr/src/pkg/manifests/system-test-libctest.mf	Mon Mar 30 10:49:09 2015
+++ new/usr/src/pkg/manifests/system-test-libctest.mf	Mon Mar 30 10:49:09 2015
@@ -33,6 +33,7 @@
 file path=opt/libc-tests/bin/libctest mode=0555
 file path=opt/libc-tests/cfg/README mode=0444
 file path=opt/libc-tests/cfg/compilation.cfg mode=0444
+file path=opt/libc-tests/cfg/symbols/README mode=0444
 file path=opt/libc-tests/cfg/symbols/ctype_h.cfg mode=0444
 file path=opt/libc-tests/cfg/symbols/dirent_h.cfg mode=0444
 file path=opt/libc-tests/cfg/symbols/fcntl_h.cfg mode=0444
--- old/usr/src/test/libc-tests/cfg/Makefile	Mon Mar 30 10:49:09 2015
+++ new/usr/src/test/libc-tests/cfg/Makefile	Mon Mar 30 10:49:09 2015
@@ -10,7 +10,7 @@
 #
 
 #
-# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright 2015 Garrett D'Amore <garrett@damore.org>
 # Copyright (c) 2012 by Delphix. All rights reserved.
 #
 
@@ -18,6 +18,7 @@
 
 CFGS = README \
 	compilation.cfg \
+	symbols/README \
 	symbols/ctype_h.cfg \
 	symbols/dirent_h.cfg \
 	symbols/fcntl_h.cfg \
--- old/usr/src/test/libc-tests/cfg/README	Mon Mar 30 10:49:09 2015
+++ new/usr/src/test/libc-tests/cfg/README	Mon Mar 30 10:49:09 2015
@@ -20,7 +20,7 @@
 New lines preceeded by backslashes are ignored, allowing for a continuation
 of lines, in the usual UNIX way.
 
-A line beginning with a hashmark is comment, and is ignore, as are lines
+A line beginning with a hashmark is a comment, and is ignored, as are lines
 consisting solely of whitespace.
 
 The first field is always the "keyword", which determines the meaning and
--- old/usr/src/test/libc-tests/cfg/compilation.cfg	Mon Mar 30 10:49:09 2015
+++ new/usr/src/test/libc-tests/cfg/compilation.cfg	Mon Mar 30 10:49:09 2015
@@ -10,12 +10,32 @@
 #
 
 #
-# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+# Copyright 2015 Garrett D'Amore <garrett@damore.org>
 #
 
 #
 # Compilation environments.
 #
+# Each compilation environment is declared using the keyword "env", like
+# this:
+#
+# env | <name> | <std> | <defs>
+#
+# <name> is just a symbolic name for environment.
+# <std>  indicates either c89 or c99, i.e. which C standard to compile
+#        under.  This infuences choice of compiler and switches.
+# <defs> is a list of CPP style -D or -U flags to define C preprocessor
+#        symbols.
+#
+# Groups of compilation environments can be named, using the "env_group"
+# keyword (this can also be used to create aliases):
+#
+# env_group | <name> | <envs>
+#
+# <name> is a name for the group or alias
+# <envs> is a whitespace separated list of previously declared environments
+#        or environment groups (or aliases).
+#
 
 env | XPG3		| c89 | -D_XOPEN_SOURCE
 env | XPG4		| c89 | -D_XOPEN_SOURCE -D_XOPEN_VERSION=4
--- /dev/null	Mon Mar 30 10:49:09 2015
+++ new/usr/src/test/libc-tests/cfg/symbols/README	Mon Mar 30 10:49:09 2015
@@ -0,0 +1,72 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2015 Garrett D'Amore <garrett@damore.org>
+#
+
+The configuration files in this directory are structured using the
+syntax defined in the ../README file.  They make use of the compilation
+environments declared in ../compilation.cfg, and are processed by the
+symbols test.
+
+We have organized the files by header file, that is the tests for symbols
+declared in a header file (e.g. <unistd.h> appear in a file based on that
+header file's name (e.g. unistd_h.cfg.)  This is purely for convenience.
+
+Within these various declarations, we have the following field types:
+
+<envs>    This is a list of compilation environments where the symbol
+          should be legal.  To indicate that the symbol must not be legal
+          an environment group can be prefixed with "-".  For example,
+          "SUS -SUSv4+" indicates a symbol that is legal in all SUS
+	  environments up to SUSv3, and was removed in SUSv4 and subsequent
+          versions of SUS.  As you can see, we can list multiple environments
+          or environment groups, and we can add or remove to previous groups
+          with subsequent ones.
+
+<name>    This is a symbol name.  It follows the rules for C symbol names.
+
+<header>  This is a header file, for example, unistd.h.  Conventionally,
+          the header files used should match the file where the test is
+          declared.
+
+<type>    This is a C type.  Function types can be declared without their
+          names, e.g. "void (*)(int)".  Structures (e.g. "struct stat") and
+          pointer types (e.g. "pthead_t *") are legal as well.
+
+Here are the types of declarations in these files:
+
+type | <name> | <header> | <envs>
+
+    Tests for a C type with <name>.  The test verifies that a variable with
+    this type can be declared when the <header> is included.
+
+value | <name> | <type> | <header> | <envs>
+
+    Tests for a value named <name>, of type <type>.  The test attempts to
+    assign the given value to a scratch variable declared with the given
+    type.  The value can be a macro or other C symbol.
+
+func | <name> | <type> | <type> [; <type> ]... | <header> | <envs>
+
+    Tests whether a function <name>, returning the first <type>, and
+    taking arguments of following <type> values, is declared.  Note that
+    the argument types are separated by semicolons.  For varargs style
+    functions, leave out the ... part.  For function declarations
+    that have no declared arguments, either void can specified, or
+    the type list can be omitted.
+
+Examples:
+
+    type | size_t | sys/types.h | ALL
+    value | NULL | void * | stdlib.h | ALL
+    func strnlen | int | const char *; int | string.h | ALL
--- old/usr/src/test/libc-tests/tests/common/test_common.c	Mon Mar 30 10:49:09 2015
+++ new/usr/src/test/libc-tests/tests/common/test_common.c	Mon Mar 30 10:49:09 2015
@@ -10,7 +10,7 @@
  */
 
 /*
- * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  */
 
 /*
@@ -171,6 +171,7 @@
 		    passes, tests, tests - passes);
 	}
 }
+
 void
 test_debugf(test_t t, const char *format, ...)
 {
@@ -279,9 +280,10 @@
 	int		rv;
 	int		found;
 	char		path[MAXPATHLEN];
+	int		i;
 
 	va_start(va, fname);
-	for (int i = 0; i < MAXCB; i++) {
+	for (i = 0; i < MAXCB; i++) {
 		keyws[i] = (const char *)va_arg(va, const char *);
 		if (keyws[i] == NULL)
 			break;
@@ -288,6 +290,9 @@
 		callbs[i] = (test_cfg_func_t)va_arg(va, test_cfg_func_t);
 	}
 	va_end(va);
+	if (i == MAXCB) {
+		test_debugf(t, "too many arguments to function >= %d", MAXCB);
+	}
 
 	found = 0;
 
--- old/usr/src/test/libc-tests/tests/symbols/symbols_test.c	Mon Mar 30 10:49:09 2015
+++ new/usr/src/test/libc-tests/tests/symbols/symbols_test.c	Mon Mar 30 10:49:09 2015
@@ -10,14 +10,12 @@
  */
 
 /*
- * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  */
 
 /*
  * This program tests symbol visibility using the /usr/bin/c89 and
  * /usr/bin/c99 programs.
- *
- * See symbols_defs.c for the actual list of symbols tested.
  */
 
 #include <stdio.h>
@@ -36,6 +34,7 @@
 char *cfile;
 char *ofile;
 char *lfile;
+char *efile;
 
 const char *sym = NULL;
 
@@ -62,25 +61,11 @@
 	NULL
 };
 
-const char *puname[] = {
-	"",
-	"/usr/bin/puname -S "
-};
-
 char *compiler = NULL;
 const char *c89flags = NULL;
 const char *c99flags = NULL;
 
-/* ====== BEGIN ======== */
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdint.h>
-
-#define	MAXENV	64	/* bits */
+#define	MAXENV	64	/* maximum number of environments (bitmask width) */
 #define	MAXHDR	10	/* maximum # headers to require to access symbol */
 #define	MAXARG	20	/* maximum # of arguments */
 
@@ -122,7 +107,43 @@
 struct sym_test *sym_tests = NULL;
 struct sym_test **sym_insert = &sym_tests;
 
+static char *
+mystrdup(const char *s)
+{
+	char *r;
+	if ((r = strdup(s)) == NULL) {
+		perror("strdup");
+		exit(1);
+	}
+	return (r);
+}
+
+static void *
+myzalloc(size_t sz)
+{
+	void *buf; 
+	if ((buf = calloc(1, sz)) == NULL) {
+		perror("calloc");
+		exit(1);
+	}
+	return (buf);
+}
+
 static void
+myasprintf(char **buf, const char *fmt, ...)
+{
+	int rv;
+	va_list va;
+	va_start(va, fmt);
+	rv = vasprintf(buf, fmt, va);
+	va_end(va);
+	if (rv < 0) {
+		perror("vasprintf");
+		exit(1);
+	}
+}
+
+static void
 append_sym_test(struct sym_test *st)
 {
 	*sym_insert = st;
@@ -211,12 +232,12 @@
 	char *defs;
 
 	if (nfields != 3) {
-		(void) asprintf(err, "number of fields (%d) != 3", nfields);
+		myasprintf(err, "number of fields (%d) != 3", nfields);
 		return (-1);
 	}
 
 	if (next_env >= MAXENV) {
-		(void) asprintf(err, "too many environments");
+		myasprintf(err, "too many environments");
 		return (-1);
 	}
 
@@ -224,9 +245,9 @@
 	lang = fields[1];
 	defs = fields[2];
 
-	compile_env[next_env].name = strdup(name);
-	compile_env[next_env].lang = strdup(lang);
-	compile_env[next_env].defs = strdup(defs);
+	compile_env[next_env].name = mystrdup(name);
+	compile_env[next_env].lang = mystrdup(lang);
+	compile_env[next_env].defs = mystrdup(defs);
 	compile_env[next_env].index = next_env;
 	next_env++;
 	return (0);
@@ -242,7 +263,7 @@
 	char *item;
 
 	if (nfields != 2) {
-		(void) asprintf(err, "number of fields (%d) != 2", nfields);
+		myasprintf(err, "number of fields (%d) != 2", nfields);
 		return (-1);
 	}
 
@@ -251,12 +272,12 @@
 	mask = 0;
 
 	if (expand_env(list, &mask, &item) < 0) {
-		(void) asprintf(err, "reference to undefined env %s", item);
+		myasprintf(err, "reference to undefined env %s", item);
 		return (-1);
 	}
 
-	eg = calloc(1, sizeof (*eg));
-	eg->name = strdup(name);
+	eg = myzalloc(sizeof (*eg));
+	eg->name = mystrdup(name);
 	eg->mask = mask;
 	eg->next = env_groups;
 	env_groups = eg;
@@ -263,56 +284,90 @@
 	return (0);
 }
 
+static char *progbuf = NULL;
+size_t proglen = 0;
+size_t progsiz = 0;
+
+static void 
+addprogch(char c)
+{
+	while (progsiz <= (proglen + 1)) {
+		progbuf = realloc(progbuf, progsiz + 4096);
+		if (progbuf == NULL) {
+			perror("realloc");
+			exit(1);
+		}
+		progsiz += 1024;
+	}
+	progbuf[proglen++] = c;
+	progbuf[proglen] = 0;
+}
+
 static void
+addprogstr(char *s)
+{
+	while (*s != NULL) {
+		addprogch(*s);
+		s++;
+	}
+}
+
+static void
+addprogfmt(const char *fmt, ...)
+{
+	va_list va;
+	char *buf = NULL;
+	va_start(va, fmt);
+	if (vasprintf(&buf, fmt, va) < 0) {
+		perror("vasprintf");
+		exit(1);
+	}
+	va_end(va);
+	addprogstr(buf);
+	free(buf);
+}
+
+static void
 mkprog(struct sym_test *st)
 {
-	static char buf[2048];
 	char *s;
-	char *prog = buf;
 
-	*prog = 0;
+	proglen = 0;
 
-#define	ADDSTR(p, str)	(void) strcpy(p, str); p += strlen(p)
-#define	ADDFMT(p, ...)	\
-	(void) snprintf(p, sizeof (buf) - (p-buf), __VA_ARGS__); \
-	p += strlen(p)
-#define	ADDCHR(p, c)	*p++ = c; *p = 0
-
 	for (int i = 0; i < MAXHDR && st->hdrs[i] != NULL; i++) {
-		ADDFMT(prog, "#include <%s>\n", st->hdrs[i]);
+		addprogfmt("#include <%s>\n", st->hdrs[i]);
 	}
 
 	for (s = st->rtype; *s; s++) {
-		ADDCHR(prog, *s);
+		addprogch(*s);
 		if (*s == '(') {
 			s++;
-			ADDCHR(prog, *s);
+			addprogch(*s);
 			s++;
 			break;
 		}
 	}
-	ADDCHR(prog, ' ');
+	addprogch(' ');
 
 	/* for function pointers, s is closing suffix, otherwise empty */
 
 	switch (st->type) {
 	case SYM_TYPE:
-		ADDFMT(prog, "test_type;", st->rtype);
+		addprogstr("test_type;");
 		break;
 
 	case SYM_VALUE:
-		ADDFMT(prog, "test_value%s;\n", s);	/* s usually empty */
-		ADDSTR(prog, "void\ntest_func(void)\n{\n");
-		ADDFMT(prog, "\ttest_value = %s;\n}",
-		    st->name);
+		addprogfmt("test_value%s;\n", s);	/* s usually empty */
+		addprogstr("void\ntest_func(void)\n{\n");
+		addprogfmt("\ttest_value = %s;\n}", st->name);
 		break;
 
 	case SYM_FUNC:
-		ADDSTR(prog, "\ntest_func(");
+		addprogstr("\ntest_func(");
 		for (int i = 0; st->atypes[i] != NULL && i < MAXARG; i++) {
 			int didname = 0;
 			if (i > 0) {
-				ADDSTR(prog, ", ");
+				addprogstr(", ");
 			}
 			if (strcmp(st->atypes[i], "void") == 0) {
 				didname = 1;
@@ -319,55 +374,55 @@
 			}
 			if (strcmp(st->atypes[i], "") == 0) {
 				didname = 1;
-				ADDSTR(prog, "void");
+				addprogstr("void");
 			}
 
 			/* print the argument list */
 			for (char *a = st->atypes[i]; *a; a++) {
 				if (*a == '(' && a[1] == '*' && !didname) {
-					ADDFMT(prog, "(*a%d", i);
+					addprogfmt("(*a%d", i);
 					didname = 1;
 					a++;
 				} else if (*a == '[' && !didname) {
-					ADDFMT(prog, "a%d[", i);
+					addprogfmt("a%d[", i);
 					didname = 1;
 				} else {
-					ADDCHR(prog, *a);
+					addprogch(*a);
 				}
 			}
 			if (!didname) {
-				ADDFMT(prog, " a%d", i);
+				addprogfmt(" a%d", i);
 			}
 		}
 
 		if (st->atypes[0] == NULL) {
-			ADDSTR(prog, "void");
+			addprogstr("void");
 		}
 
 		/* close argument list, and closing ")" for func ptrs */
-		ADDFMT(prog, ")%s\n{\n\t", s);	/* NB: s is normally empty */
+		addprogfmt(")%s\n{\n\t", s);	/* NB: s is normally empty */
 
 		if (strcmp(st->rtype, "") != 0 &&
 		    strcmp(st->rtype, "void") != 0) {
-			ADDSTR(prog, "return ");
+			addprogstr("return ");
 		}
 
 		/* add the function call */
-		ADDFMT(prog, "%s(", st->name);
+		addprogfmt("%s(", st->name);
 		for (int i = 0; st->atypes[i] != NULL && i < MAXARG; i++) {
 			if (strcmp(st->atypes[i], "") != 0 &&
 			    strcmp(st->atypes[i], "void") != 0) {
-				ADDFMT(prog, "%sa%d", i > 0 ? ", " : "", i);
+				addprogfmt("%sa%d", i > 0 ? ", " : "", i);
 			}
 		}
 
-		ADDSTR(prog, ");\n}");
+		addprogstr(");\n}");
 		break;
 	}
 
-	ADDCHR(prog, '\n');
+	addprogch('\n');
 
-	st->prog = strdup(buf);
+	st->prog = progbuf;
 }
 
 static int
@@ -375,7 +430,7 @@
 {
 	char *item;
 	if (expand_env_list(envs, &st->test_mask, &st->need_mask, &item) < 0) {
-		(void) asprintf(err, "bad env action %s", item);
+		myasprintf(err, "bad env action %s", item);
 		return (-1);
 	}
 	return (0);
@@ -388,11 +443,11 @@
 
 	for (char *h = strsep(&hdrs, ";"); h != NULL; h = strsep(&hdrs, ";")) {
 		if (i >= MAXHDR) {
-			(void) asprintf(err, "too many headers");
+			myasprintf(err, "too many headers");
 			return (-1);
 		}
 		test_trim(&h);
-		st->hdrs[i++] = strdup(h);
+		st->hdrs[i++] = mystrdup(h);
 	}
 
 	return (0);
@@ -405,11 +460,11 @@
 	char *a;
 	for (a = strsep(&atype, ";"); a != NULL; a = strsep(&atype, ";")) {
 		if (i >= MAXARG) {
-			(void) asprintf(err, "too many arguments");
+			myasprintf(err, "too many arguments");
 			return (-1);
 		}
 		test_trim(&a);
-		st->atypes[i++] = strdup(a);
+		st->atypes[i++] = mystrdup(a);
 	}
 
 	return (0);
@@ -424,7 +479,7 @@
 	struct sym_test *st;
 
 	if (nfields != 3) {
-		(void) asprintf(err, "number of fields (%d) != 3", nfields);
+		myasprintf(err, "number of fields (%d) != 3", nfields);
 		return (-1);
 	}
 	decl = fields[0];
@@ -431,10 +486,10 @@
 	hdrs = fields[1];
 	envs = fields[2];
 
-	st = calloc(1, sizeof (*st));
+	st = myzalloc(sizeof (*st));
 	st->type = SYM_TYPE;
-	st->name = strdup(decl);
-	st->rtype = strdup(decl);
+	st->name = mystrdup(decl);
+	st->rtype = mystrdup(decl);
 
 	if ((add_envs(st, envs, err) < 0) ||
 	    (add_headers(st, hdrs, err) < 0)) {
@@ -455,7 +510,7 @@
 	struct sym_test *st;
 
 	if (nfields != 4) {
-		(void) asprintf(err, "number of fields (%d) != 4", nfields);
+		myasprintf(err, "number of fields (%d) != 4", nfields);
 		return (-1);
 	}
 	name = fields[0];
@@ -463,10 +518,10 @@
 	hdrs = fields[2];
 	envs = fields[3];
 
-	st = calloc(1, sizeof (*st));
+	st = myzalloc(sizeof (*st));
 	st->type = SYM_VALUE;
-	st->name = strdup(name);
-	st->rtype = strdup(type);
+	st->name = mystrdup(name);
+	st->rtype = mystrdup(type);
 
 	if ((add_envs(st, envs, err) < 0) ||
 	    (add_headers(st, hdrs, err) < 0)) {
@@ -488,7 +543,7 @@
 	struct sym_test *st;
 
 	if (nfields != 5) {
-		(void) asprintf(err, "number of fields (%d) != 5", nfields);
+		myasprintf(err, "number of fields (%d) != 5", nfields);
 		return (-1);
 	}
 	name = fields[0];
@@ -497,10 +552,10 @@
 	hdrs = fields[3];
 	envs = fields[4];
 
-	st = calloc(1, sizeof (*st));
+	st = myzalloc(sizeof (*st));
 	st->type = SYM_FUNC;
-	st->name = strdup(name);
-	st->rtype = strdup(rtype);
+	st->name = mystrdup(name);
+	st->rtype = mystrdup(rtype);
 
 	if ((add_envs(st, envs, err) < 0) ||
 	    (add_headers(st, hdrs, err) < 0) ||
@@ -534,8 +589,9 @@
 }
 
 /*
- * Iterate through tests.  Pass NULL for cenv first time, and previous result
- * the next.  Returns NULL when no more environments.
+ * Iterate through tests.  Pass in NULL for cenv to begin the iteration. For
+ * subsequent iterations, use the return value from the previous iteration.
+ * Returns NULL when there are no more environments.
  */
 struct compile_env *
 sym_test_env(struct sym_test *st, struct compile_env *cenv, int *need)
@@ -582,6 +638,10 @@
 	int line = 1;
 
 	f = fopen(path, "r");
+	if (f == NULL) {
+		test_debugf(t, "fopen(%s): %s", path, strerror(errno));
+		return;
+	}
 
 	test_debugf(t, "----->> begin (%s) <<------", path);
 	while (getline(&buf, &cap, f) >= 0) {
@@ -611,6 +671,11 @@
 		free(cfile);
 		cfile = NULL;
 	}
+	if (efile != NULL) {
+		(void) unlink(efile);
+		free(efile);
+		efile = NULL;
+	}
 	if (dname) {
 		(void) rmdir(dname);
 		free(dname);
@@ -631,10 +696,11 @@
 		perror("mkdtemp");
 		return (-1);
 	}
-	dname = strdup(d);
-	(void) asprintf(&cfile, "%s/compile_test.c", d);
-	(void) asprintf(&ofile, "%s/compile_test.o", d);
-	(void) asprintf(&lfile, "%s/compile_test.log", d);
+	dname = mystrdup(d);
+	myasprintf(&cfile, "%s/compile_test.c", d);
+	myasprintf(&ofile, "%s/compile_test.o", d);
+	myasprintf(&lfile, "%s/compile_test.log", d);
+	myasprintf(&efile, "%s/compile_test.exe", d);
 	return (0);
 }
 
@@ -648,6 +714,8 @@
 	t = test_start("finding compiler");
 
 	if ((cf = fopen(cfile, "w+")) == NULL) {
+		test_failed(t, "Unable to open %s for write: %s", cfile,
+		    strerror(errno));
 		return;
 	}
 	(void) fprintf(cf, "#include <stdio.h>\n");
@@ -661,13 +729,13 @@
 	(void) fprintf(cf, "#endif\n}\n");
 	(void) fclose(cf);
 
-	for (i = 0; compilers[i/2] != NULL; i++) {
+	for (i = 0; compilers[i] != NULL; i++) {
 		char cmd[256];
 		int rv;
 
 		(void) snprintf(cmd, sizeof (cmd),
-		    "%s%s %s %s -o %s >/dev/null 2>&1",
-		    puname[i%2], compilers[i/2], MFLAG, cfile, ofile);
+		    "%s %s %s -o %s >/dev/null 2>&1",
+		    compilers[i], MFLAG, cfile, efile);
 		test_debugf(t, "trying %s", cmd);
 		rv = system(cmd);
 
@@ -676,7 +744,7 @@
 		if ((rv < 0) || !WIFEXITED(rv) || WEXITSTATUS(rv) != 0)
 			continue;
 
-		rv = system(ofile);
+		rv = system(efile);
 		if (rv >= 0 && WIFEXITED(rv)) {
 			rv = WEXITSTATUS(rv);
 		} else {
@@ -707,8 +775,7 @@
 		default:
 			continue;
 		}
-		(void) asprintf(&compiler,
-		    "%s%s", puname[i%2], compilers[i/2]);
+		myasprintf(&compiler, "%s", compilers[i]);
 		test_debugf(t, "compiler: %s", compiler);
 		return;
 	}
@@ -742,18 +809,14 @@
 
 	(void) unlink(ofile);
 
-	if (asprintf(&cmd, "%s %s %s -c %s -o %s >>%s 2>&1",
+	myasprintf(&cmd, "%s %s %s -c %s -o %s >>%s 2>&1",
 	    compiler, strcmp(env_lang(cenv), "c99") == 0 ? c99flags : c89flags,
-	    env_defs(cenv), cfile, ofile, lfile) < 0) {
-		test_failed(t, "asprintf: %s", strerror(errno));
-		return (-1);
-	}
+	    env_defs(cenv), cfile, ofile, lfile);
 
 	if (extra_debug) {
 		test_debugf(t, "command: %s", cmd);
 	}
 
-
 	if ((logf = fopen(lfile, "w+")) == NULL) {
 		test_failed(t, "fopen: %s", strerror(errno));
 		return (-1);
@@ -764,20 +827,27 @@
 	(void) fprintf(logf, "EXPECT: %s\n", need ? "OK" : "FAIL");
 	(void) fclose(logf);
 
-	if (system(cmd) != 0) {
-		if (need) {
+	switch (system(cmd)) {
+	case -1:
+		test_failed(t, "error compiling in %s: %s", env_name(cenv),
+		    strerror(errno));
+		return (-1);
+	case 0:
+		if (!need) {
 			fail_count++;
 			show_file(t, lfile);
-			test_failed(t, "error compiling in %s", env_name(cenv));
+			test_failed(t, "symbol visible in %s", env_name(cenv));
 			return (-1);
 		}
-	} else {
-		if (!need) {
+		break;
+	default:
+		if (need) {
 			fail_count++;
 			show_file(t, lfile);
-			test_failed(t, "symbol visible in %s", env_name(cenv));
+			test_failed(t, "error compiling in %s", env_name(cenv));
 			return (-1);
 		}
+		break;
 	}
 	good_count++;
 	return (0);
@@ -860,7 +930,10 @@
 		}
 	}
 
-	(void) atexit(cleanup);
+	if (atexit(cleanup) != 0) {
+		perror("atexit");
+		exit(1);
+	}
 
 	if (mkworkdir() < 0) {
 		perror("mkdir");
