[gnu.emacs.bug] error in emcas

klein.muc@UUNET.UU.NET (10/13/89)

Wie Du weisst, habe ich vor einiger Zeit einen Fehler an die Leute von
GNU emacs gemeldet. Heute kam die Antwort. Im Folgenden - zu Deiner
Kenntnisnahme - die Korrespondenz:

Mein Brief vom 5. Oktober:
----------
Subject: bug in GNU emacs
--text follows this line--
a minor bug is integrated in our version 18.51 of GNU emacs:
When getting a shell and invoking "who am i" nothing happens.
The who command itself works fine, but "who am i" fails.
I would be glad to get an answer. Gottfried Klein (Munich)


Die Antwort:
----------
>From ai.mit.edu!jla.eunet Wed Oct 11 15:20 MET 1989 remote from NERV
From: unido!ai.mit.edu!jla (Joseph Arceneaux)
Date: Wed, 11 Oct 89 10:00:54 EDT
In-Reply-To: <8910051019.AL27323@unido.informatik.uni-dortmund.de> (unido!nixpbe!klein.muc@uunet.uu.net)
Subject: bug in GNU emacs

This `who' seems to work.  Let me know if it gives you problems;  I
just wrote it.
______________________________________________________________________________
/* GNU's who.
   Copyright (C) 1989 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 1, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by jla 10/89 */

#include <stdio.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>

#define O_RDONLY 0		/* from <fcntl.h> */
#define UTMP "/etc/utmp"

main (argc, argv, envp)
     int argc;
     char *argv[], *envp[];
{
  switch (argc)
    {
    case 1:			/* who */
      who (UTMP);
      break;

    case 2:			/* who <utmp file> */
      who (argv[1]);
      break;

    case 3:			/* who <blurf> <glop> */
      who_am_i ();
      break;

    default:			/* lose */
      fatal ("Usage: who [ who-file ] [ am i ]");
    }
}

static struct utmp *utmp_contents;

who (filename)
     char *filename;
{
  scan_entries (read_utmp (filename));
  exit (0);
}

int
read_utmp (filename)
     char *filename;
{
  register int desc;
  struct stat file_stats;
  register int n_entries;

  desc = open (filename, O_RDONLY, 0);
  if (desc <= 0)
    fatal ("Can't open file %s.", filename);

  fstat (desc, &file_stats);
  if (file_stats.st_size > 0)
    utmp_contents = (struct utmp *) malloc (file_stats.st_size);
  else
    fatal ("Empty utmp file.");

  if (read (desc, utmp_contents, file_stats.st_size) != file_stats.st_size)
    fatal ("Can't read proper size.");

  if (close (desc) != 0)
    fatal ("Can't close utmp file.");

  n_entries = file_stats.st_size / sizeof (struct utmp);
  if (n_entries * sizeof (struct utmp) != file_stats.st_size)
    fatal ("Non-integral number of utmp entries.");

  return n_entries;
}

char *asctime ();

scan_entries (n)
     int n;
{
  register struct utmp *this = utmp_contents;

  printf ("Name\t Line\t    From\n\n");
  while (n--)
    {
      if (this->ut_name[0])
	printf ("%01.8s\t%.8s\t%16.16s\t%.26s",
		this->ut_name, this->ut_line, this->ut_host,
		asctime (localtime (&this->ut_time)));
      this++;
    }
}

struct utmp
*search_entries (n, name)
     int n;
     char *name;
{
  register struct utmp *this = utmp_contents;

  while (n--)
    {
      if (this->ut_name[0] && !strcmp (name, this->ut_name))
	return this;
      this++;
    }
  return (struct utmp *) NULL;
}

who_am_i ()
{
  register struct passwd *id_entry;
  register struct utmp *utmp_entry;
  char hostname[64];

  if (gethostname (hostname, 64))
    {
      bcopy ("<unknown>", hostname, 9);
      hostname[10] = 0;
    }

  id_entry = getpwuid (getuid ());
  if (id_entry == (struct passwd *) NULL)
    fatal ("You are a stowaway!");
  printf ("%s!%s      ", hostname, id_entry->pw_name);

  utmp_entry = search_entries (read_utmp (UTMP), id_entry->pw_name);
  if (utmp_entry != (struct utmp *) NULL)
    {
      char *time;

      time = asctime (localtime (&utmp_entry->ut_time));
      time[strlen (time) - 5] = 0;
      printf ("%.8s   %.26s  (%.16s)\n",
	      utmp_entry->ut_line, &time[4], utmp_entry->ut_host);
    }

  exit (0);
}

fatal (str, name)
     char *str, *name;
{
  fprintf (stderr, str, name);
  exit (1);
}

klein.muc@UUNET.UU.NET (10/13/89)

Wie Du weisst, habe ich vor einiger Zeit einen Fehler an die Leute von
GNU emacs gemeldet. Heute kam die Antwort. Im Folgenden - zu Deiner
Kenntnisnahme - die Korrespondenz:

Mein Brief vom 5. Oktober:
----------
Subject: bug in GNU emacs
--text follows this line--
a minor bug is integrated in our version 18.51 of GNU emacs:
When getting a shell and invoking "who am i" nothing happens.
The who command itself works fine, but "who am i" fails.
I would be glad to get an answer. Gottfried Klein (Munich)


Die Antwort:
-----------
>From ai.mit.edu!jla.eunet Wed Oct 11 15:20 MET 1989 remote from NERV
From: unido!ai.mit.edu!jla (Joseph Arceneaux)
Date: Wed, 11 Oct 89 10:00:54 EDT
In-Reply-To: <8910051019.AL27323@unido.informatik.uni-dortmund.de> (unido!nixpbe!klein.muc@uunet.uu.net)
Subject: bug in GNU emacs

This `who' seems to work.  Let me know if it gives you problems;  I
just wrote it.
______________________________________________________________________________
/* GNU's who.
   Copyright (C) 1989 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 1, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by jla 10/89 */

#include <stdio.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>

#define O_RDONLY 0		/* from <fcntl.h> */
#define UTMP "/etc/utmp"

main (argc, argv, envp)
     int argc;
     char *argv[], *envp[];
{
  switch (argc)
    {
    case 1:			/* who */
      who (UTMP);
      break;

    case 2:			/* who <utmp file> */
      who (argv[1]);
      break;

    case 3:			/* who <blurf> <glop> */
      who_am_i ();
      break;

    default:			/* lose */
      fatal ("Usage: who [ who-file ] [ am i ]");
    }
}

static struct utmp *utmp_contents;

who (filename)
     char *filename;
{
  scan_entries (read_utmp (filename));
  exit (0);
}

int
read_utmp (filename)
     char *filename;
{
  register int desc;
  struct stat file_stats;
  register int n_entries;

  desc = open (filename, O_RDONLY, 0);
  if (desc <= 0)
    fatal ("Can't open file %s.", filename);

  fstat (desc, &file_stats);
  if (file_stats.st_size > 0)
    utmp_contents = (struct utmp *) malloc (file_stats.st_size);
  else
    fatal ("Empty utmp file.");

  if (read (desc, utmp_contents, file_stats.st_size) != file_stats.st_size)
    fatal ("Can't read proper size.");

  if (close (desc) != 0)
    fatal ("Can't close utmp file.");

  n_entries = file_stats.st_size / sizeof (struct utmp);
  if (n_entries * sizeof (struct utmp) != file_stats.st_size)
    fatal ("Non-integral number of utmp entries.");

  return n_entries;
}

char *asctime ();

scan_entries (n)
     int n;
{
  register struct utmp *this = utmp_contents;

  printf ("Name\t Line\t    From\n\n");
  while (n--)
    {
      if (this->ut_name[0])
	printf ("%01.8s\t%.8s\t%16.16s\t%.26s",
		this->ut_name, this->ut_line, this->ut_host,
		asctime (localtime (&this->ut_time)));
      this++;
    }
}

struct utmp
*search_entries (n, name)
     int n;
     char *name;
{
  register struct utmp *this = utmp_contents;

  while (n--)
    {
      if (this->ut_name[0] && !strcmp (name, this->ut_name))
	return this;
      this++;
    }
  return (struct utmp *) NULL;
}

who_am_i ()
{
  register struct passwd *id_entry;
  register struct utmp *utmp_entry;
  char hostname[64];

  if (gethostname (hostname, 64))
    {
      bcopy ("<unknown>", hostname, 9);
      hostname[10] = 0;
    }

  id_entry = getpwuid (getuid ());
  if (id_entry == (struct passwd *) NULL)
    fatal ("You are a stowaway!");
  printf ("%s!%s      ", hostname, id_entry->pw_name);

  utmp_entry = search_entries (read_utmp (UTMP), id_entry->pw_name);
  if (utmp_entry != (struct utmp *) NULL)
    {
      char *time;

      time = asctime (localtime (&utmp_entry->ut_time));
      time[strlen (time) - 5] = 0;
      printf ("%.8s   %.26s  (%.16s)\n",
	      utmp_entry->ut_line, &time[4], utmp_entry->ut_host);
    }

  exit (0);
}

fatal (str, name)
     char *str, *name;
{
  fprintf (stderr, str, name);
  exit (1);
}