[comp.os.minix] Improved WHO

nick@nswitgould.OZ (Nick Andrew) (10/13/88)

	I have made one improvement and one BUGFIX to who(1) 1.3b. The new
who.c follows the descriptions.

BUGFIX:
	The wtmp file contains 8-character Name and Line fields. For an 8
character (or longer) userid, the Name field is not null terminated.
This breaks Who - it prints junk after the name. Who.c uses
  printf("%s ...",w->wt_name)
which is a no-no. I have fixed who so it can handle this OK.

	Note: login.c compiled with the 1.2 getenv.c would corrupt the first
byte of the tty field of the wtmp file whenever an 8 character userid logged on.

IMPROVEMENT:
	Who now understands an optional filename argument. When this
argument is given Who reads the file and prints out all records. This is
the same as 4.2bsd Who, I don't know about V7 (don't own a manual).

	I have refrained from adding the "who am i" feature to Who, as in
4.2, because Minix already has whoami(1).

	The complete source is provided, as the diff is nearly as long anyway.

-------------------------------- hack here ---------------------------------
echo x - who.c
sed '/^X/s///' > who.c << '/'
X/* who - tell who is currently logged in	Author: Andy Tanenbaum
X * Modified:
X *	allow usage: who [filename]  to print entire file's contents
X *	fix bug with 8-character login names	(nick@nswitgould.oz)
X */
X
X/* Who reads the file /usr/adm/wtmp and prints a list of who is curently
X * logged in.  The format of this file is a sequence of 20-character records,
X * as defined by struct wtmprec below.  There is an implicit assumption that
X * all terminal names are of the form ttyn, where n is a single decimal digit.
X */
X
X#include <stdio.h>
X
X#define SLOTS   10
X#define WTMPSIZE 8
X#define DIGIT    3
X
Xchar *fn, *wtmpfile = "/usr/adm/wtmp";
Xint	fromfile = 0;
Xchar name[WTMPSIZE+1], line[WTMPSIZE+1];
X
Xstruct wtmprec {
X  char wt_line[WTMPSIZE];	/* tty name */
X  char wt_name[WTMPSIZE];	/* user id */
X  long wt_time;			/* time */
X} wtmp;
X
Xstruct wtmprec user[SLOTS];
Xextern char *ctime();
X
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X  int fd;
X
X  noperprintf(stdout);		/* yuk */
X  name[WTMPSIZE] = line[WTMPSIZE] = 0;
X
X  if (argc==2) {
X	fromfile = 1;
X	fn = argv[1];
X  }
X
X  fd = open(fromfile ? fn : wtmpfile, 0);
X  if (fd < 0) {
X	printf("The file %s cannot be opened.\n", fromfile ? fn : wtmpfile);
X	if (!fromfile) printf("To enable login accounting (required by who),");
X	if (!fromfile) printf("create an empty file with this name.\n");
X	exit(1);
X  }
X
X  if (fromfile)
X	readprint(fd);
X  else {
X	readwtmp(fd);
X	printwtmp();
X  }
X}
X
X
Xreadwtmp(fd)
Xint fd;
X{
X/* Read the /usr/adm/wtmp file and build up a log of current users. */
X
X  int i, ttynr;
X
X  while (read(fd, &wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
X	if (strcmp(wtmp.wt_line, "~") == 0) {
X		/* This line means that the system was rebooted. */
X		for (i = 0; i < SLOTS; i++) user[i].wt_line[0] = 0;
X		continue;
X	}
X	ttynr = wtmp.wt_line[DIGIT] - '0';
X	if (ttynr < 0 || ttynr >= SLOTS) continue;
X	if (wtmp.wt_name[0] == 0) {
X		user[ttynr].wt_line[0] = 0 ;
X		continue;
X	}
X	user[ttynr] = wtmp;
X  }
X}
X
Xprintwtmp()
X{
X  struct wtmprec *w;
X  char *p;
X
X  for (w = &user[0]; w < &user[SLOTS]; w++) {
X	if (w->wt_line[0] == 0) continue;
X	padnprint(w);
X  }
X}
X
Xreadprint(fd)
Xint fd;
X{
X  /* Read the who-format file and print all entries. */
X
X  while (read(fd, &wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
X	padnprint(&wtmp);
X  }
X}
X
Xpadnprint(w)
Xstruct wtmprec *w;
X{
X  char *p;
X  int  i;
X
X  p = w->wt_name;
X  for (i=0; i<8 && *p;) name[i++] = *(p++);
X  while (i < 8) name[i++] = ' ';
X  p = w->wt_line;
X  for (i=0; i<8 && *p;) line[i++] = *(p++);
X  while (i < 8) line[i++] = ' ';
X  printf("%s %s ", name, line);
X  p = ctime(&w->wt_time);
X  *(p+16) = 0;
X  printf("%s\n", p);
X}
/
exit 0

allbery@ncoast.UUCP (Brandon S. Allbery) (10/23/88)

As quoted from <9535@nswitgould.OZ> by nick@nswitgould.OZ (Nick Andrew):
+---------------
| 	I have refrained from adding the "who am i" feature to Who, as in
| 4.2, because Minix already has whoami(1).
+---------------

Ummm, "whoami" displays the current suid user name, whereas "who am i" prints
the login name.  At least that's the way it works in BSD and those System V's
that have "whoami" (and our System III version).  I think "who am i" is a
good idea, unless you prefer PWB "logname".

++Brandon
-- 
Brandon S. Allbery, comp.sources.misc moderator and one admin of ncoast PA UN*X
uunet!hal.cwru.edu!ncoast!allbery  <PREFERRED!>	    ncoast!allbery@hal.cwru.edu
allbery@skybridge.sdi.cwru.edu	      <ALSO>		   allbery@uunet.uu.net
comp.sources.misc is moving off ncoast -- please do NOT send submissions direct
  (But the aliases are NOT on UUNET yet, use the aliases at backbone sites!)