Fix some issues raised (albeit indirectly) by Isaac Dunham.

POLL_IN defined as a constant by some libc.
Factor out login.c's change_identity() to xwrap.c as xsetuser().
Replace xsetuid() with xsetuser()
Put a space between argument globals and non-argument globals.
TT starts zeroed, don't need to re-zero entries in it.
STDIN_FILENO has been 0 since 1969, even DOS copied that. Just say 0.
Added an xchroot() using xchdir() to lib/xwrap.c.
Remove endgrent() call until somebody can explain why it was there.
diff --git a/lib/xwrap.c b/lib/xwrap.c
index c0c8a44..08a93dd 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -363,6 +363,12 @@
   if (chdir(path)) error_exit("chdir '%s'", path);
 }
 
+void xchroot(char *path)
+{
+  if (chroot(path)) error_exit("chroot '%s'", path);
+  xchdir("/");
+}
+
 // Ensure entire path exists.
 // If mode != -1 set permissions on newly created dirs.
 // Requires that path string be writable (for temporary null terminators).
@@ -391,14 +397,6 @@
   }
 }
 
-// setuid() can fail (for example, too many processes belonging to that user),
-// which opens a security hole if the process continues as the original user.
-
-void xsetuid(uid_t uid)
-{
-  if (setuid(uid)) perror_exit("xsetuid");
-}
-
 struct passwd *xgetpwuid(uid_t uid)
 {
   struct passwd *pwd = getpwuid(uid);
@@ -420,6 +418,15 @@
   return up;
 }
 
+// setuid() can fail (for example, too many processes belonging to that user),
+// which opens a security hole if the process continues as the original user.
+
+void xsetuser(struct passwd *pwd)
+{
+  if (initgroups(pwd->pw_name, pwd->pw_gid) || setgid(pwd->pw_uid)
+      || setuid(pwd->pw_uid)) perror_exit("xsetuser '%s'", pwd->pw_name);
+}
+
 // This can return null (meaning file not found).  It just won't return null
 // for memory allocation reasons.
 char *xreadlink(char *name)