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