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
----------------------------------------------------------