[comp.os.minix] programs using /etc/utmp

holm@ubc-bdcvax.UUCP (Terrence W. Holm) (02/11/89)

EFTH MINIX report #68  - February 1989 -  programs using /etc/utmp


Recently Peter Housel posted changes for login and init to write
to utmp, as well as to wtmp. I recommend applying these patches.
(GOOD WORK PETER!)

This posting includes updated versions of who(1), users(1)
and a patch to leave(1); these all use /etc/utmp now, instead
of /usr/adm/wtmp. Who(1) is much faster, and the other
commands benefit from cleaner code.

		Terrence W. Holm
		  holm@bdc.ubc.ca


----------------------------------------------------------
echo x - users.c
sed '/^X/s///' > users.c << '/'
X/*  users(1)           Author: Terrence W. Holm          Feb. 1989  */
X
X#include <stdio.h>
X#include <utmp.h>
X
X#ifndef  UTMP
X#define  UTMP   "/etc/utmp"
X#endif
X
X
Xint Strncmp( str1, str2 )
X  char *str1, *str2;
X  {
X  return( strncmp( str1, str2, 8 ) );
X  }
X
X
Xmain()
X  {
X  FILE   *f;
X  struct utmp login;
X  char   users[ 20 ][ 8 ];
X  int    user_count = 0, i;
X
X
X  if ( (f = fopen( UTMP, "r" )) == NULL )
X    /*  No login/logout records kept  */
X    exit( 0 );
X
X
X  while ( fread( &login, sizeof(struct utmp), 1, f ) == 1 )
X    {
X    if ( login.ut_name[0] != '\0' )
X      memcpy( users[ user_count++ ], login.ut_name, 8 );
X    }
X
X  qsort( users, user_count, 8, Strncmp );
X
X  for ( i = 0;  i < user_count - 1;  ++i )
X    printf( "%.8s ", users[ i ] );
X
X  if ( user_count > 0 )
X    printf( "%.8s\n", users[ user_count - 1 ] );
X
X  exit( 0 );
X  }
/
echo x - who.c
sed '/^X/s///' > who.c << '/'
X/*  who(1)           Author: Terrence W. Holm          Feb. 1989  */
X
X/*  who [file]
X *  who am i
X *
X * The user log-in name, terminal port and log-in time
X * are displayed for all users, or the current user.
X */
X
X#include <stdio.h>
X#include <utmp.h>
X
X#ifndef  UTMP
X#define  UTMP   "/etc/utmp"
X#endif
X
Xchar *ttyname();
X
X
Xmain( argc, argv )
X  int   argc;
X  char *argv[];
X
X  {
X  char *file   = UTMP;
X  char *whoami = ttyname(0) + 5;
X  int all_entries = 0;
X  int any_one = 1;
X  FILE   *f;
X  struct utmp entry;
X
X
X  if ( argc == 2 )
X    {
X    file = argv[1];
X    all_entries = 1;
X    }
X
X  else if ( argc == 3  &&  strcmp(argv[1],"am") == 0  &&
X     ( strcmp(argv[2],"i") == 0  ||  strcmp(argv[2],"I") == 0 ) )
X    any_one = 0;
X
X  else if ( argc > 2 )
X    {
X    fprintf( stderr, "Usage:  who [file]\n        who am i\n" );
X    exit( 1 );
X    }
X
X
X  if ( (f = fopen( file, "r" )) == NULL )
X    /*  No login/logout records kept  */
X    exit( 0 );
X
X
X  while ( fread( &entry, sizeof(struct utmp), 1, f ) == 1 )
X    {
X    if ( all_entries || entry.ut_name[0] != '\0' &&
X	  (any_one || strncmp( whoami, entry.ut_line, 8 ) == 0) )
X      printf( "%-8.8s  %-8.8s %.12s\n",
X        entry.ut_name, entry.ut_line, ctime( &entry.ut_time )+4 );
X    }
X
X  exit( 0 );
X  }
/
echo x - leave.c.cdif
sed '/^X/s///' > leave.c.cdif << '/'
X*** /usr/src/minix/commands/leave.c	Sun Feb  5 21:20:17 1989
X--- leave.c	Thu Feb  9 22:52:52 1989
X***************
X*** 10,23 ****
X  
X  #define  Min(a,b)  ((a<b) ? a : b)
X  
X! #ifndef  WTMP
X! #define  WTMP   "/usr/adm/wtmp"
X! #endif
X! 
X! #define  BUFFER_SIZE     1024	  /*  Room for wtmp records  */
X! #define  MAX_WTMP_COUNT  ( BUFFER_SIZE / sizeof(struct utmp) )
X! 
X! struct utmp  wtmp_buffer[ MAX_WTMP_COUNT ];
X  
X  #define  STRING	   80		/*  Lots of room for an argument  */
X  #define  MIN	   60L		/*  Seconds per minute		  */
X--- 10,18 ----
X  
X  #define  Min(a,b)  ((a<b) ? a : b)
X  
X! #ifndef  UTMP
X! #define  UTMP   "/etc/utmp"
X! #endif
X  
X  #define  STRING	   80		/*  Lots of room for an argument  */
X  #define  MIN	   60L		/*  Seconds per minute		  */
X***************
X*** 248,307 ****
X  
X    {
X    FILE  *f;
X!   long   size;		/*  Number of wtmp records in the file	*/
X!   int    wtmp_count;	/*  How many to read into wtmp_buffer	*/
X! 
X! 
X!   if( (f = fopen( WTMP, "r" )) == NULL )
X      /*  No login/logout records kept  */
X      return( 1 );
X  
X!   if ( fseek( f, 0L, 2 ) != 0  ||  (size = ftell(f)) % sizeof(struct utmp) !
= 0  )
X!     {
X!     fprintf( stderr, "leave: invalid wtmp file\n" );
X!     exit( 1 );
X!     }
X! 
X! 
X!   size /= sizeof(struct utmp);	/*  Number of records in wtmp	*/
X! 
X! 
X!   while( size > 0 )
X!     {
X!     wtmp_count = (int) Min( size, MAX_WTMP_COUNT );
X! 
X!     size -= (long) wtmp_count;
X! 
X!     fseek( f, size * sizeof(struct utmp), 0 );
X! 
X!     if ( fread( &wtmp_buffer[ 0 ], sizeof(struct utmp), wtmp_count, f ) != w
tmp_count )
X! 	{
X!     	fprintf( stderr, "leave: read error on wtmp file\n" );
X!     	exit( 1 );
X!     	}
X! 
X! 
X!     while ( --wtmp_count >= 0 )
X! 	{
X! 	if ( strcmp( wtmp_buffer[ wtmp_count ].ut_line, "~" ) == 0 )
X! 	  return( 0 );
X! 
X! 	if ( strncmp( wtmp_buffer[ wtmp_count ].ut_line, tty, 8 ) == 0 )
X!           if ( strncmp( wtmp_buffer[ wtmp_count ].ut_name, user, 8 ) == 0 )
X! 	    return( 1 );
X! 	  else
X! 	    return( 0 );
X! 	}
X! 
X!     }  /* end while( size > 0 ) */
X! 
X!   return( 0 );
X!   }
X! 
X! 
X! 
X! Usage()
X!   {
X!   fprintf( stderr, "Usage: leave [[+]hhmm]\n" );
X!   exit( 1 );
X!   }
X--- 243,271 ----
X  
X    {
X    FILE  *f;
X!   struct utmp login;
X! 
X!   if ( (f = fopen( UTMP, "r" )) == NULL )
X      /*  No login/logout records kept  */
X      return( 1 );
X  
X! 
X!   while ( fread( &login, sizeof(struct utmp), 1, f ) == 1 )
X!     {
X!     if ( strncmp( login.ut_line, tty, 8 ) == 0 )
X!           if ( strncmp( login.ut_name, user, 8 ) == 0 )
X! 	    return( 1 );
X! 	  else
X! 	    return( 0 );
X!     }
X! 
X!   return( 0 );
X!   }
X! 
X! 
X! 
X! Usage()
X!   {
X!   fprintf( stderr, "Usage: leave [[+]hhmm]\n" );
X!   exit( 1 );
X!   }
/
exit 0
----------------------------------------------------------