Merge with git://charm.itp.tuwien.ac.at/mattems/klibc/.git#maks
diff --git a/Makefile b/Makefile
index bb018cc..b507668 100644
--- a/Makefile
+++ b/Makefile
@@ -151,4 +151,4 @@
 # This does all the prep work needed to turn a freshly exported git repository
 # into a release tarball tree
 release: klibc.spec
-	rm -f maketar.sh
+	rm -f maketar.sh .config
diff --git a/klcc/Kbuild b/klcc/Kbuild
index 7efcd24..b71581b 100644
--- a/klcc/Kbuild
+++ b/klcc/Kbuild
@@ -14,7 +14,7 @@
 	$(Q)echo 'KCROSS=$(KCROSS)' >> $@
 	$(Q)echo 'CC=$(KLIBCCC)' >> $@
 	$(Q)echo 'LD=$(KLIBCLD)' >> $@
-	$(Q)echo 'REQFLAGS=$(filter-out -I%,$(KLIBCDEFS) $(KLIBCREQFLAGS) $(KLIBCARCHREQFLAGS))' >> $@
+	$(Q)echo 'REQFLAGS=$(filter-out -I%,$(KLIBCDEFS) $(KLIBCREQFLAGS) $(KLIBCARCHREQFLAGS) $(KLIBCCPPFLAGS))' >> $@
 	$(Q)echo 'OPTFLAGS=$(KLIBCOPTFLAGS)' >> $@
 	$(Q)echo 'LDFLAGS=$(KLIBCLDFLAGS)' >> $@
 	$(Q)echo 'STRIP=$(KLIBCSTRIP)' >> $@
diff --git a/klibc.spec.in b/klibc.spec.in
index 85f57ef..30c1155 100644
--- a/klibc.spec.in
+++ b/klibc.spec.in
@@ -61,7 +61,8 @@
 mkdir -p %{buildroot}
 
 %build
-make  KLIBCARCH=%{_target_cpu} prefix=%{_prefix} bindir=%{_bindir} \
+make %{_smp_mflags} \
+	KLIBCARCH=%{_target_cpu} prefix=%{_prefix} bindir=%{_bindir} \
 	INSTALLDIR=%{klibcdir} mandir=%{_mandir} INSTALLROOT=%{buildroot}
 
 %install
diff --git a/scripts/Kbuild.klibc b/scripts/Kbuild.klibc
index bbb86f4..227b9bd 100644
--- a/scripts/Kbuild.klibc
+++ b/scripts/Kbuild.klibc
@@ -96,7 +96,8 @@
 KLIBCOBJDUMP	 := $(OBJDUMP)
 
 # klibc include paths
-KLIBCCPPFLAGS    := -I$(KLIBCINC)/arch/$(KLIBCARCHDIR)	\
+KLIBCCPPFLAGS    := -nostdinc -iwithprefix include \
+		    -I$(KLIBCINC)/arch/$(KLIBCARCHDIR)	\
                     -I$(KLIBCINC)/bits$(KLIBCBITSIZE)	\
 		    -I$(KLIBCOBJ)/../include		\
                     -I$(KLIBCINC)
diff --git a/usr/dash/Kbuild b/usr/dash/Kbuild
index 10e9591..edaa93f 100644
--- a/usr/dash/Kbuild
+++ b/usr/dash/Kbuild
@@ -3,7 +3,7 @@
 #
 
 config-cppflags := -DBSD=1 -DSMALL -DJOBS=0 -DHAVE_CONFIG_H -DSHELL
-config-cppflags += -DGLOB_BROKEN -DFNMATCH_BROKEN -DIFS_BROKEN
+config-cppflags += -DGLOB_BROKEN -DIFS_BROKEN
 
 EXTRA_KLIBCCFLAGS := -I$(srctree)/$(src) -I$(objtree)/$(obj)
 EXTRA_KLIBCCFLAGS += -include $(srctree)/$(src)/config.h
diff --git a/usr/include/fnmatch.h b/usr/include/fnmatch.h
new file mode 100644
index 0000000..0d88140
--- /dev/null
+++ b/usr/include/fnmatch.h
@@ -0,0 +1,15 @@
+#ifndef _FNMATCH_H
+#define _FNMATCH_H
+
+#include <klibc/extern.h>
+
+#define FNM_NOMATCH		1
+
+#define FNM_PATHNAME		1
+#define FNM_FILE_NAME		FNM_PATHNAME
+#define FNM_NOESCAPE		2
+#define FNM_PERIOD		4
+
+__extern int fnmatch(const char *, const char *, int);
+
+#endif /* _FNMATCH_H */
diff --git a/usr/include/getopt.h b/usr/include/getopt.h
new file mode 100644
index 0000000..71c41cd
--- /dev/null
+++ b/usr/include/getopt.h
@@ -0,0 +1,22 @@
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+#include <klibc/extern.h>
+
+struct option {
+	const char *name;
+	int has_arg;
+	int *flag;
+	int val;
+};
+
+enum {
+	no_argument	  = 0,
+	required_argument = 1,
+	optional_argument = 2,
+};
+
+__extern int getopt_long(int, char *const *, const char *,
+			 const struct option *, int *);
+
+#endif /* _GETOPT_H */
diff --git a/usr/include/grp.h b/usr/include/grp.h
index 19b1828..88bf79e 100644
--- a/usr/include/grp.h
+++ b/usr/include/grp.h
@@ -8,6 +8,13 @@
 #include <klibc/extern.h>
 #include <sys/types.h>
 
+struct group {
+	char *gr_name;
+	char *gr_passwd;
+	gid_t gr_gid;
+	char **gr_mem;
+};
+
 __extern int setgroups(size_t, const gid_t *);
 
 #endif				/* _GRP_H */
diff --git a/usr/include/pwd.h b/usr/include/pwd.h
new file mode 100644
index 0000000..aeddbfb
--- /dev/null
+++ b/usr/include/pwd.h
@@ -0,0 +1,19 @@
+#ifndef _PWD_H
+#define _PWD_H
+
+#include <klibc/extern.h>
+#include <sys/types.h>
+
+struct passwd {
+	char *pw_name;
+	char *pw_passwd;
+	uid_t pw_uid;
+	gid_t pw_gid;
+	char *pw_gecos;
+	char *pw_dir;
+	char *pw_shell;
+};
+
+__extern struct passwd *getpwnam(const char *name);
+
+#endif	/* _PWD_H */
diff --git a/usr/include/sys/prctl.h b/usr/include/sys/prctl.h
new file mode 100644
index 0000000..c12c191
--- /dev/null
+++ b/usr/include/sys/prctl.h
@@ -0,0 +1,10 @@
+#ifndef _SYS_PRCTL_H
+#define _SYS_PRCTL_H
+
+#include <klibc/extern.h>
+#include <linux/prctl.h>
+
+/* glibc has this as a varadic function, so join the club... */
+__extern int prctl(int, ...);
+
+#endif /* _SYS_PRCTL_H */
diff --git a/usr/include/sysexits.h b/usr/include/sysexits.h
new file mode 100644
index 0000000..ef454b9
--- /dev/null
+++ b/usr/include/sysexits.h
@@ -0,0 +1,26 @@
+#ifndef	_SYSEXITS_H
+#define	_SYSEXITS_H
+
+#define EX_OK		0	/* successful termination */
+
+#define EX__BASE	64	/* base value for error messages */
+
+#define EX_USAGE	64	/* command line usage error */
+#define EX_DATAERR	65	/* data format error */
+#define EX_NOINPUT	66	/* cannot open input */
+#define EX_NOUSER	67	/* addressee unknown */
+#define EX_NOHOST	68	/* host name unknown */
+#define EX_UNAVAILABLE	69	/* service unavailable */
+#define EX_SOFTWARE	70	/* internal software error */
+#define EX_OSERR	71	/* system error (e.g., can't fork) */
+#define EX_OSFILE	72	/* critical OS file missing */
+#define EX_CANTCREAT	73	/* can't create (user) output file */
+#define EX_IOERR	74	/* input/output error */
+#define EX_TEMPFAIL	75	/* temp failure; user is invited to retry */
+#define EX_PROTOCOL	76	/* remote error in protocol */
+#define EX_NOPERM	77	/* permission denied */
+#define EX_CONFIG	78	/* configuration error */
+
+#define EX__MAX	78	/* maximum listed value */
+
+#endif /* _SYSEXITS_H */
diff --git a/usr/include/unistd.h b/usr/include/unistd.h
index 4df42d6..c7badd8 100644
--- a/usr/include/unistd.h
+++ b/usr/include/unistd.h
@@ -98,7 +98,7 @@
 __extern ssize_t read(int, void *, size_t);
 __extern ssize_t write(int, const void *, size_t);
 __extern ssize_t pread(int, void *, size_t, off_t);
-__extern ssize_t pwrite(int, void *, size_t, off_t);
+__extern ssize_t pwrite(int, const void *, size_t, off_t);
 
 __extern int dup(int);
 __extern int dup2(int, int);
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index 65ca2e4..906caae 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -36,11 +36,12 @@
 	  strncat.o strlcpy.o strlcat.o \
 	  strstr.o strncmp.o strncpy.o strrchr.o \
 	  strxspn.o strspn.o strcspn.o strpbrk.o strsep.o strtok.o \
+	  fnmatch.o \
 	  gethostname.o getdomainname.o getcwd.o \
 	  seteuid.o setegid.o \
 	  getenv.o setenv.o putenv.o __put_env.o unsetenv.o \
 	  clearenv.o nullenv.o \
-	  getopt.o readdir.o remove.o \
+	  getopt.o getopt_long.o readdir.o remove.o \
 	  syslog.o closelog.o pty.o getpt.o isatty.o reboot.o \
 	  time.o utime.o llseek.o nice.o getpriority.o \
 	  qsort.o bsearch.o \
@@ -52,7 +53,9 @@
 	  ctype/isblank.o ctype/iscntrl.o ctype/isdigit.o \
 	  ctype/isgraph.o ctype/islower.o ctype/isprint.o \
 	  ctype/ispunct.o ctype/isspace.o ctype/isupper.o \
-	  ctype/isxdigit.o ctype/tolower.o ctype/toupper.o
+	  ctype/isxdigit.o ctype/tolower.o ctype/toupper.o \
+	  userdb/getgrgid.o userdb/getgrnam.o userdb/getpwnam.o \
+	  userdb/getpwuid.o userdb/root_group.o userdb/root_user.o
 
 klib-$(CONFIG_KLIBC_ERRLIST) += errlist.o
 
diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def
index 64b92be..c12d525 100644
--- a/usr/klibc/SYSCALLS.def
+++ b/usr/klibc/SYSCALLS.def
@@ -49,6 +49,8 @@
 int setpriority(int, int, int);
 int sched_setscheduler(pid_t, int, const struct sched_param *);
 int sched_yield();
+<i386> int prctl@varadic(int, unsigned long, unsigned long, unsigned long, unsigned long);
+<!i386> int prctl(int, unsigned long, unsigned long, unsigned long, unsigned long);
 
 /*
  * User and group IDs
diff --git a/usr/klibc/arch/x86_64/MCONFIG b/usr/klibc/arch/x86_64/MCONFIG
index d01f5e3..a229905 100644
--- a/usr/klibc/arch/x86_64/MCONFIG
+++ b/usr/klibc/arch/x86_64/MCONFIG
@@ -16,7 +16,7 @@
 #
 KLIBCARCHREQFLAGS = -m64
 ifeq ($(DEBUG),y)
-KLIBCOPTFLAGS     += -Os -fomit-frame-pointer \
+KLIBCOPTFLAGS     += -g -Os -fomit-frame-pointer \
 		-falign-functions=1 -falign-jumps=1 -falign-loops=1
 else
 KLIBCOPTFLAGS     += -Os -fno-asynchronous-unwind-tables -fomit-frame-pointer \
diff --git a/usr/klibc/fnmatch.c b/usr/klibc/fnmatch.c
new file mode 100644
index 0000000..5d0a25f
--- /dev/null
+++ b/usr/klibc/fnmatch.c
@@ -0,0 +1,72 @@
+/*
+ * fnmatch.c
+ *
+ * Original implementation by Kay Sievers, modified by H. Peter Anvin.
+ */
+
+#include <fnmatch.h>
+
+int fnmatch(const char *p, const char *s, int flags)
+{
+	if (flags & FNM_PATHNAME && *s == '/')
+		return (*p != '/') || fnmatch(p+1, s+1, flags);
+	if (flags & FNM_PERIOD && *s == '.')
+		return (*p != '.') || fnmatch(p+1, s+1, flags);
+
+	flags &= ~FNM_PERIOD;	/* Only applies at beginning */
+
+	if (!(flags & FNM_NOESCAPE) && *p == '\\') {
+		p++;
+		return (*p != *s) || fnmatch(p+1, s+1, flags);
+	}
+
+	if (*s == '\0') {
+		while (*p == '*')
+			p++;
+		return (*p != '\0');
+	}
+
+	switch (*p) {
+	case '[':
+		{
+			int not = 0;
+			p++;
+			if (*p == '!') {
+				not = 1;
+				p++;
+			}
+			while ((*p != '\0') && (*p != ']')) {
+				int match = 0;
+				if (p[1] == '-') {
+					if ((*s >= *p) && (*s <= p[2]))
+						match = 1;
+					p += 3;
+				} else {
+					match = (*p == *s);
+					p++;
+				}
+				if (match ^ not) {
+					while ((*p != '\0') && (*p != ']'))
+						p++;
+					if (*p == ']')
+						return fnmatch(p+1, s+1, flags);
+				}
+			}
+		}
+		break;
+	case '*':
+		if (fnmatch(p, s+1, flags))
+			return fnmatch(p+1, s, flags);
+		return 0;
+	case '\0':
+		if (*s == '\0') {
+			return 0;
+		}
+		break;
+	default:
+		if ((*p == *s) || (*p == '?'))
+			return fnmatch(p+1, s+1, flags);
+		break;
+	}
+	return 1;
+}
diff --git a/usr/klibc/getopt_long.c b/usr/klibc/getopt_long.c
new file mode 100644
index 0000000..e3d064b
--- /dev/null
+++ b/usr/klibc/getopt_long.c
@@ -0,0 +1,152 @@
+/*
+ * getopt.c
+ *
+ * getopt_long(), or at least a common subset thereof:
+ *
+ * - Option reordering is not supported
+ * - -W foo is not supported
+ * - First optstring character "-" not supported.
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+char *optarg;
+int optind, opterr, optopt;
+static struct getopt_private_state {
+	const char *optptr;
+	const char *last_optstring;
+	char *const *last_argv;
+} pvt;
+
+static inline const char *option_matches(const char *arg_str,
+					 const char *opt_name)
+{
+	while (*arg_str != '\0' && *arg_str != '=') {
+		if (*arg_str++ != *opt_name++)
+			return NULL;
+	}
+
+	if (*opt_name)
+		return NULL;
+
+	return arg_str;
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring,
+		const struct option *longopts, int *longindex)
+{
+	const char *carg;
+	const char *osptr;
+	int opt;
+
+	/* getopt() relies on a number of different global state
+	   variables, which can make this really confusing if there is
+	   more than one use of getopt() in the same program.  This
+	   attempts to detect that situation by detecting if the
+	   "optstring" or "argv" argument have changed since last time
+	   we were called; if so, reinitialize the query state. */
+
+	if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
+	    optind < 1 || optind > argc) {
+		/* optind doesn't match the current query */
+		pvt.last_optstring = optstring;
+		pvt.last_argv = argv;
+		optind = 1;
+		pvt.optptr = NULL;
+	}
+
+	carg = argv[optind];
+
+	/* First, eliminate all non-option cases */
+
+	if (!carg || carg[0] != '-' || !carg[1])
+		return -1;
+
+	if (carg[1] == '-') {
+		const struct option *lo;
+		const char *opt_end = NULL;
+
+		optind++;
+
+		/* Either it's a long option, or it's -- */
+		if (!carg[2]) {
+			/* It's -- */
+			return -1;
+		}
+
+		for (lo = longopts; lo->name; lo++) {
+			if ((opt_end = option_matches(carg+2, lo->name)))
+			    break;
+		}
+		if (!opt_end)
+			return '?';
+
+		if (longindex)
+			*longindex = lo-longopts;
+
+		if (*opt_end == '=') {
+			if (lo->has_arg)
+				optarg = (char *)opt_end+1;
+			else
+				return '?';
+		} else if (lo->has_arg == 1) {
+			if (!(optarg = argv[optind]))
+				return '?';
+			optind++;
+		}
+
+		if (lo->flag) {
+			*lo->flag = lo->val;
+			return 0;
+		} else {
+			return lo->val;
+		}
+	}
+
+	if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
+		/* Someone frobbed optind, change to new opt. */
+		pvt.optptr = carg + 1;
+	}
+
+	opt = *pvt.optptr++;
+
+	if (opt != ':' && (osptr = strchr(optstring, opt))) {
+		if (osptr[1] == ':') {
+			if (*pvt.optptr) {
+				/* Argument-taking option with attached
+				   argument */
+				optarg = (char *)pvt.optptr;
+				optind++;
+			} else {
+				/* Argument-taking option with non-attached
+				   argument */
+				if (argv[optind + 1]) {
+					optarg = (char *)argv[optind+1];
+					optind += 2;
+				} else {
+					/* Missing argument */
+					optind++;
+					return (optstring[0] == ':')
+						? ':' : '?';
+				}
+			}
+			return opt;
+		} else {
+			/* Non-argument-taking option */
+			/* pvt.optptr will remember the exact position to
+			   resume at */
+			if (!*pvt.optptr)
+				optind++;
+			return opt;
+		}
+	} else {
+		/* Unknown option */
+		optopt = opt;
+		if (!*pvt.optptr)
+			optind++;
+		return '?';
+	}
+}
diff --git a/usr/klibc/malloc.c b/usr/klibc/malloc.c
index f07ebd2..fbbbbbc 100644
--- a/usr/klibc/malloc.c
+++ b/usr/klibc/malloc.c
@@ -40,7 +40,7 @@
 	an = ah->a.next;
 	ap->a.next = an;
 	an->a.prev = ap;
-}	
+}
 
 static inline void remove_from_free_chain(struct free_arena_header *ah)
 {
@@ -50,7 +50,7 @@
 	an = ah->next_free;
 	ap->next_free = an;
 	an->prev_free = ap;
-}	
+}
 
 static inline void remove_from_chains(struct free_arena_header *ah)
 {
diff --git a/usr/klibc/tests/Kbuild b/usr/klibc/tests/Kbuild
index a97e86c..75d8bb3 100644
--- a/usr/klibc/tests/Kbuild
+++ b/usr/klibc/tests/Kbuild
@@ -15,7 +15,9 @@
 
 environ.shared-y	:= environ.o
 fcntl.shared-y		:= fcntl.o
+fnmatch.shared-y	:= fnmatch.o
 getopttest.shared-y	:= getopttest.o
+getoptlong.shared-y	:= getoptlong.o
 getpagesize.shared-y	:= getpagesize.o
 hello.shared-y		:= hello.o
 idtest.shared-y		:= idtest.o
diff --git a/usr/klibc/tests/fnmatch.c b/usr/klibc/tests/fnmatch.c
new file mode 100644
index 0000000..4150857
--- /dev/null
+++ b/usr/klibc/tests/fnmatch.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fnmatch.h>
+
+int main(int argc, char *argv[])
+{
+	int flags = atoi(argv[3]);
+	int match = fnmatch(argv[1], argv[2], flags);
+
+	printf("\"%s\" matches \"%s\": %d\n", argv[1], argv[2], match);
+
+	return match;
+}
+
+	
diff --git a/usr/klibc/tests/getoptlong.c b/usr/klibc/tests/getoptlong.c
new file mode 100644
index 0000000..c1174ab
--- /dev/null
+++ b/usr/klibc/tests/getoptlong.c
@@ -0,0 +1,57 @@
+/*
+ * getoptlong.c
+ *
+ * Simple test for getopt_long, set the environment variable GETOPTTEST
+ * to give the argument string to getopt()
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <getopt.h>
+
+static int foo = 0;
+	
+static const struct option long_options[] = {
+	{ "first",   1, NULL, 'f' },
+	{ "second",  0, NULL, 's' },
+	{ "third",   2, NULL, '3' },
+	{ "fourth",  0, NULL,  4 },
+	{ "set-foo", 0, &foo,  1 },
+	{ NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char *const *argv)
+{
+	const char *parser;
+	const char *showchar;
+	char one_char[] = "\'?\'";
+	char num_buf[16];
+	int c;
+	int longindex;
+
+	parser = getenv("GETOPTTEST");
+	if (!parser)
+		parser = "abzf:o:";
+
+	do {
+		c = getopt_long(argc, argv, parser, long_options, &longindex);
+
+		if (c == EOF) {
+			showchar = "EOF";
+		} else if (c >= 32 && c <= 126) {
+			one_char[1] = c;
+			showchar = one_char;
+		} else {
+			snprintf(num_buf, sizeof num_buf, "%d", c);
+			showchar = num_buf;
+		}
+
+		printf("c = %s, optind = %d (\"%s\"), optarg = \"%s\", "
+		       "optopt = \'%c\', foo = %d, longindex = %d\n",
+		       showchar, optind, argv[optind],
+		       optarg, optopt, foo, longindex);
+	} while (c != -1);
+
+	return 0;
+}
diff --git a/usr/klibc/userdb/getgrgid.c b/usr/klibc/userdb/getgrgid.c
new file mode 100644
index 0000000..5e13a47
--- /dev/null
+++ b/usr/klibc/userdb/getgrgid.c
@@ -0,0 +1,16 @@
+/*
+ * getgrgid.c
+ *
+ * Dummy getgrgid() to support udev
+ */
+
+#include "userdb.h"
+
+struct group *getgrgid(gid_t gid)
+{
+	if (!gid)
+		return (struct group *)&__root_group;
+
+	errno = ENOENT;
+	return NULL;
+}
diff --git a/usr/klibc/userdb/getgrnam.c b/usr/klibc/userdb/getgrnam.c
new file mode 100644
index 0000000..8df7b8f
--- /dev/null
+++ b/usr/klibc/userdb/getgrnam.c
@@ -0,0 +1,16 @@
+/*
+ * getgrnam.c
+ *
+ * Dummy getgrnam() to support udev
+ */
+
+#include "userdb.h"
+
+struct group *getgrnam(const char *name)
+{
+	if (!strcmp(name, "root"))
+		return (struct group *)&__root_group;
+
+	errno = ENOENT;
+	return NULL;
+}
diff --git a/usr/klibc/userdb/getpwnam.c b/usr/klibc/userdb/getpwnam.c
new file mode 100644
index 0000000..ae1359c
--- /dev/null
+++ b/usr/klibc/userdb/getpwnam.c
@@ -0,0 +1,17 @@
+/*
+ * getpwnam.c
+ *
+ * Dummy getpwnam() to support udev
+ */
+
+#include "userdb.h"
+
+
+struct passwd *getpwnam(const char *name)
+{
+	if (!strcmp(name, "root"))
+		return (struct passwd *)&__root_user;
+
+	errno = ENOENT;
+	return NULL;
+}
diff --git a/usr/klibc/userdb/getpwuid.c b/usr/klibc/userdb/getpwuid.c
new file mode 100644
index 0000000..f924f29
--- /dev/null
+++ b/usr/klibc/userdb/getpwuid.c
@@ -0,0 +1,17 @@
+/*
+ * getpwuid.c
+ *
+ * Dummy getpwuid() to support udev
+ */
+
+#include "userdb.h"
+
+
+struct passwd *getpwuid(uid_t uid)
+{
+	if (!uid)
+		return (struct passwd *)&__root_user;
+
+	errno = ENOENT;
+	return NULL;
+}
diff --git a/usr/klibc/userdb/root_group.c b/usr/klibc/userdb/root_group.c
new file mode 100644
index 0000000..e936d54
--- /dev/null
+++ b/usr/klibc/userdb/root_group.c
@@ -0,0 +1,12 @@
+/*
+ * root_group.c
+ */
+
+#include "userdb.h"
+
+const struct group __root_group = {
+	.gr_name   = "root",
+	.gr_passwd = "",
+	.gr_gid    = 0,
+	.gr_mem    = NULL
+};
diff --git a/usr/klibc/userdb/root_user.c b/usr/klibc/userdb/root_user.c
new file mode 100644
index 0000000..ee2e99a
--- /dev/null
+++ b/usr/klibc/userdb/root_user.c
@@ -0,0 +1,17 @@
+/*
+ * root_user.c
+ *
+ */
+
+#include "userdb.h"
+#include <paths.h>
+
+const struct passwd __root_user = {
+	.pw_name    = "root",
+	.pw_passwd  = "",
+	.pw_uid     = 0,
+	.pw_gid     = 0,
+	.pw_gecos   = "root",
+	.pw_dir     = "/",
+	.pw_shell   = _PATH_BSHELL
+};
diff --git a/usr/klibc/userdb/userdb.h b/usr/klibc/userdb/userdb.h
new file mode 100644
index 0000000..dda093f
--- /dev/null
+++ b/usr/klibc/userdb/userdb.h
@@ -0,0 +1,19 @@
+/*
+ * userdb.h
+ *
+ * Common header file
+ */
+
+#ifndef USERDB_H
+#define USERDB_H
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <errno.h>
+
+extern const struct passwd __root_user;
+extern const struct group __root_group;
+
+#endif /* USERDB_H */
diff --git a/usr/klibc/version b/usr/klibc/version
index d6e2616..5e99adf 100644
--- a/usr/klibc/version
+++ b/usr/klibc/version
@@ -1 +1 @@
-1.4.22
+1.4.27
diff --git a/usr/utils/nuke.c b/usr/utils/nuke.c
index 9470bcf..829bd05 100644
--- a/usr/utils/nuke.c
+++ b/usr/utils/nuke.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2004-2006 H. Peter Anvin - All Rights Reserved
  *
  *   Permission is hereby granted, free of charge, to any person
  *   obtaining a copy of this software and associated documentation
@@ -111,7 +111,6 @@
 int main(int argc, char *argv[])
 {
 	int i;
-	int err = 0;
 
 	program = argv[0];