--- src/lastlog.c.orig_before_mw	Mon Jun  7 09:40:45 1999
+++ src/lastlog.c	Fri Jan 19 16:02:01 2001
@@ -73,23 +73,49 @@
 static void print P_((void));
 static void print_one P_((const struct passwd *));
 
+static void
+virt_setpwent(char *our_root);
+static struct passwd *
+virt_getpwent(const char *our_root);
+static struct passwd *
+virt_getpwnam(const char *name, const char *our_root);
+static struct passwd *
+virt_getpwuid(const uid_t uid, const char *our_root);
+static char *our_root = NULL;
+static int print_all = 0;
+char *lastlog_name = LASTLOG_FILE;
+
 int
 main(int argc, char **argv)
 {
 	int	c;
-
+	
 	setlocale(LC_ALL, "");
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
 
-	if ((lastlogfile = fopen (LASTLOG_FILE,"r")) == (FILE *) 0) {
-		perror (LASTLOG_FILE);
-		exit (1);
-	}
-	while ((c = getopt (argc, argv, "u:t:")) != EOF) {
+	while ((c = getopt (argc, argv, "af:r:u:t:")) != EOF) {
 		switch (c) {
+		case 'a':
+		  {
+		    print_all = 1;
+		  }
+		  break;
+		  
+		case 'f':
+		  {
+		    lastlog_name = strdup(optarg);
+		  }
+		  break;
+		  
+		case 'r':
+		  {
+		    our_root = strdup(optarg);
+		  }
+		  break;
+
 			case 'u':
-				pwent = getpwnam (optarg);
+				pwent = virt_getpwnam (optarg, our_root);
 				if (!pwent) {
 					fprintf(stderr,
 						_("Unknown User: %s\n"),
@@ -106,6 +132,20 @@
 				break;
 		}
 	}
+
+	if ((strcmp(lastlog_name, LASTLOG_FILE) == 0) &&
+	    (our_root != NULL))
+	  {
+	    lastlog_name = (char *)malloc(strlen(our_root) +
+					  strlen(LASTLOG_FILE) + 2);
+	    sprintf(lastlog_name, "%s%s", our_root, LASTLOG_FILE);
+	  }
+	
+	if ((lastlogfile = fopen (lastlog_name,"r")) == (FILE *) 0) {
+		perror (lastlog_name);
+		exit (1);
+	}
+
 	print ();
 	fclose (lastlogfile);
 	exit (0);
@@ -120,7 +160,7 @@
 	if (uflg) {
 		offset = (unsigned long) user * sizeof lastlog;
 		if (fstat (fileno (lastlogfile), &statbuf)) {
-			perror(LASTLOG_FILE);
+			perror(lastlog_name);
 			return;
 		}
 		if (offset >= statbuf.st_size)
@@ -131,10 +171,52 @@
 					lastlogfile) == 1)
 			print_one (pwent);
 		else
-			perror (LASTLOG_FILE);
+		  perror (lastlog_name);
+	}
+	else if (print_all)
+	  {
+	    unsigned int i;
+	    unsigned int max_i;
+	    
+	    if (fstat (fileno (lastlogfile), &statbuf))
+	      {
+		perror(lastlog_name);
+		return;
+	      }
+	    
+	    max_i = statbuf.st_size / sizeof(lastlog);
+	    
+	    for (i = 0; i < max_i; i++)
+	      {
+		offset = i * sizeof lastlog;
+		fseek (lastlogfile, offset, SEEK_SET);
+		if (fread ((char *) &lastlog, sizeof lastlog, 1,
+			   lastlogfile) != 1)
+		  {
+		    continue;
+		  }
+		
+		if (((pwent = virt_getpwuid((uid_t)i, our_root)) !=
+		     NULL) ||
+		    (lastlog.ll_time > (time_t) 0))
+		  {
+		    char fake_name[64];
+		    struct passwd fake_pw;
+		    
+		    if (pwent == NULL)
+		      {
+
+			sprintf(fake_name, "uid%d", i);
+			fake_pw.pw_name = fake_name;
+			pwent = &fake_pw;
+		      }
+		    
+		    print_one(pwent);
+		  }
+	      }
 	} else {
-		setpwent ();
-		while ((pwent = getpwent ())) {
+		virt_setpwent (our_root);
+		while ((pwent = virt_getpwent (our_root))) {
 			user = pwent->pw_uid;
 			offset = (unsigned long) user * sizeof lastlog;
 			fseek (lastlogfile, offset, SEEK_SET);
@@ -190,4 +272,354 @@
 	printf ("%-16s\t%-8.8s %s\n", pw->pw_name,
 		lastlog.ll_line, cp);
 #endif
+}
+
+/* ------------------------------------------------------------------------- */
+static FILE *pw_file = NULL;
+static int pw_current = 0;
+
+static struct passwd *
+virt_getpwnam(const char *name, const char *our_root)
+{
+  char pw_filename[PATH_MAX];
+  char *retp;
+  
+  static struct passwd pw;
+  static char buffer[1024];
+  
+  if ((our_root == NULL) || *our_root == '\0')
+    {
+      return(getpwnam(name));
+    }
+  
+  if (pw_file == NULL)
+    {
+      snprintf(pw_filename, PATH_MAX, "%s/etc/passwd", our_root);
+      
+      if ((pw_file = fopen(pw_filename, "r")) == NULL)
+	{
+	  perror(pw_filename);
+	}
+    }
+  else 
+    {
+      fseek(pw_file, SEEK_SET, 0);
+    }
+  
+  while ((retp = fgets(buffer, 1024, pw_file)) != NULL)
+    {
+      int len;
+      
+      len = strlen(name);
+
+      if ((buffer[len] == ':') &&
+	  (strncmp(buffer, name, len) == 0))
+	{
+	  break;
+	}
+    }
+  
+  if (retp != NULL)
+    {
+      char *p;
+
+      pw.pw_name = buffer;
+      if ((retp = strchr(pw.pw_name, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_passwd = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      p = ++retp;      
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      pw.pw_uid = (uid_t)atoi(p);
+      
+      p = ++retp;      
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      pw.pw_gid = (uid_t)atoi(p);
+      
+      pw.pw_gecos = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_dir = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_shell = ++retp;
+      if ((retp = strchr(retp, '\n')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      
+      return(&pw);
+    }
+  else
+    {
+      return (NULL);
+    }
+}
+
+
+static struct passwd *
+virt_getpwuid(const uid_t uid, const char *our_root)
+{
+  char pw_filename[PATH_MAX];
+  char *retp;
+  char *p;
+  
+  static struct passwd pw;
+  char buffer[1024];
+  
+  if ((our_root == NULL) || *our_root == '\0')
+    {
+      return(getpwuid(uid));
+    }
+  
+  if (pw_file == NULL)
+    {
+      snprintf(pw_filename, PATH_MAX, "%s/etc/passwd", our_root);
+      
+      if ((pw_file = fopen(pw_filename, "r")) == NULL)
+	{
+	  perror(pw_filename);
+	}
+    }
+  else 
+    {
+      fseek(pw_file, SEEK_SET, 0);
+    }
+  
+  while ((retp = fgets(buffer, 1024, pw_file)) != NULL)
+    {
+      pw.pw_name = buffer;
+      if ((retp = strchr(pw.pw_name, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_passwd = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      p = ++retp;      
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      pw.pw_uid = (uid_t)atoi(p);
+
+      p = ++retp;      
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      pw.pw_gid = (uid_t)atoi(p);
+      
+      pw.pw_gecos = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_dir = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_shell = ++retp;
+      if ((retp = strchr(retp, '\n')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      
+      if (pw.pw_uid == uid)
+	{
+	  return(&pw);
+	}
+    }
+
+  return (NULL);
+}
+
+
+static struct passwd *
+virt_getpwent(const char *our_root)
+{
+  char pw_filename[PATH_MAX];
+  int pwc = 0;
+  char *retp;
+  char *p;
+
+  static struct passwd pw;
+  static char buffer[1024];
+  
+  if ((our_root == NULL) || *our_root == '\0')
+    {
+      return(getpwent());
+    }
+  
+  if (pw_file == NULL)
+    {
+      snprintf(pw_filename, PATH_MAX, "%s/etc/passwd", our_root);
+      
+      if ((pw_file = fopen(pw_filename, "r")) == NULL)
+	{
+	  perror(pw_filename);
+	}
+    }
+  else 
+    {
+      fseek(pw_file, SEEK_SET, 0);
+    }
+  
+  while (((retp = fgets(buffer, 1024, pw_file)) != NULL) &&
+	 (pwc != pw_current))
+    {
+      pwc++;
+    }
+
+  if (retp != NULL)
+    {
+      pw.pw_name = buffer;
+      if ((retp = strchr(pw.pw_name, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_passwd = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      p = ++retp;      
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      pw.pw_uid = (uid_t)atoi(p);
+      
+      p = ++retp;      
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      pw.pw_gid = (uid_t)atoi(p);
+      
+      pw.pw_gecos = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_dir = ++retp;
+      if ((retp = strchr(retp, ':')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+
+      pw.pw_shell = ++retp;
+      if ((retp = strchr(retp, '\n')) == NULL)
+	{
+	  fprintf(stderr, "virt_getpwnam: format error!\n");
+	  exit(1);
+	}
+      *retp = '\0';
+      
+      pw_current++;
+      
+      return(&pw);
+    }
+  else
+    {
+      return (NULL);
+    }
+}
+
+
+static void
+virt_setpwent(char *our_root)
+{
+  char pw_filename[PATH_MAX];
+
+  if ((our_root == NULL) || *our_root == '\0')
+    {
+      return(setpwent());
+    }
+  
+  pw_current = 0;
+
+  if (pw_file != NULL)
+    {
+      fclose(pw_file);
+      pw_file = NULL;
+    }
+
+  if (pw_file == NULL)
+    {
+      snprintf(pw_filename, PATH_MAX, "%s/etc/passwd", our_root);
+      if ((pw_file = fopen(pw_filename, "r")) == NULL)
+	{
+	  perror(pw_filename);
+	}
+    }
 }
